Ghép mã được giới thiệu bởi DRY và OOD


14

Tôi đang tìm kiếm hướng dẫn về khớp nối DRY và Code. Tôi không thích sao chép mã của mình và tôi cũng không thích ghép mã giữa các mô-đun không liên quan. Vì vậy, tôi tái cấu trúc mã trùng lặp nếu tôi tìm thấy mã trùng lặp giống hệt một năm sau khi sao chép được giới thiệu. Tuy nhiên, tôi đã ngày càng trải qua các tình huống trong đó thế giới thực khó lường hơn nhiều, và sau khi tái cấu trúc mã, đã phát sinh các tình huống yêu cầu loại bỏ mã một lần nữa.

Ví dụ: nếu tôi có mã để xử lý ô tô chạy xăng, SUV xăng, ô tô điện và SUV điện, giả sử tôi đã tái cấu trúc mã trùng lặp thành phân cấp "xăng" và phân cấp "điện", cả hai đều giảm dần từ phân cấp "xe". Càng xa càng tốt. Và sau đó, công ty của tôi giới thiệu một chiếc xe hybrid và Semi Semi - sẽ yêu cầu thay đổi cốt lõi đối với hệ thống phân cấp ban đầu của tôi. Có lẽ nó sẽ yêu cầu "thành phần" giữa xăng và hệ thống phân cấp điện.

Rõ ràng sao chép mã là xấu vì nó làm tăng thời gian thực hiện thay đổi chung cho tất cả các sản phẩm trên. Nhưng việc tái cấu trúc mã phổ biến khiến việc giới thiệu các biến thể dành riêng cho sản phẩm trở nên khó khăn như nhau và dẫn đến nhiều "nhảy lớp" khi người ta phải tìm dòng mã để sửa lỗi - một thay đổi trong lớp cha cấp cao hơn có thể kích hoạt lỗi hồi quy kích hoạt trong số tất cả các hậu duệ.

Làm thế nào để người ta đạt được sự cân bằng tối ưu giữa DRY và khớp nối mã không mong muốn?


1
Luôn luôn tốt khi không tuân theo các quy tắc một cách mù quáng mà là tham gia vào bộ não trước tiên.
gnasher729

đủ công bằng - do đó hướng dẫn, không quy tắc.
dùng2549686

Bạn đã đọc trang Wiki trên DRY (hoặc OAOO, như trước đây được gọi là) chưa? wiki.c2.com/?OnceAndOnlyOnce Đó là nơi diễn ra rất nhiều cuộc thảo luận ban đầu về nó. (Trên thực tế, Ward đã phát minh ra Wiki dành riêng cho các cuộc thảo luận về Mô hình và Thực tiễn.)
Jörg W Mittag

Các câu trả lời rất liên quan, ngay cả khi câu hỏi không hoàn toàn giống như một bản sao: softwareengineering.stackexchange.com/questions/300043/
mẹo

Câu trả lời:


8

giả sử tôi tái cấu trúc mã trùng lặp thành phân cấp "xăng" và phân cấp "điện", cả hai đều giảm dần từ phân cấp "xe". Càng xa càng tốt.

Và sau đó, công ty của tôi giới thiệu một chiếc xe hybrid và Semi Semi - sẽ yêu cầu thay đổi cốt lõi đối với hệ thống phân cấp ban đầu của tôi. Có lẽ nó sẽ yêu cầu "thành phần" giữa xăng và hệ thống phân cấp điện

Tôi nghĩ rằng đây là một trong những lý do chính khiến mọi người hướng tới sáng tác hơn là thừa kế.

Kế thừa buộc bạn phải tái cấu trúc lớn khi bạn có một sự thay đổi về mặt khái niệm giống như bạn mô tả.

Khi tái cấu trúc là 'quá lớn / khó khăn' thì mọi người viết mã trùng lặp để tránh nó.

Thay vì điều khiển từ xa bản sao bằng cách di chuyển mã lên chuỗi thừa kế, bạn có thể chuyển nó ra một lớp trợ giúp hoặc dịch vụ và sau đó tiêm lớp đó như một phần của một chế phẩm khi được yêu cầu.

Liệu thiết kế kết quả là OOP có mở để tranh luận không


