Làm thế nào để tái cấu trúc khi tất cả sự phát triển của bạn là trên các chi nhánh?


24

Tại công ty của tôi, tất cả sự phát triển của chúng tôi (sửa lỗi và các tính năng mới) được thực hiện trên các chi nhánh riêng biệt. Khi nó hoàn thành, chúng tôi gửi nó cho QA, người kiểm tra nó trên nhánh đó và khi chúng bật đèn xanh, chúng tôi hợp nhất nó vào nhánh chính của chúng tôi. Điều này có thể mất bất cứ nơi nào giữa một ngày và một năm.

Nếu chúng ta cố gắng siết chặt bất kỳ cấu trúc lại nào trên một nhánh, chúng ta sẽ không biết nó sẽ "ra ngoài" trong bao lâu, vì vậy nó có thể gây ra nhiều xung đột khi nó được hợp nhất trở lại.

Ví dụ: giả sử tôi muốn đổi tên một hàm vì tính năng tôi đang sử dụng đang sử dụng rất nhiều chức năng này và tôi thấy rằng tên của nó không thực sự phù hợp với mục đích của nó (một lần nữa, đây chỉ là một ví dụ). Vì vậy, tôi đi khắp nơi và tìm mọi cách sử dụng chức năng này, và đổi tên tất cả chúng thành tên mới của nó, và mọi thứ hoạt động hoàn hảo, vì vậy tôi gửi nó cho QA.

Trong khi đó, sự phát triển mới đang diễn ra và chức năng được đổi tên của tôi không tồn tại trên bất kỳ nhánh nào đang bị rẽ nhánh chính. Khi vấn đề của tôi được hợp nhất trở lại, tất cả sẽ tan vỡ.

Có cách nào để đối phó với điều này?

Nó không giống như quản lý sẽ phê duyệt một vấn đề chỉ tái cấu trúc để nó phải được xử lý với các công việc khác. Nó không thể được phát triển trực tiếp trên main vì tất cả các thay đổi đều phải trải qua QA và không ai muốn trở thành kẻ phá vỡ chính để anh ta có thể thực hiện một chút tái cấu trúc không cần thiết.


Bạn đang sử dụng kiểm soát phiên bản nào? Có nhiều cách tiếp cận khác nhau cho DVCS và mô hình máy chủ tập trung. Hơn nữa, các ngành phát triển đang được đưa ra là gì? Nếu một nhánh tính năng được chấp nhận, làm thế nào để các nhánh dev khác nhận các thay đổi?

2
Bên cạnh đó, một sơ đồ của cấu trúc phân nhánh hiện tại có thể thực sự hữu ích. Hoàn toàn có thể là nguyên nhân của vấn đề khó khăn trong việc tái cấu trúc một phần là do một số ... chính sách phân nhánh độc đáo (xem lập trình viên.stackexchange.com /questions / 210360 để biết một ví dụ như vậy). Tôi cũng đề nghị đọc vance.com/steve/perforce/Branching_Strargeties.html để có một số ý tưởng và nền tảng (nếu tôi có thể trả lời câu hỏi này sẽ là một điểm tham chiếu chính).

1
Đoạn cuối tổng hợp nó - nếu Doanh nghiệp không nhận thức được giá trị thì không có cách nào một nhà tái cấu trúc chính có thể đi trước. Bạn cần phải làm việc với nhóm thử nghiệm của mình để giải quyết các mốc thời gian của họ. (Tôi nghi ngờ QA của bạn thực sự là Thử nghiệm kéo (Họ đặt một bộ tóc giả và son môi và giả vờ là một thứ gì đó mà họ không phải). Một nhóm QA thực sự sẽ nói với bạn những gì cần tái cấu trúc, không theo cách của bạn.)
mattnz

1
@mattnz: Bạn hoàn toàn đúng. Họ không phải là một đội QA thực sự. Họ chủ yếu là hỗ trợ khách hàng. Tôi nghĩ rằng rất nhiều trách nhiệm của họ nên được chuyển lại cho nhóm Dev vì đơn giản là họ không thể xử lý mọi thứ chúng tôi đổ cho họ, nhưng đó là vấn đề quản lý và là trận chiến tôi chưa chiến thắng.
mở

