Làm thế nào để tránh các phương pháp keo khổng lồ?


21

Trong công việc hiện tại của tôi, tôi đã được giao nhiệm vụ dọn dẹp mã cũ một vài lần. Thông thường mã là một mê cung và dữ liệu đằng sau nó thậm chí còn rối hơn. Tôi thấy mình kết hợp mọi thứ thành các phương thức mô đun, gọn gàng. Mỗi phương pháp làm một việc và làm tốt. Đó là khi mọi thứ bắt đầu đi về phía nam ...

Lúc nào tôi cũng kết thúc với một API sạch và không có cách nào thực sự để gắn kết tất cả lại với nhau. Giải pháp là viết một phương pháp "keo" xấu xí (nói chung là đầy đủ các câu điều kiện) mà cuối cùng gọi tất cả các phương thức "sạch" của tôi.

Phương pháp keo thường kết thúc là một phiên bản ngắn gọn của mớ mã / dữ liệu mà tôi đang cố gắng dọn sạch. Nó thường dễ đọc hơn, nhưng nó vẫn gây phiền nhiễu.

Làm thế nào tôi có thể tránh các phương pháp như vậy? Đây có phải là triệu chứng của dữ liệu bị rối hoặc phản ánh một cái gì đó mà tôi đang làm sai?


3
API có nghĩa là được sử dụng. Từ mớ hỗn độn mà bạn có, bạn đã tạo một API và sau đó đánh lại nó. Có lẽ đó chỉ là yêu cầu kinh doanh. Nhưng bạn đã thêm giá trị vì người khác có thể đến và tạo một chức năng keo khác dễ dàng bằng API của bạn. Không cần vắt tay ...
Aditya MP

1
Chúng ta thậm chí đang nói chuyện các đối tượng ở đây hay chỉ là funcs ở khắp mọi nơi?
Erik Reppen

3
Tôi không nghĩ rằng đây là một bản sao của câu hỏi đó, tôi nói chung chung hơn một chút (và ở quy mô lớn hơn một chức năng).
cmhobbs

1
erik - Tôi đang nói về các đối tượng và phương pháp ở đây. Tôi đã lấy một vài mớ hỗn độn có điều kiện và biến chúng thành API. Vấn đề xảy ra khi đến lúc gọi API. Câu trả lời đầu tiên ở đây có thể chính xác là những gì tôi đang tìm kiếm.
cmhobbs

2
Làm thế nào trên trái đất là một bản sao?
MattDavey

Câu trả lời:


12

Tôi sẽ cung cấp cho bạn kinh nghiệm tái cấu trúc LedgerSMB. Chúng tôi đã đưa ra quyết định thực hiện những điều khác biệt từ sớm và vẫn đang làm chính xác những gì bạn mô tả nhưng không có nhiều phương pháp keo (chúng tôi có một vài phương pháp keo btw, chỉ là không nhiều).

Cuộc sống với hai Codebase

LedgerSMB đã tồn tại với hai cơ sở mã hóa trong khoảng 5 năm và nó sẽ còn nhiều lần nữa trước khi cơ sở mã cũ bị loại bỏ. Codebase cũ là một nỗi kinh hoàng thực sự đáng chú ý. Thiết kế db xấu, các cấu trúc Perl giống như IS->some_func(\%$some_object);cùng với mã cho thấy chính xác lý do tại sao ẩn dụ spaghetti đôi khi được sử dụng (đường dẫn thực hiện uốn khúc giữa các mô-đun và ngược lại, và giữa các ngôn ngữ, không có vần điệu hoặc lý do). Cơ sở mã mới tránh điều này bằng cách di chuyển các truy vấn db vào các thủ tục được lưu trữ, có một khung công tác sạch hơn để xử lý yêu cầu và hơn thế nữa.

Điều đầu tiên chúng tôi quyết định làm là cố gắng cấu trúc lại mô-đun bằng mô-đun. Điều này có nghĩa là di chuyển tất cả các chức năng trong một khu vực cụ thể vào một mô-đun mới và sau đó nối mã cũ vào mô-đun mới. Nếu API mới sạch, đây không phải là vấn đề lớn. Nếu API mới không phải là thứ có nhiều lông và đó là lời mời làm việc chăm chỉ hơn một chút với API mới ....

Điều thứ hai là có rất nhiều lần mã mới phải truy cập logic trong mã cũ. Điều này cần tránh ở mức độ có thể bởi vì nó dẫn đến các phương pháp keo xấu xí nhưng người ta không thể luôn luôn tránh nó. Trong trường hợp này, các phương pháp keo nên được giảm thiểu và tránh đến mức có thể nhưng được sử dụng khi cần thiết.

Để thực hiện công việc này, bạn phải cam kết viết lại tất cả các chức năng trong một khu vực cụ thể. Ví dụ, nếu bạn có thể viết lại tất cả mã theo dõi thông tin khách hàng, điều đó có nghĩa là mã gọi mã này từ mã cũ không khó để xử lý và việc gửi đến mã cũ từ mã mới được giảm thiểu.

