Tại sao nên sử dụng Hệ thống bản dựng?

Báo cáo sự cố Xem nguồn

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 hệ thống xây dựng, và lý do các trình biên dịch cũng như tập lệnh bản dựng không phải là lựa chọn tốt nhất khi tổ chức của bạn bắt đầu mở rộng quy mô. Nội dung này dành cho các nhà phát triển không có nhiều kinh nghiệm về 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ột mục đích đơn giản: chúng chuyển đổi mã nguồn do kỹ sư viết thành các tệp nhị phân có thể thực thi mà máy có thể đọc được. Hệ thống xây dựng không chỉ dành cho mã do con người tạo, chúng còn cho phép máy tự động tạo các bản dựng, cho dù để thử nghiệm hay để phát hành chính thức. Trong một tổ chức có hàng nghìn kỹ sư, 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 tạo ra.

Tôi có thể chỉ dùng trình biên dịch không?

Nhu cầu về 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 cách 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 ngay từ dòng lệnh hoặc tương đương trong môi trường phát triển tích hợp (IDE). Miễn là tất cả mã nguồn nằm trong cùng một thư mục, lệnh như sau 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 thư mục hiện tại và chuyển tệp đó thành tệp lớp nhị phân. Trong trường hợp đơn giản nhất, đây là 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 để xem trong các thư mục con của thư mục hiện tại nhằm tìm mã để nhập. Tuy nhiên, phương thức này 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à một thư viện dùng chung cho một số dự án). Nó cũng chỉ biết cách tạo mã Java. Các hệ thống lớn thường liên quan đến các phần khác nhau được viết bằng nhiều ngôn ngữ lập trình có web gồm các phần phụ thuộc, nghĩa là không có trình biên dịch nào cho một ngôn ngữ có thể xây dựng toàn bộ hệ thống.

Khi bạn đang xử lý mã từ nhiều ngôn ngữ hoặc nhiều đơn vị biên dịch, việc tạo mã không còn là quá trình một bước nữa. Bây giờ, bạn phải đánh giá nội dung mà mã của mình phụ thuộc và tạo các phần đó theo thứ tự phù hợp, có thể sử dụng một bộ công cụ riêng cho từng phần. 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ó kích thước vừa phải, quá trình này sẽ 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ý các phần phụ thuộc bên ngoài, 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ý việc này bằng cách tải phần phụ thuộc xuống từ Internet, dán phần phụ thuộc đó vào một 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, rất khó để duy trì các 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.

Tập lệnh shell thì sao?