3
Bạn đã bỏ lỡ đào của tôi. Kiểm tra! = QA. QA giám sát chất lượng và nhằm mục đích cải thiện kết quả kinh doanh. Thử nghiệm để chứng minh sự vắng mặt của khuyết tật bằng cách tìm thấy chúng.
mattnz

Câu trả lời:


12

Có một số vấn đề đang trộn lẫn với nhau để khiến việc tái cấu trúc trở nên khó khăn trong môi trường này. Trộn lẫn với điều này là một số vấn đề phi kỹ thuật ("nhưng đó là vấn đề quản lý và trận chiến tôi chưa chiến thắng").

Vấn đề đầu tiên cần xem xét là nhánh chạy dài. Các chi nhánh này gặp khó khăn với việc theo dõi các thay đổi bên ngoài quan điểm của nhà phát triển. Để giải quyết vấn đề này:

  • Khi mã hoàn tất - hãy thử lại một lần (hãy để bộ phận hỗ trợ khách hàng xem xét nếu họ muốn), nhưng nhanh chóng hợp nhất để phát triển để những thay đổi khác phụ thuộc vào nó sẽ có thể được chọn và những thay đổi đó được xác định sớm trong quá trình.
  • Nếu, vì một lý do nào đó, một brach sẽ hoạt động lâu trong khi tái cấu trúc đang diễn ra, nó có xu hướng được thực hiện tốt để hợp nhất từ ​​ổn định vào chi nhánh để nhận các thay đổi và tái cấu trúc. Thông thường, điều này giảm thiểu xung đột và bất ngờ khi hợp nhất từ ​​nhánh tính năng thành nhánh ổn định.
  • Tất cả các thử nghiệm tích hợp cần phải được thực hiện trên các bản phát hành - không phải tính năng . Trong môi trường này, các tính năng có thể hoặc không thể được tích hợp hoàn toàn với hệ thống. Mặc dù có thể thực hiện kiểm tra độ tỉnh táo đối với tính năng này, nhưng nó không xác định được các vấn đề khi phát hành.
  • Từ thời điểm hoàn thành mã để hợp nhất thành (hãy gọi nó là phát triển - phân nhánh từ chính / ổn định / phát hành có vấn đề riêng của việc không chọn các thay đổi phát triển mới nhất) không nên quá dài. Bạn càng chờ lâu, càng mất nhiều kiến ​​thức và mã càng khó tích hợp với các dòng mã khác.

Một vấn đề khác được đưa vào đây là tôi đã ám chỉ đến những điểm trên là vai trò thay đổi của chi nhánh theo thời gian. Nó bắt đầu như một nhánh phát triển nơi các nhà phát triển cam kết và sau đó trở thành một khu vực thử nghiệm (thử nghiệm nào đang được thực hiện ở đây có thể có ý nghĩa trong toàn bộ ứng dụng?), Sau đó được sáp nhập vào ổn định (và có lẽ được phát hành - phải không kiểm tra lại?).

Với một tính năng ngắn hơn bắt đầu để kết thúc thời gian, việc tái cấu trúc có thể được các nhánh khác chọn dễ dàng hơn.

Khuyến khích các nhà phát triển để có được toàn bộ môi trường. Chỉ cần thay đổi chọn anh đào có thể dẫn đến ... giả sử môi trường nhà phát triển thú vị. Mặc dù việc hái anh đào có công dụng của nó, nhưng đó là chế độ mặc định để kéo các thay đổi vào một nhánh có thể đáng lo ngại.

Tái cấu trúc là một cái gì đó lý tưởng được thực hiện liên tục, hoặc nếu không liên tục bất cứ khi nào có một chút thời gian chết. Chi nhánh, thực hiện tái cấu trúc đơn giản, chạy thử nghiệm đơn vị để xác minh mọi thứ vẫn hoạt động (đơn vị của nó đã được kiểm tra, phải không ? ) Và sau đó hợp nhất trở lại ổn định. Chuyển xung quanh thông tin cho các nhà phát triển khác để kéo những thay đổi mà bạn tái cấu trúc thành các nhánh của họ.

