Định dạng lại và kiểm soát phiên bản


23

Các vấn đề định dạng mã. Ngay cả vấn đề thụt đầu dòng . Và tính nhất quán là quan trọng hơn những cải tiến nhỏ. Nhưng các dự án thường không có hướng dẫn phong cách rõ ràng, đầy đủ, có thể kiểm chứngđược thi hành từ ngày 1 và những cải tiến lớn có thể đến bất kỳ ngày nào. Có thể bạn thấy rằng

SELECT id, name, address
FROM persons JOIN addresses ON persons.id = addresses.person_id;

có thể được viết tốt hơn vì / được viết tốt hơn

SELECT persons.id,
       persons.name,
       addresses.address
  FROM persons
  JOIN addresses ON persons.id = addresses.person_id;

trong khi làm việc để thêm nhiều cột vào truy vấn. Có thể đây là phức tạp nhất trong tất cả bốn truy vấn trong mã của bạn hoặc một truy vấn tầm thường trong số hàng ngàn. Cho dù quá trình chuyển đổi có khó khăn đến đâu, bạn vẫn quyết định nó xứng đáng. Nhưng làm thế nào để bạn theo dõi các thay đổi mã trên các thay đổi định dạng chính? Bạn chỉ có thể từ bỏ và nói "đây là điểm chúng tôi bắt đầu lại" hoặc bạn có thể định dạng lại tất cả các truy vấn trong toàn bộ lịch sử kho lưu trữ.

Nếu bạn đang sử dụng một hệ thống kiểm soát phiên bản phân tán như Git, bạn có thể trở lại cam kết đầu tiên và định dạng lại theo cách của bạn từ trạng thái hiện tại. Nhưng đó là rất nhiều công việc, và mọi người khác sẽ phải tạm dừng công việc (hoặc được chuẩn bị cho mẹ của tất cả các sự hợp nhất) trong khi nó đang diễn ra. Có cách nào tốt hơn để thay đổi lịch sử mang lại kết quả tốt nhất không:

  • Cùng một phong cách trong tất cả các cam kết
  • Công việc hợp nhất tối thiểu

?

Để làm rõ, đây không phải là về các thực tiễn tốt nhất khi bắt đầu dự án, mà là nên làm gì khi một phép tái cấu trúc lớn đã được coi là Điều tốt ™ nhưng bạn vẫn muốn có một lịch sử có thể theo dõi? Không bao giờ viết lại lịch sử là điều tuyệt vời nếu đó là cách duy nhất để đảm bảo rằng các phiên bản của bạn luôn hoạt động giống nhau, nhưng lợi ích của nhà phát triển khi viết lại sạch sẽ là gì? Đặc biệt là nếu bạn có các cách (kiểm tra, định nghĩa cú pháp hoặc nhị phân giống hệt sau khi biên dịch) để đảm bảo rằng phiên bản viết lại hoạt động chính xác như bản gốc?


24
Tại sao bạn muốn viết lại lịch sử? Nó đánh bại mục đích kiểm soát phiên bản. Bạn muốn chắc chắn rằng ứng dụng bạn đã gửi 3 tháng trước phù hợp với bản sửa đổi xxxxxx mà không có chút nghi ngờ nào. Ngay cả định dạng lại tầm thường là không thể chấp nhận.
Simon Bergot

5
Tôi muốn bình luận cam kết rằng tôi làm điều này với thẻ "Reformat. Không thay đổi chức năng"
Rig

3
Trong một chủ đề không liên quan, có vẻ như bạn đang đề nghị viết lại lịch sử Git bằng cách định dạng lại tất cả các mã. Đừng cho mọi người ý tưởng, viết lại lịch sử Git là xấu cho 99,9% các trường hợp. Định dạng lại không phải là trường hợp cạnh .1%.
Andrew T Finnell

4
Trong một số ngôn ngữ (tôi đang xem YOU, Python) việc định dạng lại có thể thay đổi chức năng logic của mã. Bạn phải có khả năng phân tích tất cả các ngôn ngữ được lưu trữ trong VCS của bạn để theo dõi và bỏ qua các định dạng an toàn.
Joris Timmermans

