2009-04-23 34 views
18

tôi xin lỗi vì sự chủ quan của câu hỏi này, nhưng tôi là một chút khó khăn và tôi sẽ đánh giá cao một số hướng dẫn và lời khuyên từ bất cứ ai đã phải đối phó với vấn đề này trước:Làm thế nào để thực hiện nguyên tắc RẮN vào một dự án hiện

Tôi có (những gì trở thành) một dự án RESTful API rất lớn được viết bằng C# 2.0 và một số lớp học của tôi đã trở nên quái dị. Lớp API chính của tôi là một ví dụ về điều này - với vài chục thành viên và các phương thức (có thể là hàng trăm). Như bạn có thể tưởng tượng, nó trở thành một cơn ác mộng nhỏ, không chỉ để duy trì mã này mà còn chỉ cần điều hướng mã đã trở thành việc vặt.

Tôi khá mới với các nguyên tắc RẮN, và tôi là fan hâm mộ lớn của các mẫu thiết kế (nhưng tôi vẫn còn ở giai đoạn đó nơi tôi có thể thực hiện họ, nhưng không hoàn toàn đủ để biết khi nào nên sử dụng họ - trong những tình huống không rõ ràng).

Tôi cần phải phá vỡ các lớp học của tôi xuống trong kích thước, nhưng tôi đang ở một mất mát như thế nào tốt nhất để đi về làm việc đó. StackOverflow'ers đồng nghiệp của tôi có thể đề nghị những cách mà họ đã lấy mã monoliths hiện có và cắt chúng xuống kích thước?

Trả lời

23

Nguyên tắc trách nhiệm duy nhất - Lớp học chỉ nên có một lý do để thay đổi. Nếu bạn có một lớp nguyên khối, thì có lẽ nó có nhiều hơn một lý do để thay đổi. Chỉ cần xác định một lý do của bạn để thay đổi và trở thành chi tiết chi tiết như hợp lý. Tôi sẽ đề nghị để bắt đầu "lớn". Tái cấu trúc một phần ba mã vào một lớp khác. Một khi bạn đã có, sau đó bắt đầu lại với lớp học mới của bạn. Đi thẳng từ một lớp đến lớp 20 là quá khó khăn.

Nguyên tắc mở/đóng - Một lớp học phải mở để mở rộng nhưng đóng để thay đổi. Khi hợp lý, hãy đánh dấu các thành viên và phương thức của bạn là ảo hoặc trừu tượng. Mỗi mục phải tương đối nhỏ trong tự nhiên và cung cấp cho bạn một số chức năng hoặc định nghĩa cơ bản về hành vi. Tuy nhiên, nếu bạn cần thay đổi chức năng sau này, bạn sẽ có thể thêm mã, thay vì thay đổi mã để giới thiệu chức năng mới/khác.

Nguyên tắc thay thế Liskov - Lớp học nên được thay thế cho lớp cơ sở của nó. Chìa khóa ở đây, theo ý kiến ​​của tôi, là làm thừa kế một cách chính xác. Nếu bạn có một tuyên bố trường hợp rất lớn, hoặc hai trang của báo cáo nếu kiểm tra loại có nguồn gốc của đối tượng, sau đó bạn vi phạm nguyên tắc này và cần phải suy nghĩ lại cách tiếp cận của bạn.

Nguyên tắc phân đoạn giao diện - Theo tôi, nguyên tắc này gần giống với nguyên tắc về Trách nhiệm duy nhất. Nó chỉ áp dụng đặc biệt cho một giao diện lớp/cấp độ cao (hoặc trưởng thành). Một cách để sử dụng nguyên tắc này trong một lớp học lớn là làm cho lớp của bạn triển khai giao diện trống. Tiếp theo, thay đổi tất cả các loại sử dụng lớp của bạn là loại giao diện. Điều này sẽ phá vỡ mã của bạn. Tuy nhiên, nó sẽ chỉ ra chính xác cách bạn đang tiêu thụ lớp học của bạn. Nếu bạn có ba trường hợp, mỗi trường hợp sử dụng tập con của riêng họ về các phương thức và thuộc tính, thì bây giờ bạn biết rằng bạn cần ba giao diện khác nhau. Mỗi giao diện đại diện cho một tập hợp các chức năng, và một lý do để thay đổi.