Điều quan trọng là các nhà phát triển phải sở hữu chất lượng của mã. Mặc dù hướng của các tính năng đến từ bên ngoài và phân bổ thời gian thường không phải là của chúng tôi, chất lượng mã là thứ cần thiết để tự hào và dành thời gian cho nó.

Bạn có thể thấy các câu hỏi sau hữu ích trong nhiệm vụ phân bổ thời gian xử lý nợ kỹ thuật:

Bạn cũng có thể muốn xem các công cụ như sonar có thể giúp xác định các khu vực của mã cần nhiều công việc nhất để tái cấu trúc. Các plugin nợ kỹ thuật là cái gì đó có thể được sử dụng để giúp đỡ điểm ra sự tích tụ của nợ theo thời gian trong cơ sở mã.

Thông thường cần phải chỉ ra rằng ROI để xử lý nợ kỹ thuật là thời gian quay vòng nhanh hơn cho các tính năng và sửa lỗi từ nhóm phát triển.


Các xét nghiệm về cơ bản được thực hiện tại ba thời điểm. Một lần khi sự cố được yêu cầu khắc phục (để đảm bảo rằng nó đáp ứng tất cả các yêu cầu và không có vấn đề lớn nào), một lần nữa khi nó được hợp nhất trở lại mặc định (kiểm tra tích hợp) và một lần nữa khi chúng tôi thực hiện xây dựng (tích hợp với tất cả cherry đã chọn vấn đề / cái nhìn cuối cùng). Tôi nghĩ rằng việc hái anh đào là cần thiết trong môi trường của chúng tôi khi chúng tôi vận hành SaaS với các khách hàng rất đặc biệt. Tôi sẽ xem xét các liên kết này, cảm ơn vì con trỏ! Chỉnh sửa: Thực sự có thêm một lần xem qua sản xuất để đảm bảo rằng nó đã tăng lên.
mở

3

Thông thường tôi đang phát triển phiên bản tái cấu trúc "song song" với hiện tại, tức là trong cùng một cơ sở mã, nhưng không tham chiếu nó từ ứng dụng cốt lõi. Và khi giải pháp mới được thực hiện và thử nghiệm, tôi đang bắt đầu tái cấu trúc thực tế.

Ví dụ 1. Giả sử tôi có Thing, hãy để nó là chức năng, giao diện, mô-đun hoặc bất cứ điều gì. Và tôi muốn cấu trúc lại nó. Tôi đang tạo Thing2 trong cùng một codebase, đây là phiên bản được cấu trúc lại của Thing. Khi nó được thực hiện và thử nghiệm, tôi sẽ cấu trúc lại mọi thứ tham chiếu đến Thing, để thay thế nó bằng Thing2. Thông thường bước này mất thời gian tương đối nhỏ.

Nếu tái cấu trúc thực tế mất quá nhiều thời gian để giữ đồng bộ mà không làm hỏng nhóm, tôi cũng đang sử dụng tất cả các tính năng có liên quan và tái cấu trúc chúng song song.

Ví dụ 2. Tôi có phần phụ trợ kết xuất mới, đó là phiên bản được cấu trúc lại của bản cũ. Nhưng nó không tương thích với frontend render cũ. Vì vậy, tôi cần tái cấu trúc frontend. Và một lần nữa: trong cùng một cơ sở mã. Khi mọi thứ đã xong, tôi chỉ thay đổi lớp thể hiện frontend, lý tưởng là nó sẽ thực hiện một cam kết ngắn.

Vâng, đệ quy người ta có thể đi đến kết luận rằng mọi thứ phải được thực hiện song song. Nhưng điều này thường xảy ra khi có quá nhiều khớp nối trong codebase hoặc nó đang thay đổi quá nhanh.

Cuối cùng, khi mã mới được tích hợp và hoạt động tốt, các tính năng cũ có thể bị xóa khỏi cơ sở mã và các tính năng mới có thể được đổi tên để lấy tên cũ.

Nói chung, ý tưởng là chuẩn bị song song các tính năng mới và chuyển sang sử dụng chúng theo một bước nhỏ.