3
Định dạng lại là thay đổi mã và nên được cam kết như vậy.
David Cowden

Câu trả lời:


26

Làm định dạng lại như cam kết riêng biệt. Điều này sẽ can thiệp tối thiểu vào lịch sử và bạn sẽ có thể thấy trong nháy mắt những cam kết nào chỉ là định dạng lại và thực sự thay đổi mã. Nó có thể sai lệch git blamevà tương tự, nhưng nếu nó chỉ ra một cam kết chỉ định dạng lại, thì khá đơn giản để tìm kiếm sự thay đổi trước đó.


Tôi đã thấy các dự án bị trật bánh trong nhiều tuần vì một trong những nhà phát triển nghĩ rằng đây là một ý tưởng tốt. Nếu bạn sẽ làm điều này, hãy hiểu các rủi ro trước đó và quyết định chính xác bạn sẽ đi bao xa với định dạng. Tôi nghĩ rằng mjfgates có câu trả lời đúng.
Johntron

1
Âm thanh như nhóm trong câu hỏi có vấn đề lớn hơn định dạng mã. Nhưng vâng, tôi không khuyên bạn nên làm điều này trừ khi bạn phải làm điều đó. Nếu bạn muốn thực hiện định dạng lại các thay đổi, tôi vẫn nói tốt hơn là thực hiện chúng như các cam kết riêng biệt hơn là xen kẽ với các thay đổi chức năng.
harald

Vâng, rất nhiều vấn đề: PI chỉ muốn cảnh báo các nhà phát triển mới rằng nó không đơn giản như vẻ ngoài của nó. Các công cụ định dạng lại hàng loạt rất rủi ro (đặc biệt là nếu bạn tự xây dựng nó bằng regex - ít nhất là sử dụng AST) và nếu bạn quan tâm đến việc xem xét mã và theo dõi lỗi, nó thực sự có thể gây rối cho quá trình của bạn. Cá nhân, tôi viết mã của mình để phù hợp với phong cách của từng tệp, mặc dù tôi không ngại xem lại mã khi một vài chức năng được định dạng lại. Nhiều nhà phát triển bị treo lên về phong cách mã và bỏ qua các vấn đề lớn hơn như kiến ​​trúc, quy trình, công cụ, v.v.
Johntron

Trong lập trình, không có gì đơn giản như âm thanh :)
harald

13

Không viết lại lịch sử VCS: nó chống lại các nguyên tắc của VCS.

Đừng cố tự động sửa lỗi định dạng: nó đang xử lý các triệu chứng, không phải là vấn đề thực sự (= nhà phát triển không tuân theo các tiêu chuẩn mã hóa).

Xác định tiêu chuẩn mã hóa và định dạng các thực tiễn tốt nhất trong một tài liệu chung và khiến tất cả các nhà phát triển đồng ý.

Bạn đề cập đến Git, thật tuyệt, vì nó được phân phối. Với một DVCS, thật dễ dàng để thực thi các thực tiễn tốt nhất thông qua quy trình làm việc của người gác cổng . Người gác cổng từ chối các đề xuất hợp nhất (= yêu cầu kéo trong Git) không tuân thủ các nguyên tắc chung. Và tôi có nghĩa là từ chối , bằng chữ in đậm, nếu không, người viết mã vi phạm sẽ không bận tâm tuân theo các quy tắc và tiếp tục lặp lại các lỗi tương tự.

Kỹ thuật này hoạt động tốt cho tôi. Các lập trình viên muốn công việc của họ được hợp nhất, vì vậy sau một vài sai lầm ban đầu, họ bắt đầu tuân theo các quy tắc.

Theo sửa lỗi cơ sở mã hiện tại ... Tôi khuyên bạn nên làm điều đó dần dần, có thể là mô-đun theo mô-đun hoặc vì nó có ý nghĩa cho dự án của bạn. Kiểm tra cẩn thận ở mỗi bước. Nghe có vẻ ngu ngốc, nhưng sai lầm xảy ra ngay cả với những thay đổi nhỏ như định dạng, vì vậy hãy chuẩn bị cho một số va chạm nhỏ trên đường.