Điều thứ hai là nếu bạn có sự trừu tượng hợp lý ở vị trí của mình, bạn sẽ có thể chọn mức API nào sẽ gọi và cách giữ sạch sẽ. Tuy nhiên, bạn nên suy nghĩ về việc viết lại các phần đang gọi API của bạn để chúng cũng sạch hơn một chút.

Có nhiều lĩnh vực công cụ kinh doanh phức tạp không thể tưởng tượng được. Bạn không thể thoát khỏi mọi sự phức tạp. Nhưng bạn có thể quản lý nó bằng cách tập trung vào API sạch, cụ thể là những gì bạn cần làm và các mô-đun sử dụng API đó một cách xây dựng. Keo chỉ nên là giải pháp cuối cùng sau khi xem xét rằng việc viết lại phần còn lại của mã gọi có thể nhanh hơn.


Tôi nghĩ rằng bạn có thể đã đánh vào đầu đinh. Lý do keo tồn tại có thể là do mã gọi giao diện tôi đã tạo. Tôi sẽ chờ đợi một số phản hồi nữa để xem liệu chúng tôi có thiếu sót gì không, nhưng tôi tin rằng điều này tổng hợp khá tốt.
cmhobbs

1
"Đường dẫn thực thi uốn khúc giữa các mô-đun và ngược lại, và giữa các ngôn ngữ, không có vần điệu hoặc lý do" - điều này nhắc nhở tôi về một số thực tiễn OO hiện đại.
dùng253751

8

Nghe có vẻ giống như những gì bạn đã làm được lấy một mớ hỗn độn rối của một precedural codebase và tạo ra một mô-đun đáng yêu precedural codebase.

Lúc nào tôi cũng kết thúc với một API sạch và không có cách nào thực sự để gắn kết tất cả lại với nhau. Giải pháp là viết một phương pháp "keo" xấu xí (nói chung là đầy đủ các câu điều kiện) mà cuối cùng gọi tất cả các phương thức "sạch" của tôi.

Với mã thủ tục (ngay cả khi nó được ngụy trang thành OO), bạn sẽ luôn kết thúc với một loại quy trình công việc tuần tự được xác định ở đâu đó, thường chứa đầy các nhánh có điều kiện phức tạp như bạn mô tả. Tôi nghi ngờ đây là bản chất thủ tục của mã khiến bạn cảm thấy có gì đó không đúng. Đây không hẳn là một điều xấu và khi làm việc với mã kế thừa có thể hoàn toàn không thể tránh khỏi


6

Bạn nên làm sạch phương pháp keo lớn xấu xí giống như cách bạn làm sạch cơ sở mã gốc. Chia nó ra theo phương pháp mô-đun gọn gàng. Bạn có thể có các nhóm dòng mã thực hiện một số nhiệm vụ chia các dòng này thành các phương thức, nếu bạn chia sẻ một số biến, bạn có thể xem xét đưa các biến được chia sẻ và các phương thức mới vào một lớp.


2
Bạn không nhận được một cây keo?
Pieter B

3
@PieterB có thể, nhưng sẽ dễ dàng hơn để trích xuất các phụ thuộc khác nhau khi bạn có các tác vụ khác nhau trong các phương thức khác nhau. Bạn có thể thực hiện một lần tái cấu trúc khác sau khi giải nén các phương thức mới.
Paling

1

Về cơ bản, bạn tiếp tục thêm các lớp trừu tượng, cho đến khi nó trông đúng ở từng lớp được thực hiện . Điều nghịch lý về sự trừu tượng là bạn thêm độ phức tạp để giảm bớt nó, bởi vì khi bạn đọc mã trừu tượng, bạn chỉ quan tâm đến một lớp mỗi lần. Nếu mỗi lớp đủ nhỏ để dễ hiểu, thì nó không quan trọng bao nhiêu lớp.

Đó cũng là điều làm cho sự trừu tượng trở nên khó viết. Ngay cả một cái gì đó đơn giản như một cây bút chì là uốn cong tâm trí nếu bạn cố gắng giữ tất cả các lớp trừu tượng của nó trong đầu của bạn cùng một lúc. Điều quan trọng là có được một lớp theo cách bạn muốn, mà bạn đã làm, sau đó quên tất cả sự phức tạp làm nền tảng cho lớp đó và làm điều tương tự ở cấp độ tiếp theo.


0

Có vẻ như bạn đang cấu trúc lại API bằng cách chỉ nghĩ về việc triển khai API, nhưng không nghĩ đủ về mã sử dụng API - đó là "mã keo" mà bạn đang nói đến.

Nếu đó là sự thật, bạn có thể thử bắt đầu ở đầu kia. Viết lại nội dung đe dọa trở thành mã keo xấu xí của bạn trước tiên và tạo một vài giao diện chưa được triển khai sẽ trở thành API của bạn trong quy trình đó. Đừng suy nghĩ quá nhiều về việc triển khai API thực tế này - vẫn ổn nếu bạn có cảm giác đặc biệt là bạn có thể làm được. Và chỉ sau đó viết lại mê cung mã để phù hợp với API đó. Tất nhiên sẽ có một số thay đổi trong API và mã keo trong quy trình này, nhưng nó sẽ phù hợp với nhau hơn.

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.