John Carmack sử dụng phương pháp này (hoặc ít nhất là tương tự), có lẽ bài đăng trên blog của anh ấy giải thích nó tốt hơn: (liên kết)


Đây là một cách tiếp cận tốt. Tôi đang cố gắng nhớ những gì thực sự thúc đẩy câu hỏi này bây giờ ... Tôi không nghĩ rằng đó là một cái gì đó rất dễ chấp nhận song song. Hoặc nếu có, tôi nghĩ rằng mối quan tâm của tôi là cách tiếp cận này gây ra nhiều sự phân mảnh trong cơ sở mã. Chúng ta có "cách cũ" để làm mọi thứ và "cách mới" để làm việc, và những thứ cũ đang được thay thế với tốc độ chóng mặt nhưng điều đó gây đau đầu cho các nhà phát triển vì về cơ bản họ phải biết hai (hoặc nhiều) hệ thống.
mở

1

Nó có thể trông giống như một khó khăn trong khía cạnh kỹ thuật khi thực sự nó ở phía yêu cầu.

Trong đó sự phát triển được định hướng theo các yêu cầu khác nhau trong các ngành khác nhau là khó khăn thực sự. Các nhà quản lý và kiến ​​trúc sư của nhóm nên đưa ra các quyết định có thể cho phép các nhu cầu kinh doanh khác nhau cùng tồn tại.

Quá trình ZBB và Co-Dev "thỏa hiệp" khi được thực hiện sau khi đưa ra quyết định đúng đắn với các đầu vào có liên quan từ tất cả các nhà phát triển nên cho phép bạn thực hiện những gì bạn cần mà không phải suy nghĩ - Tôi sẽ hợp nhất mã của mình như thế nào.

ZBB là viết tắt của ngân sách dựa trên Zero . Bằng cách nói Co-Dev tôi có nghĩa là rất ít người đang làm việc trong lập trình song song.


2
"ZBB" và "Co-Dev" là gì?
gnat

ZBB - en.wikipedia.org/wiki/Zero-basing_bocateing . Bằng cách nói Co-Dev tôi có nghĩa là rất ít người đang làm việc trong lập trình song song.
Yosi Dahari

1

Vấn đề đối với tôi là bạn đang làm việc quá lâu trên các chi nhánh. Chi phí của các xung đột tăng theo cấp số nhân với thời gian mọi người ở trên một nhánh, do đó, với các xung đột rất dài, bạn có rất ít cơ hội để thực hiện bất kỳ tái cấu trúc nào.


0

Vấn đề của bạn là mô hình chi nhánh bạn đang sử dụng. Bạn có thể phát triển trên một nhánh và khi hoàn thành và sẵn sàng cho QA, nhánh đó được hợp nhất thành một "thân trung gian", đôi khi được gọi là Tích hợp hoặc Kiểm tra. Khi bạn phát triển tính năng tiếp theo, bạn có thể phân nhánh từ thân cây trung gian này thay thế.

Mô hình này cho phép bạn phát triển nhiều tính năng song song trên các nhánh khác nhau, hợp nhất tất cả chúng lại với nhánh Tích hợp để gửi tới QA và cũng duy trì một bản phát hành duy nhất (bạn hợp nhất QA cơ sở mã hóa nhận được vào thân chính khi chúng chứng nhận )

Bạn đang đưa ra một giả định rằng các thay đổi của bạn được gửi tới QA sẽ được thông qua mà không cần sửa đổi lớn - nếu mã QA quay lại với các hướng dẫn để loại bỏ một nửa các thay đổi, bạn sẽ phải hoàn nguyên nhưng nếu điều đó không xảy ra thì nó sẽ thực hiện sự phát triển của bạn mượt mà hơn nhiều. Vì vậy, về cơ bản, bạn đang lấy các nhánh cho các tính năng mới từ mã chính của bạn sẽ là gì (tức là thân cây sau khi hợp nhất mã được chuyển sang QA), thay vì ngày nay (thân cây hiện tại) và do đó không còn phát triển so với cơ sở mã phát hành trước đó .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.