1
Bị từ chối, bởi vì tác giả nói rõ điều này nằm trong bối cảnh các dự án không bắt đầu bằng "... một hướng dẫn phong cách rõ ràng, đầy đủ, có thể kiểm chứng và được thi hành từ ngày 1". Anh ta không thể xử lý vấn đề thực sự, vì nó đã xảy ra. Tôi đồng ý với bạn mặc dù :)
Johntron

2
từ chối có nghĩa là sẽ có một cuộc chiến giữa con người và robot. Đã ở đó. Sớm hay muộn, robot sẽ yêu cầu một đoạn mã thực sự phức tạp để được định dạng theo cách không thể đọc được. Ví dụ: một chuỗi Java trên thực tế là một câu lệnh SQL, nhưng robot không biết điều này; khoảng trắng trước khi đóng parens có thể mang thông tin về cấu trúc mã cho con người, nhưng không phải cho robot; tham số chức năng được phân chia trên nhiều dòng theo cách vô nghĩa nhất ...
18446744073709551615

9

Câu trả lời cho câu hỏi thực tế của bạn là "Bạn không." Tôi biết không có công cụ SCM hiện tại nào có thể theo dõi các thay đổi trong logic từ mã được định dạng theo một cách, thông qua thay đổi định dạng chính và thông qua các thay đổi tiếp theo sau khi mã được định dạng theo cách mới. Và, bạn biết điều này, mất lịch sử trên một đoạn mã là không tốt.

Theo đó, tôi sẽ mâu thuẫn với câu đầu tiên của bạn một chút. Mã định dạng không quan trọng nhiều. Đẹp là tốt, nhưng đó không phải là những gì chúng ta ở đây. Tôi hiểu cũng như bất kỳ ai bị đổ vào mã biến thể K & R kỳ lạ cũ kỹ của ai đó với các vết lõm hai không gian (1), nhưng ... định dạng không thực sự là một trở ngại để hiểu những gì đang diễn ra, trừ khi đó là một điều gì đó đặc biệt bệnh lý. Và trong trường hợp đó, dù sao bạn cũng sẽ gặp vấn đề khi thay đổi mã và không nên làm phiền nó.

Do đó, không đáng để thực hiện các thay đổi đối với mã được thiết lập NGAY LẬP TỨC để định dạng lại nó. Thay đổi tên biến, phá vỡ các hàm dài, tất cả những thứ tái cấu trúc tốt làm thay đổi nội dung, vâng, nhưng không định dạng lại CHỈ.

1) - Tôi đã từng sở hữu Windows Clipboard Viewer một thời gian. Toàn bộ điều là một, 150k, mô-đun C. Tôi nghĩ rằng một nơi mà những người khác nhau đã sử dụng, tôi nghĩ, năm kiểu niềng răng khác nhau trong vòng ba mươi dòng của nhau. Nhưng phần đó làm việc. Tôi đã mang theo một bản in đoạn mã đó trong mười năm, nhưng tôi đã không chọc nó vì lịch sử đó quan trọng, và mã đó có trong ít nhất ba cây nguồn (Windows 3.x, NT, tương lai 95) mà tất cả đều sống trong các tòa nhà khác nhau.


Trước đây, bằng cách sử dụng hg, tôi đã thấy rằng hợp nhất từng phần là một công cụ vô giá trong việc đối phó với các hợp nhất lại yếu tố lớn khó khăn . Thông thường, những gì tôi sẽ làm là hợp nhất các xác nhận trước khi có yếu tố lại lớn, sau đó hợp nhất chính yếu tố đó và sau đó hợp nhất các cam kết kể từ yếu tố đó. Mỗi ba hòa trộn tự mìnhnhiều dễ dàng hơn sau đó cố gắng để gỡ rối sự lộn xộn mà kết quả từ thực hiện tất cả các thao tác trộn trong một đi.
Đánh dấu gian hàng