Giả sử dự án sở thích của bạn bắt đầu đủ đơn giản để bạn có thể tạo dự án chỉ bằng trình biên dịch, nhưng bạn bắt đầu gặp phải một số vấn đề được mô tả trước đó. Có thể bạn vẫn chưa nghĩ rằng mình cần một hệ thống xây dựng và có thể tự động hoá 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 để đảm nhiệm việc xây dựng mọi thứ theo đúng thứ tự. Điều này sẽ giúp ích trong một thời gian, nhưng khá sớm bạn bắt đầu gặp phải nhiều vấn đề hơn:

  • Điều đó sẽ trở nên tẻ nhạt. Khi hệ thống ngày càng phức tạp, bạn bắt đầu dành gần như nhiều thời gian để xử lý các tập lệnh bản dựng như trên mã thực. Việc gỡ lỗi các tập lệnh môi trường shell sẽ rất khó khăn, do ngày càng có nhiều vụ tấn công bị xếp chồng lên nhau.

  • Trang web chạy chậm. Để đảm bảo không vô tình phụ thuộc vào thư viện cũ, bạn cần xây dựng tập lệnh bản dựng cho mọi phần phụ thuộc theo thứ tự mỗi khi bạn chạy. Bạn đang nghĩ đến việc thêm một số logic để phát hiện những phần cần xây dựng lại, nhưng nghe có vẻ rất phức tạp và dễ xảy ra lỗi đối với tập lệnh. Hoặc bạn nghĩ về việc chỉ định các phần cần xây dựng lại mỗi, nhưng sau đó bạn quay lại hình vuông.

  • Tin vui! Đã đến lúc phát hành! Tốt hơn hết, bạn hãy tìm ra tất cả đối số cần thiết để truyền vào lệnh jar để tạo bản dựng cuối cùng. Đồng thời, hãy nhớ cách tải lên và đẩy tệp lên kho lưu trữ trung tâm. Và tạo và đẩy bản cập nhật tài liệu cũng như gửi thông báo cho người dùng. Rất tiếc, có thể lệnh gọi này cho một tập lệnh khác...

  • Thảm hoạ! Ổ đĩa cứng 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ữ cho tất cả các tệp nguồn kiểm soát phiên bản, nhưng còn các thư viện bạn đã tải xuống thì sao? Bạn có thể tìm lại tất cả các tệp và đảm bảo rằng chúng giống phiên bản khi bạn tải xuống lần đầu không? Tập lệnh của bạn có thể phụ thuộc vào các công cụ cụ thể đượ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 hoạt động lại không? Còn tất cả những biến môi trường mà bạn thiết lập từ lâu để giúp trình biên dịch hoạt động đúng cách rồi quên mất?

  • Mặc dù có vấn đề, dự án của bạn vẫn đủ thành công để bạn có thể bắt đầu tuyển dụng thêm kỹ sư. Giờ đây, bạn đã nhận ra rằng không có thảm họa nào xảy ra để các vấn đề trước đó phát sinh — bạn cần trải qua quy trình khởi động khó khăn tương tự mỗi khi một nhà phát triển mới tham gia vào nhóm của bạn. Và mặc dù bạn đã cố gắng hết sức, nhưng hệ thống của mỗi người vẫn có sự khác biệt nhỏ. Thông thường, những gì hoạt động trên máy của một người không hoạt động trên một máy khác và mỗi lần phải mất vài giờ để gỡ lỗi đường dẫn của công cụ hoặc phiên bản thư viện để tìm ra điểm khác biệt.

  • Bạn quyết định rằng bạn cần tự động hoá hệ thống xây dựng. Về lý thuyết, việc này cũng đơn giản như việc lấy một máy tính mới và thiết lập máy tính đó để chạy tập lệnh bản dựng mỗi đêm bằng cách sử dụng cron. Bạn vẫn phải trải qua quá trình thiết lập khó khăn, nhưng giờ đây bạn không có lợi ích cho bộ não con người là có thể phát hiện và giải quyết các vấn đề nhỏ. Bây giờ, mỗi sáng khi bạn vào cửa, bạn thấy 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 trên hệ thống của họ nhưng không hoạt động trên hệ thống xây dựng tự động. Mỗi lần đó là một bản sửa lỗi đơn giản, nhưng nó xảy ra thường xuyên đến mức bạn phải 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 đơn giản đó.

  • Các bản dựng trở nên chậm hơn và chậm hơn khi dự án phát triển. Một ngày nọ, trong khi đợi quá trình tạo bản dựng hoàn tất, bạn lo lắng nhìn vào chiếc máy tính nhàn rỗi của đồng nghiệp đang đi nghỉ và ước gì có cách để tận dụng tất cả sức mạnh tính toán lãng phí này.

Bạn đã gặp phải một vấn đề kinh điển trên quy mô lớn. Đối với một nhà phát triển làm việc tối đa vài trăm dòng mã trong tối đa một hoặc hai tuần (có thể là toàn bộ trải nghiệm của một nhà phát triển cơ sở mới tốt nghiệp đại học), họ sẽ cần một trình biên dịch. Tập lệnh có thể đưa bạn đến nơi khác hơn một chút. Tuy nhiên, ngay khi bạn cần phối hợp giữa nhiều nhà phát triển và máy của họ, ngay cả một tập lệnh bản dựng hoàn hảo cũng chưa đủ vì nó trở nên rất khó khăn để có thể giải thích được những khác biệt nhỏ trong các máy đó. Tại thời điểm này, phương pháp đơn giản này sẽ gây lỗi và đã đến lúc bạn đầu tư vào một hệ thống xây dựng thực sự.