1
+1 để chỉ ra rằng thừa kế là vấn đề, không phải DRY. Cách dễ nhất để sử dụng lại mã là loại bỏ các phụ thuộc không cần thiết và tất cả mọi người thường bỏ lỡ thực tế rằng một lớp cha (và con cháu của nó) đều là các phụ thuộc khi sử dụng thừa kế. Chỉ khi bạn giảm hoặc loại bỏ sự phụ thuộc, bạn mới thực sự có được mã tái sử dụng.
Greg Burghardt

3
" Liệu thiết kế kết quả là OOP có sẵn sàng để tranh luận hay không ". Mọi thứ đều mở để tranh luận. Câu hỏi cần đặt ra là nó có mở cho cuộc tranh luận hợp lý, hợp lý không? Câu trả lời là không. Tôi nghĩ rằng đoạn cuối của bạn làm mất đi một câu trả lời rất tốt.
David Arno

@davidarno không thực sự theo bạn, tôi đọc bài viết trong tựa đề là Thiết kế hướng đối tượng? vì vậy tôi đang giải quyết câu hỏi mà không cần phải đi qua cuộc tranh luận
Ewan

1
@Ewan: Tôi ở đây với David Arno. Tôi nghĩ rằng trong hơn 2 thập kỷ, người ta đã tin rằng "nếu không có quyền thừa kế, thì đó không phải là OOP" là một lời ngụy biện.
Doc Brown

jeeze đây chính xác là loại thảo luận tôi đã cố gắng tránh. có quan điểm từ cả hai phía, không có câu trả lời dứt khoát
Ewan

3

Bạn đã đúng, theo nguyên tắc DRY, có thể tăng khớp nối giữa các mô-đun không liên quan. Đặc biệt trong các hệ thống phần mềm lớn hơn, điều này có thể dẫn đến các tình huống không tuân theo DRY có thể là sự thay thế tốt hơn.

Thật không may, ví dụ của bạn cũng không phải là phù hợp với chứng minh điều này - những vấn đề mô tả ở đó là do lỗi cổ điển trong sai việc sử dụng kế thừa dưới mức tối ưu. Tuy nhiên, đối với những gì tôi đã viết ở trên, không có vấn đề gì nếu bạn cấu trúc lại mã chung thành một lớp cơ sở chung hoặc thành lớp trợ giúp (thành phần). Trong cả hai trường hợp, người ta có thể buộc phải đưa mã chung vào thư viện L và tham chiếu thư viện đó từ hai chương trình A và B. trước đây không liên quan.

Chúng ta hãy giả sử A và B hoàn toàn không liên quan với nhau trước đây, chúng có thể được phiên bản, phát hành và triển khai độc lập. Tuy nhiên, bằng cách đặt mã chung vào một lib L được chia sẻ, các yêu cầu mới đối với A có thể tạo ra các thay đổi đối với L, hiện có thể gây ra thay đổi cho B. Vì vậy, điều này gây ra sự cần thiết phải thử nghiệm bổ sung và có thể là một chu kỳ phát hành và triển khai mới cho B.

Vậy làm thế nào bạn có thể xử lý tình huống này, nếu bạn không sẵn sàng từ bỏ nguyên tắc DRY? Vâng, có một số chiến thuật nổi tiếng để tiếp cận điều này:

  1. Giữ A, B và L là một phần của cùng một sản phẩm, với một số phiên bản chung, quy trình xây dựng, phát hành và triển khai chung, với mức độ tự động hóa cao

  2. hoặc tự tạo L thành sản phẩm, với số phiên bản nhỏ (không có thay đổi không tương thích) và số phiên bản chính (có thể chứa các thay đổi vi phạm) và để A và B cho phép mỗi người tham chiếu một dòng phiên bản khác nhau của L.

  3. Tạo L càng RẮN càng tốt và quan tâm đến khả năng tương thích ngược. Càng nhiều mô-đun trong L có thể được sử dụng lại mà không cần sửa đổi (OCP), các thay đổi vi phạm sẽ ít xảy ra hơn. Và các nguyên tắc khác trong "RẮN" đang giúp hỗ trợ mục tiêu đó.

  4. Sử dụng các bài kiểm tra tự động đặc biệt cho L, nhưng cũng cho A và B.

  5. Hãy cẩn thận những gì bạn đưa vào L. Logic kinh doanh chỉ tồn tại ở một nơi trong hệ thống là một ứng cử viên sáng giá. Những thứ chỉ "trông giống nhau" và có thể khác nhau trong tương lai là những ứng cử viên tồi.