Tôi hoàn toàn đồng ý! Ngoài ra, tôi đã thấy nhiều nhà phát triển vượt qua (bao gồm cả phiên bản trẻ hơn của tôi) về định dạng lại và kiểu mã, và cuối cùng họ đưa ra các lỗi. Dấu phẩy / dấu chấm phẩy bị thiếu ở đây, các khai báo biến được chuyển lên đầu các hàm, các vòng lặp được đổi thành for-every - tất cả chúng đều có thể đưa ra các lỗi tinh vi. Phải mất một lượng kỹ năng lừa đảo để thực hiện những thay đổi này một cách an toàn.
Johntron

4

Nhưng làm thế nào để bạn theo dõi các thay đổi mã trên các thay đổi định dạng chính?

Thay đổi định dạng thay đổi mã; đối xử với họ như bạn sẽ thay đổi mã của bạn. Bất cứ ai đã làm việc trong một dự án quan trọng có thể sẽ thấy các lỗi và các vấn đề khác được tạo ra khi ai đó quyết định "chỉ" định dạng lại một số mã.

Nhưng đó là rất nhiều công việc, và mọi người khác sẽ phải tạm dừng công việc (hoặc được chuẩn bị cho mẹ của tất cả các sự hợp nhất) trong khi nó đang diễn ra.

Tại sao bạn phải định dạng lại tất cả mọi thứ cùng một lúc? Đặc biệt nếu việc định dạng lại không thay đổi ý nghĩa của mã, bạn sẽ có thể định dạng lại các tệp riêng lẻ và kiểm tra chúng khi bạn đi cùng. Tốt hơn, hãy khiến mọi người trong nhóm của bạn đồng ý về một phong cách (nếu không thì không có điểm nào trong việc định dạng lại) và tất cả họ đều quan tâm đến việc định dạng lại trong quá trình làm việc khác của họ. Sau một thời gian, bạn sẽ bao phủ hầu hết các mã mà không làm gián đoạn phần còn lại của dự án.


1

Có hai cách tiếp cận khả thi mà tôi đã thấy cho điều này.

1. Định dạng lại mã trên hook-hook

Mặc dù ban đầu, việc nuôi tóc để thay đổi mã sau khi họ đã gửi nó, nếu quy trình định dạng lại của bạn (ví dụ astyle ) không làm tổn thương mã, thì đó là một hoạt động an toàn. Theo thời gian, toàn bộ nhóm sẽ đánh giá cao rằng tất cả các mã cuối cùng trông giống nhau. Rõ ràng, có các bài kiểm tra đơn vị / tự động toàn diện sẽ đảm bảo rằng không có gì bị phá vỡ.

2. Định dạng lại một lần tất cả các mã

Điều này nguy hiểm hơn theo kinh nghiệm của tôi và khiến việc theo dõi các vấn đề lớn trở nên khó khăn, nhưng điều đó là có thể. Chạy tất cả các bài kiểm tra sau đó là điều cần thiết. Đối với phong cách mã hóa, phần lớn sự khác biệt xoay quanh việc sử dụng khoảng trắng - thụt đầu dòng hoặc dòng mới. Một công cụ hợp nhất tốt sẽ có thể được yêu cầu bỏ qua tất cả các khác biệt về khoảng trắng, vì vậy điều này sẽ giúp hợp nhất.


1
Sẽ không có tùy chọn nào khi bật Ripple trên phần lớn cơ sở mã nhanh chóng dẫn đến cùng một vụ nổ lớn khi mỗi tệp thay đổi?

@Sign: Chính xác là quan điểm của tôi - Khi hook hook thay đổi, lịch sử của bạn có thể xấu đi thành một thứ gần như vô dụng. Định dạng không thay đổi chức năng không nên là một cam kết, nó nên được ghép trong suốt lịch sử mã.
l0b0

1
Nếu IDE hỗ trợ thì cũng có 3) có IDE tự động định dạng khi lưu. Sau đó, chỉ cần sử dụng cùng một cài đặt ở mọi nơi - điều này là dễ nhất nếu bạn sử dụng mặc định với IDE.

Tôi đã thực hiện cả hai cách tiếp cận này. Cách tiếp cận đầu tiên rất khó chịu vì sẽ có rất nhiều thay đổi mỗi lần cam kết một tệp mới. Cách tiếp cận thứ hai là tốt hơn cho nhóm, như xé toạc một dải băng nhanh chóng.
Druska
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.