Nguyên tắc đảo ngược phụ thuộc - Câu chuyện ngụ ngôn của phụ huynh/con khiến tôi hiểu điều này. Hãy suy nghĩ của một lớp cha mẹ. Nó định nghĩa hành vi, nhưng không quan tâm đến các chi tiết bẩn. Nó đáng tin cậy. Tuy nhiên, một lớp trẻ em là tất cả về các chi tiết và không thể phụ thuộc vào vì nó thay đổi thường xuyên. Bạn luôn muốn phụ thuộc vào cha mẹ, các lớp học có trách nhiệm, và không bao giờ theo cách khác. Nếu bạn có một lớp cha mẹ tùy thuộc vào một lớp con, bạn sẽ nhận được hành vi bất ngờ khi bạn thay đổi một cái gì đó. Trong tâm trí của tôi, đây là cùng một suy nghĩ của SOA. Hợp đồng dịch vụ xác định đầu vào, đầu ra và hành vi, không có chi tiết.

Tất nhiên, ý kiến ​​và hiểu biết của tôi có thể không đầy đủ hoặc sai. Tôi sẽ đề nghị học hỏi từ những người đã nắm vững những nguyên tắc này, như Bác Bob. Một điểm khởi đầu tốt cho tôi là cuốn sách của ông, Agile Principles, Patterns, and Practices in C#.Một tài nguyên khác là Uncle Bob on Hanselminutes.

Tất nhiên, là Joel and Jeff pointed out, đây là những nguyên tắc chứ không phải quy tắc. Họ là những công cụ để giúp hướng dẫn bạn, không phải là luật đất đai.

EDIT:

Tôi chỉ tìm thấy những SOLID screencasts trông thực sự thú vị. Mỗi cái dài khoảng 10-15 phút.

3