Lưu ý khi A và B được phát triển, duy trì và phát triển bởi các nhóm khác nhau, không liên quan, nguyên tắc DRY trở nên khá quan trọng - DRY là về khả năng duy trì và khả năng phát triển, nhưng để hai nhóm khác nhau cung cấp nỗ lực bảo trì cá nhân đôi khi có thể hiệu quả hơn so với việc buộc các sản phẩm của họ bên nhau vì một chút tái phạm.

Vì vậy, cuối cùng, nó là một sự đánh đổi. Nếu bạn muốn tuân theo nguyên tắc DRY trong các hệ thống lớn hơn, bạn cần đầu tư nhiều công sức hơn để tạo ra các thành phần mạnh mẽ, có thể tái sử dụng - thường là nhiều hơn bạn mong đợi. Bạn phải tin tưởng vào phán đoán của mình khi nó đáng giá, và khi nào thì không.


1

DRY là một quy tắc cấu trúc khác. Điều đó có nghĩa là nếu bạn đưa nó đến mức cực đoan thì tệ như thể bạn bỏ qua nó. Đây là một phép ẩn dụ để đưa bạn ra khỏi bộ óc cấu trúc.

Yêu cặp song sinh của bạn. Giết các phân thân.

Khi bạn sao chép và dán một cách mù quáng để tránh gõ bàn phím, bạn sẽ vô tình tạo bản sao. Chắc chắn họ làm những gì bạn muốn nhưng họ đè nặng bạn vì bây giờ thay đổi hành vi đó rất tốn kém.

Khi bạn tái tạo hành vi giống hệt nhau với mã giống hệt nhau do có trách nhiệm khác nhau có cùng một nhu cầu bây giờ nhưng điều đó có thể khiến bạn thay đổi khác nhau, bạn có một cặp song sinh có thể tự do thay đổi và phát triển như một cá nhân theo thời gian.

Bạn có thể quét DNA (mã) của họ tất cả những gì bạn thích. Bản sao và cặp song sinh rất khó để phân biệt nếu tất cả những gì bạn làm là nhìn vào chúng. Những gì bạn cần là để hiểu bối cảnh họ sống. Tại sao họ được sinh ra. Số phận cuối cùng của họ có khả năng là gì.

Giả sử bạn làm việc cho công ty ABC. Nó được điều hành bởi ba giám đốc điều hành của công ty, A, B và C. Tất cả họ đều muốn bạn tạo ra một sản phẩm phần mềm nhưng mỗi người đều có bộ phận riêng. Họ đều muốn bạn bắt đầu nhỏ. Chỉ cần xuất một tin nhắn đơn giản cho bây giờ. Vì vậy, bạn viết "Xin chào thế giới".

A ghét nó, muốn bạn đặt tên công ty ở đó.

B thích nó, muốn bạn để nó một mình và thêm tên công ty vào một màn hình giật gân.

C chỉ muốn một máy tính và nghĩ rằng tin nhắn chỉ là một cách để bạn bắt đầu.

Một điều bạn chắc chắn, những người này có những ý tưởng rất khác nhau về dự án này. Đôi khi họ sẽ đồng ý. Đôi khi họ sẽ kéo bạn theo những hướng khác nhau.

Khi bạn sao chép mã vì bạn đang tạo khả năng cho mã đó thay đổi độc lập, bạn đang tạo một cặp. Khi bạn sao chép mã vì gõ là một nỗi đau và sao chép và dán dễ dàng là bạn đang tạo bản sao ác.

A, B và C là các bậc thầy khác nhau mà mã của bạn phải phục vụ. Không một dòng mã nào có thể phục vụ nhiều hơn một chủ trong thời gian dài.


Trước hết, cảm ơn tất cả, cho tất cả các ý kiến.
dùng2549686
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.