Trang này thảo luận về hệ thống xây dựng là gì, chức năng của chúng, lý do bạn nên sử dụng và tại sao trình biên dịch và tập lệnh bản dựng không phải là lựa chọn tốt nhất làm lựa chọn tổ chức của bạn bắt đầu mở rộng quy mô. Sản phẩm này dành cho những nhà phát triển chưa có nhiều với hệ thống xây dựng.
Hệ thống xây dựng là gì?
Về cơ bản, tất cả các hệ thống xây dựng đều có mục đích đơn giản: chúng biến đổi mã nguồn do các kỹ sư viết vào các tệp nhị phân có thể thực thi và đọc được theo máy. Hệ thống xây dựng không chỉ dành cho mã do con người tạo; chúng cũng cho phép để tạo các bản dựng tự động, cho dù là dành cho mục đích kiểm thử hay phát hành để sản xuất. Trong một tổ chức có hàng nghìn kỹ sư, thông thường thì hầu hết các bản dựng được kích hoạt tự động thay vì do các kỹ sư trực tiếp kích hoạt.
Tôi không thể chỉ sử dụng một trình biên dịch phải không?
Nhu cầu xây dựng một hệ thống xây dựng có thể không rõ ràng ngay lập tức. Hầu hết các kỹ sư
không sử dụng hệ thống xây dựng trong khi học lập trình: hầu hết bắt đầu bằng cách gọi các công cụ
như gcc
hoặc javac
trực tiếp từ dòng lệnh hoặc tương đương trong một
môi trường phát triển tích hợp (IDE). Miễn là tất cả các mã nguồn nằm trong
cùng một thư mục, lệnh như thế này sẽ hoạt động tốt:
javac *.java
Thao tác này sẽ hướng dẫn trình biên dịch Java lấy mọi tệp nguồn Java trong và chuyển thư mục đó thành tệp lớp nhị phân. Trong trường hợp đơn giản nhất, tất cả những gì bạn cần.
Tuy nhiên, ngay khi mã mở rộng, các chức năng sẽ bắt đầu. javac
thông minh
đủ để tìm trong các thư mục con của thư mục hiện tại nhằm tìm mã
nhập. Nhưng nó không có cách nào để tìm mã được lưu trữ trong các phần khác của
hệ thống tệp (có thể là thư viện được một số dự án dùng chung). Trợ lý cũng chỉ biết
cách xây dựng mã Java. Các hệ thống lớn thường liên quan đến nhiều phần được viết bằng
nhiều ngôn ngữ lập trình với mạng lưới phụ thuộc giữa các phần đó,
nghĩa là không có trình biên dịch nào cho một ngôn ngữ duy nhất có thể xây dựng toàn bộ hệ thống.
Khi bạn xử lý mã từ nhiều ngôn ngữ hoặc nhiều quá trình biên dịch đơn vị, mã tòa nhà không còn là quy trình một bước. Giờ bạn phải đánh giá xem mã của bạn phụ thuộc vào và tạo các phần đó theo thứ tự thích hợp, có thể sử dụng một bộ công cụ khác nhau cho từng sản phẩm. Nếu có phần phụ thuộc nào thay đổi, bạn phải lặp lại quy trình này để tránh phụ thuộc vào các tệp nhị phân cũ. Đối với cơ sở mã của có kích thước vừa phải thì quá trình này nhanh chóng trở nên tẻ nhạt và dễ xảy ra lỗi.
Trình biên dịch cũng không biết gì về cách xử lý dữ liệu bên ngoài
các phần phụ thuộc, chẳng hạn như tệp JAR
của bên thứ ba trong Java. Nếu không có hệ thống xây dựng,
bạn có thể quản lý vấn đề này
bằng cách tải phần phụ thuộc xuống từ Internet,
tệp đó vào thư mục lib
trên ổ đĩa cứng và định cấu hình trình biên dịch để đọc
các thư viện từ thư mục đó. Theo thời gian, khó có thể duy trì
bản cập nhật, phiên bản và nguồn của các phần phụ thuộc bên ngoài này.
Còn tập lệnh shell thì sao?
Giả sử rằng dự án sở thích của bạn bắt đầu đủ đơn giản để bạn có thể xây dựng chỉ dùng một trình biên dịch, nhưng bạn sẽ bắt đầu gặp phải một số vấn đề được mô tả trước đây. Có thể bạn vẫn không cho rằng mình cần một hệ thống xây dựng và có thể tự động hoá loại bỏ những phần tẻ nhạt bằng cách sử dụng một số tập lệnh shell đơn giản giúp sắp xếp mọi thứ theo đúng thứ tự. Việc này sẽ có tác dụng một lúc, nhưng khá thì bạn sẽ sớm gặp phải nhiều vấn đề hơn nữa:
Việc này trở nên tẻ nhạt. Khi hệ thống của bạn trở nên phức tạp hơn, bạn bắt đầu chi tiêu tương đương với thời gian xử lý tập lệnh bản dựng giống như trên mã thực. Gỡ lỗi tập lệnh shell rất khó khăn, với ngày càng nhiều vụ tấn công được xếp chồng lên nhau.
Công cụ này chậm. Để đảm bảo bạn không vô tình dựa vào thư viện cũ, bạn có tập lệnh bản dựng tạo mọi phần phụ thuộc để mỗi khi bạn chạy ứng dụng đó. Bạn cân nhắc thêm một số logic để phát hiện những phần cần được được xây dựng lại, nhưng điều đó nghe có vẻ cực kỳ phức tạp và dễ gặp lỗi đối với tập lệnh. Hoặc bạn suy nghĩ về việc chỉ định phần nào cần được xây dựng lại mỗi lần, nhưng thì bạn sẽ quay lại ô vuông.
Tin vui: đã đến lúc phát hành! Tốt hơn là tìm ra tất cả các đối số bạn cần chuyển lệnh jar để tạo bản dựng cuối cùng. Và hãy nhớ cách tải lên và đẩy tệp vào kho lưu trữ trung tâm. Đồng thời xây dựng và đẩy bản cập nhật tài liệu và gửi thông báo cho người dùng. Hừm, có thể lệnh này gọi một tập lệnh khác...
Thảm hoạ! Ổ đĩa cứng của bạn gặp sự cố và bây giờ, bạn cần tạo lại toàn bộ hệ thống. Bạn đã đủ thông minh để giữ tất cả các tệp nguồn của mình ở cùng một phiên bản nhưng còn các thư viện mà bạn đã tải xuống thì sao? Bạn có tìm thấy chúng không và đảm bảo chúng giống với phiên bản lúc bạn đầu tiên đã tải xuống chưa? Tập lệnh của bạn có thể phụ thuộc vào các công cụ cụ thể đang được được cài đặt ở những vị trí cụ thể—bạn có thể khôi phục cùng một môi trường đó để các tập lệnh có hoạt động trở lại không? Tất cả các biến môi trường mà bạn đặt từ lâu để trình biên dịch hoạt động hiệu quả rồi quên mất?
Mặc dù gặp phải các vấn đề nhưng dự án của bạn đủ thành công để bạn có thể hãy bắt đầu thuê thêm kỹ sư. Giờ đây, bạn nhận ra rằng không hề dễ dàng để những vấn đề trước đó phát sinh—bạn phải trải qua quá trình tự khởi động mỗi khi có nhà phát triển mới tham gia nhóm của bạn. và bất kể bạn đã nỗ lực hết sức, nhưng vẫn có những khác biệt nhỏ giữa mỗi lên hệ thống của một người. Thông thường, những tính năng hoạt động trên máy của một người lại không hoạt động trên một thiết bị khác và mỗi lần phải mất vài giờ đường dẫn công cụ gỡ lỗi hoặc các phiên bản thư viện khác để xác định sự khác biệt.
Bạn quyết định rằng mình cần tự động hoá hệ thống xây dựng. Trên lý thuyết, đây là đơn giản như mua một máy tính mới và thiết lập máy tính đó để chạy bản dựng tập lệnh mỗi đêm bằng cron. Bạn vẫn cần vượt qua giai đoạn đau khổ này quá trình thiết lập, nhưng giờ đây bạn không có được bộ não con người có thể phát hiện và giải quyết các vấn đề nhỏ. Giờ đây, mỗi sáng khi bạn vào, bạn thấy rằng bản dựng tối qua không thành công vì hôm qua một nhà phát triển đã thực hiện một thay đổi có hiệu quả trên hệ thống của họ nhưng không hiệu quả với hệ thống xây dựng. Mỗi lần khắc phục là vấn đề đơn giản, nhưng việc này xảy ra thường xuyên đến mức bạn và dành rất nhiều thời gian mỗi ngày để khám phá và áp dụng những bản sửa lỗi.
Các bản dựng sẽ càng chậm lại khi dự án tăng lên. Một ngày, trong khi chờ khi quá trình tạo bản dựng hoàn tất, bạn nhìn thê thiết nhìn vào màn hình máy tính là đồng nghiệp đang đi nghỉ và ước gì có cách nào đó để tận dụng tất cả những năng lượng tính toán lãng phí.
Bạn đã gặp một bài toán kinh điển về quy mô. Đối với một nhà phát triển làm việc tại tối đa vài trăm dòng mã trong tối đa một hoặc hai tuần (có thể có là toàn bộ trải nghiệm của một nhà phát triển trẻ mới tốt nghiệp từ trước đến nay trường đại học), một trình biên dịch là tất cả những gì bạn cần. Kịch bản có thể khiến bạn mất một chút thời gian xa hơn. Nhưng ngay khi bạn cần điều phối giữa nhiều nhà phát triển và máy móc của họ, thậm chí một tập lệnh bản dựng hoàn hảo là chưa đủ bởi vì nó trở nên khó có thể giải thích được những khác biệt nhỏ trong những máy đó. Tại thời điểm này, cách tiếp cận đơn giản này sẽ bị chia nhỏ và đã đến lúc đầu tư vào một hệ thống xây dựng thực tế.