Nó sẽ là một quá trình tốn thời gian. Bạn cần phải đọc mã và xác định các phần không đáp ứng các nguyên tắc SOLID và cấu trúc lại thành các lớp mới. Sử dụng một VS add-in như Resharper (http://www.jetbrains.com) sẽ hỗ trợ quá trình tái cấu trúc.

Lý tưởng nhất là bạn sẽ có phạm vi phủ sóng tốt của các bài kiểm tra đơn vị tự động để bạn có thể đảm bảo các thay đổi của mình không đưa ra các vấn đề với mã.

biết thêm thông tin

Trong lớp API chính, bạn cần phải xác định phương pháp có liên quan với nhau và tạo ra một lớp mà cụ thể hơn đại diện cho những hành động phương pháp thực hiện.

ví dụ:

Giả sử tôi có một lớp Địa chỉ với các biến riêng biệt có chứa số đường, tên, v.v. Lớp này chịu trách nhiệm chèn, cập nhật, xóa, v.v. Nếu tôi cũng cần định dạng địa chỉ theo cách cụ thể cho địa chỉ bưu điện , Tôi có thể có một phương thức gọi là GetFormattedPostalAddress() trả về địa chỉ được định dạng.

Hoặc, tôi có thể cấu trúc lại phương thức này thành một lớp gọi là AddressFormatter lấy địa chỉ trong hàm khởi tạo và có thuộc tính Get được gọi là PostalAddress trả về địa chỉ được định dạng.

Ý tưởng là phân chia các trách nhiệm khác nhau thành các lớp riêng biệt.

+0

Tôi là một fan hâm mộ lớn của Resharper, và đã sử dụng nó trong một thời gian dài, và tôi có một số phạm vi kiểm tra đơn vị, nhưng không đủ gần. Có cái gì đó cụ thể hơn để suy nghĩ về khi làm refactor? – Ash

2

Những gì tôi đã làm khi trình bày loại điều này (và tôi sẽ dễ dàng thừa nhận rằng trước đây tôi chưa sử dụng nguyên tắc SOLID, nhưng từ những gì tôi biết về chúng, chúng nghe hay) là xem codebase hiện tại từ một điểm kết nối. Về cơ bản, bằng cách nhìn vào hệ thống, bạn sẽ có thể tìm thấy một số tập hợp các chức năng được kết nối nội bộ cao (nhiều tương tác thường xuyên) nhưng bên ngoài lỏng lẻo ghép đôi (ít tương tác không thường xuyên). Thông thường, có một vài trong số các phần này trong bất kỳ bộ mã lớn nào; họ là ứng cử viên cho việc cắt bỏ. Về cơ bản, một khi bạn đã xác định được các ứng cử viên của mình, bạn phải liệt kê các điểm mà tại đó chúng được kết hợp bên ngoài với toàn bộ hệ thống. Điều này sẽ cung cấp cho bạn một ý tưởng tốt về mức độ phụ thuộc lẫn nhau liên quan. Thường có một chút công bằng của sự phụ thuộc lẫn nhau.Đánh giá các tập con và điểm kết nối của chúng để tái cấu trúc; thường xuyên (nhưng không phải luôn luôn) có kết thúc là một vài cấu trúc lại cấu trúc rõ ràng có thể làm tăng sự tách rời. Với một mắt trên những refactorings, sử dụng các khớp nối hiện có để xác định giao diện tối thiểu cần thiết để cho phép các hệ thống phụ để làm việc với phần còn lại của hệ thống. Tìm kiếm sự tương đồng trong các giao diện đó (thường xuyên, bạn tìm thấy nhiều hơn bạn mong đợi!). Và cuối cùng, triển khai những thay đổi này mà bạn đã xác định.

Quá trình này nghe có vẻ khủng khiếp, nhưng trên thực tế, nó thực sự khá đơn giản. Tâm trí bạn, đây không phải là lộ trình hướng tới một hệ thống hoàn toàn được thiết kế hoàn hảo (cho điều đó, bạn cần phải bắt đầu từ đầu), nhưng nó chắc chắn sẽ làm giảm sự phức tạp của toàn bộ hệ thống và tăng tính toàn diện của mã.

4

Có một cuốn sách kinh điển của Martin Fowler - Refactoring: Improving the Design of Existing Code.

Ở đó, ông cung cấp một bộ kỹ thuật thiết kế và ví dụ về các quyết định để làm cơ sở mã hiện tại của bạn dễ quản lý hơn và dễ bảo trì (và rằng những gì hiệu trưởng RẮN là tất cả về). Mặc dù có một số thói quen chuẩn trong tái cấu trúc nó là một quá trình rất tùy chỉnh và một giải pháp không thể được áp dụng cho tất cả các dự án.

Thử nghiệm đơn vị là một trong những trụ cột ở góc để quá trình này thành công. Bạn cần phải bao gồm codebase hiện tại của bạn với mức độ bao phủ mã đủ để bạn chắc chắn rằng bạn không phá vỡ công cụ trong khi thay đổi nó. Trên thực tế, việc sử dụng khung kiểm thử đơn vị hiện đại với sự hỗ trợ chế nhạo sẽ dẫn đến việc khuyến khích bạn thiết kế tốt hơn.

Có các công cụ như ReSharper (yêu thích của tôi) và CodeRush để hỗ trợ thay đổi mã tẻ nhạt. Nhưng đó thường là những thứ cơ khí tầm thường, đưa ra quyết định thiết kế là quá trình phức tạp hơn nhiều và không có quá nhiều công cụ hỗ trợ. Sử dụng sơ đồ lớp và UML giúp. Đó là những gì tôi sẽ bắt đầu từ, thực sự. Hãy cố gắng hiểu được những gì đã có và mang lại một số cấu trúc cho nó. Sau đó, từ đó bạn có thể đưa ra quyết định về phân tách và quan hệ giữa các thành phần khác nhau và thay đổi mã của bạn cho phù hợp.

Hy vọng điều này sẽ giúp tái cấu trúc vui vẻ!

Các vấn đề liên quan