Khớp nối. Thực hành tốt nhất


11

Tiếp theo từ chủ đề này, tôi bắt đầu

Mẫu đơn

Nó khiến tôi suy nghĩ về việc kết hợp các lớp học của mình như thế nào và cách tốt nhất để đạt được khớp nối lỏng lẻo. Xin lưu ý rằng tôi là một lập trình viên mới (4 tháng trong công việc đầu tiên của tôi) và đây thực sự là sự cân nhắc đầu tiên tôi dành cho việc này, và tôi rất muốn hiểu khái niệm này.

Vì vậy, những gì chính xác cấu thành khớp nối lỏng lẻo so với khớp nối nặng? Trong dự án hiện tại (và dự án đầu tiên) của tôi, tôi đang làm việc với dự án ac # winforms, trong đó phần GUI tạo các đối tượng và ghi lại các sự kiện của chúng, khi chúng được kích hoạt, GUI tạo một đối tượng khác (trong ví dụ này là datagridview (một lớp) mà tôi đã tạo ra bao bọc xung quanh một datagridview tiêu chuẩn và thêm chức năng bổ sung) và gắn nó vào GUI. Đây là khớp nối xấu hay tốt?

Tôi thực sự không muốn có thói quen xấu và bắt đầu viết mã kém, do đó tôi sẽ đánh giá cao phản hồi của bạn.

Câu trả lời:


11

Để làm cho mã của bạn được ghép lỏng lẻo ở đây là một số điều đơn giản cần nhớ:

Phần 1:

Về mặt kỹ thuật được gọi là "Tách mối quan tâm". Mỗi lớp có một vai trò cụ thể, cần xử lý logic nghiệp vụ hoặc logic ứng dụng. Hãy cố gắng và tránh xa lớp học kết hợp cả hai trách nhiệm. tức là Một lớp quản lý dữ liệu (thuật ngữ rộng) là logic ứng dụng trong khi một lớp sử dụng dữ liệu là logic nghiệp vụ.

Cá nhân tôi đề cập đến điều này (trong thế giới nhỏ bé của riêng tôi) như create it or use it. Một lớp nên tạo một đối tượng hoặc sử dụng một đối tượng mà nó không bao giờ nên làm cả hai.

Phần 2:

Làm thế nào để thực hiện tách mối quan tâm.
Là một điểm khởi đầu, có hai kỹ thuật đơn giản:

Lưu ý: Các mẫu thiết kế không tuyệt đối.
Chúng được cho là tùy chỉnh theo tình huống nhưng có một chủ đề cơ bản tương tự như tất cả các ứng dụng. Vì vậy, đừng nhìn vào các ví dụ dưới đây và nói rằng tôi phải tuân theo điều này một cách cứng nhắc; đây chỉ là những ví dụ (và hơi giả tạo ở đó).

Phụ thuộc tiêm :

Đây là nơi bạn vượt qua trong một đối tượng mà một lớp sử dụng. Đối tượng mà bạn truyền vào dựa trên một giao diện để lớp của bạn biết phải làm gì với nó nhưng không cần biết triển khai thực tế.

class Tokenizer
{
    public:
        Tokenizer(std::istream& s)
            : stream(s)
        {}
        std::string nextToken() { std::string token; stream >> token;return token;}
    private:
        std::istream& stream;
};

Ở đây chúng tôi tiêm luồng vào Tokenizer. Mã thông báo không biết loại luồng nào miễn là nó thực hiện giao diện của std :: istream.

Mẫu định vị dịch vụ :

Mẫu định vị dịch vụ là một biến thể nhỏ của tiêm phụ thuộc. Thay vì đưa ra một đối tượng mà nó có thể sử dụng, bạn truyền cho nó một đối tượng biết cách định vị (tạo) đối tượng bạn muốn sử dụng.

class Application
{
     public:
         Application(Persister& p)
             : persistor(p)
         {}

         void save()
         {
             std::auto_ptr<SaveDialog> saveDialog = persistor.getSaveDialog();
             saveDialog.DoSaveAction();
         }

         void load()
         {
             std::auto_ptr<LoadDialog> loadDialog = persistor.getLoadDialog();
             loadDialog.DoLoadAction();
         }
    private:
        Persister& persistor;
};

Ở đây chúng ta truyền đối tượng ứng dụng một đối tượng điện trở. Khi bạn thực hiện một hành động lưu / tải, nó sử dụng điện trở để tạo ra một đối tượng thực sự biết cách thực hiện hành động đó. Lưu ý: Một lần nữa, điện trở là một giao diện và bạn có thể cung cấp các cài đặt khác nhau tùy theo tình huống.

Điều này hữu ích khi một potentiallyđối tượng duy nhất được yêu cầu mỗi khi bạn khởi tạo một hành động.

Cá nhân tôi thấy điều này đặc biệt hữu ích trong việc viết bài kiểm tra đơn vị.

Lưu ý về mẫu:

Các mẫu thiết kế là một chủ đề rất lớn đối với chính nó. Đây không phải là một danh sách các mẫu độc quyền mà bạn có thể sử dụng để trợ giúp với khớp nối lỏng lẻo; đây chỉ là một điểm khởi đầu phổ biến

Với kinh nghiệm bạn sẽ nhận ra bạn đã sử dụng các mẫu này, chỉ là bạn không sử dụng tên chính thức của chúng. Bằng cách tiêu chuẩn hóa tên của họ (và khiến mọi người tìm hiểu chúng), chúng tôi thấy rằng việc truyền đạt ý tưởng thật dễ dàng và nhanh chóng hơn.


3
@Darren Young: Cảm ơn vì đã chấp nhận nó. Nhưng câu hỏi của bạn chỉ có ba giờ. Tôi sẽ quay lại sau một ngày hoặc xác minh rằng những người khác không cung cấp câu trả lời tốt hơn.
Martin York

Cảm ơn các phản ứng tuyệt vời. Liên quan đến vấn đề quan tâm .... Tôi có các lớp yêu cầu một số dữ liệu để sử dụng và sau đó làm một cái gì đó với dữ liệu đó. Đây là cách trước đây tôi đã thiết kế các lớp học. Do đó, tốt hơn là tạo một lớp lấy dữ liệu và điều chỉnh nó thành đúng mẫu và sau đó một lớp khác thực sự sử dụng dữ liệu?
Darren Young

@Darren Young: Như với tất cả các chương trình, dòng màu xám và mờ không được xác định rõ. Thật khó để đưa ra một phản hồi chính xác mà không cần đọc mã của bạn. Nhưng khi tôi nói về managing the datatôi đang đề cập đến các biến (không phải dữ liệu thực tế). Vì vậy, những thứ như con trỏ cần phải được quản lý để chúng không bị rò rỉ. Nhưng dữ liệu có thể được chèn hoặc cách lấy dữ liệu có thể được trừu tượng hóa (để lớp của bạn có thể được sử dụng lại với các phương thức truy xuất dữ liệu khác nhau). Tôi xin lỗi tôi không thể chính xác hơn.
Martin York

1
@Darren Young: Theo ghi nhận của @StuperUser trong câu trả lời của anh ấy. Đừng quá nhiệt tình (AKA minutae of loose coupling(thích từ minutae)). Bí quyết của lập trình là học khi sử dụng các kỹ thuật. Việc sử dụng quá mức có thể dẫn đến một mớ mã.
Martin York

@Martin - cảm ơn vì lời khuyên. Tôi nghĩ đó là nơi tôi đang gặp khó khăn hiện tại ..... Tôi có xu hướng liên tục lo lắng về kiến ​​trúc mã của mình và cũng cố gắng học ngôn ngữ cụ thể mà tôi đang sử dụng C #. Tôi đoán nó sẽ đi kèm với kinh nghiệm và mong muốn của tôi để học những thứ này. Tôi đánh giá cao ý kiến ​​của bạn.
Darren Young

6

Tôi là nhà phát triển ASP.NET nên không biết nhiều về ghép nối WinForms, nhưng biết một chút từ các ứng dụng web N-Tier, giả sử kiến ​​trúc ứng dụng 3 tầng gồm UI, Miền, Lớp truy cập dữ liệu (DAL).

Khớp nối lỏng lẻo là về trừu tượng.

Như @MKO tuyên bố nếu bạn có thể thay thế một tổ hợp bằng một tổ hợp khác (ví dụ: một dự án UI mới sử dụng dự án Miền của bạn, một DAL mới lưu vào bảng tính thay vì cơ sở dữ liệu) thì có khớp nối lỏng lẻo. Nếu Tên miền và DAL của bạn phụ thuộc vào các dự án tiếp theo chuỗi, thì khớp nối có thể lỏng lẻo hơn.

Một khía cạnh của một cái gì đó được ghép lỏng lẻo là liệu bạn có thể thay thế một đối tượng bằng một đối tượng khác thực hiện cùng một giao diện hay không. Nó không phụ thuộc vào đối tượng thực tế, nhưng mô tả trừu tượng về những gì nó làm (giao diện của nó).
Khớp nối lỏng lẻo, giao diện và đầu phun phụ thuộc (DI) và Inversion of Control (IoC) rất hữu ích cho khía cạnh cách ly của thiết kế để kiểm tra.

Ví dụ: Một đối tượng trong dự án UI gọi một đối tượng Kho lưu trữ trong dự án Miền.
Bạn có thể tạo ra một giả đối tượng mà cụ giao diện tương tự như kho rằng mã dưới sử dụng kiểm tra, sau đó viết hành vi đặc biệt đối với các bài kiểm tra ( khai để ngăn ngừa mã sản xuất mà tiết kiệm / xóa / bị được gọi và mocks rằng hành động như khai theo dõi của trạng thái của đối tượng giả cho mục đích thử nghiệm).
Điều này có nghĩa là mã sản xuất duy nhất được gọi bây giờ chỉ có trong đối tượng UI của bạn, thử nghiệm của bạn sẽ chỉ chống lại phương thức đó và bất kỳ lỗi thử nghiệm nào cũng sẽ cô lập lỗi đối với phương thức đó.

Ngoài ra, trong menu Phân tích trong VS (tùy thuộc vào phiên bản bạn có), có các công cụ để tính toán số liệu mã cho dự án của bạn, một trong số đó là Ghép nối lớp, sẽ có thêm thông tin về điều này trong tài liệu MSDN.

Đừng TOO sa lầy trong minutae của khớp nối lỏng lẻo tuy nhiên, nếu không có cơ hội rằng mọi thứ để có được tái sử dụng (ví dụ như một dự án miền với nhiều hơn một giao diện người dùng) và tuổi thọ của sản phẩm là nhỏ, sau đó khớp nối lỏng lẻo trở nên ít mức độ ưu tiên (nó vẫn sẽ được tính đến), nhưng nó vẫn sẽ là trách nhiệm của các kiến ​​trúc sư / lãnh đạo công nghệ, những người sẽ xem xét mã của bạn.


3

Khớp nối đề cập đến mức độ kiến ​​thức trực tiếp mà một lớp có của một lớp khác . Điều này không có nghĩa được hiểu là đóng gói so với không đóng gói. Nó không phải là một tham chiếu đến kiến ​​thức của một lớp về các thuộc tính hoặc việc thực hiện của một lớp khác, mà là kiến ​​thức về chính lớp đó. Khớp mạnh xảy ra khi một lớp phụ thuộc chứa một con trỏ trực tiếp đến một lớp cụ thể cung cấp hành vi cần thiết. Sự phụ thuộc không thể được thay thế, hoặc "chữ ký" của nó thay đổi, mà không yêu cầu thay đổi đối với lớp phụ thuộc. Khớp nối lỏng lẻo xảy ra khi lớp phụ thuộc chỉ chứa một con trỏ tới một giao diện, sau đó có thể được thực hiện bởi một hoặc nhiều lớp cụ thể.Sự phụ thuộc của lớp phụ thuộc là "hợp đồng" được chỉ định bởi giao diện; một danh sách xác định các phương thức và / hoặc các thuộc tính mà các lớp triển khai phải cung cấp. Do đó, bất kỳ lớp nào thực hiện giao diện đều có thể đáp ứng sự phụ thuộc của lớp phụ thuộc mà không phải thay đổi lớp. Điều này cho phép mở rộng trong thiết kế phần mềm; một lớp mới thực hiện một giao diện có thể được viết để thay thế một phụ thuộc hiện tại trong một số hoặc tất cả các tình huống, mà không yêu cầu thay đổi đối với lớp phụ thuộc; các lớp mới và cũ có thể được thay thế tự do. Khớp nối mạnh mẽ không cho phép điều này. Liên kết tham chiếu.


3

Hãy xem 5 nguyên tắc RẮN . Tuân thủ SRP, ISP và DIP sẽ có khả năng khớp nối thấp hơn đáng kể, cho đến nay, DIP là mạnh nhất. Đây là nguyên tắc cơ bản bên dưới DI đã được đề cập .

Ngoài ra, GRASP đáng để xem xét. Đó là một sự pha trộn kỳ lạ giữa các khái niệm trừu tượng (ban đầu bạn sẽ khó thực hiện) và các mẫu cụ thể (có thể thực sự hữu ích), nhưng vẻ đẹp có lẽ là mối quan tâm ít nhất của bạn ngay bây giờ.

Và cuối cùng, bạn có thể thấy phần này trên IoC khá hữu ích, như là một điểm khởi đầu cho các kỹ thuật phổ biến.

Trong thực tế, tôi đã tìm thấy một câu hỏi về stackoverflow , nơi tôi chứng minh việc áp dụng RẮN trên một vấn đề cụ thể. Có thể là một đọc thú vị.


1

Theo Wikipedia:

Trong điện toán và thiết kế hệ thống, một hệ thống kết hợp lỏng lẻo là một hệ thống mà mỗi thành phần của nó có hoặc sử dụng ít hoặc không có kiến ​​thức về các định nghĩa của các thành phần riêng biệt khác.

Vấn đề với khớp nối chặt chẽ làm cho nó khó thực hiện thay đổi. (Nhiều tác giả dường như cho rằng điều này chủ yếu gây ra sự cố trong quá trình bảo trì, nhưng theo kinh nghiệm của tôi thì nó cũng có liên quan trong quá trình phát triển ban đầu.) trong các mô-đun mà nó được ghép nối. Thường xuyên hơn không, điều này đòi hỏi nhiều thay đổi trong các mô-đun khác, v.v.

Ngược lại, trong một hệ thống kết hợp lỏng lẻo, những thay đổi tương đối biệt lập. Do đó, chúng ít tốn kém hơn và có thể được thực hiện với sự tự tin hơn.

Trong ví dụ cụ thể của bạn, công cụ xử lý sự kiện sẽ cung cấp một số tách biệt giữa GUI và dữ liệu cơ bản. Tuy nhiên, nó có vẻ như có những khu vực tách biệt khác mà bạn có thể khám phá. Không có thêm chi tiết về tình huống cụ thể của bạn, rất khó để được cụ thể. Tuy nhiên, bạn có thể bắt đầu với kiến ​​trúc 3 tầng tách biệt:

  • Lưu trữ và truy xuất dữ liệu logic
  • Logic kinh doanh
  • Logic cần thiết để chạy UI

Một cái gì đó để xem xét là đối với các ứng dụng nhỏ, một lần với một nhà phát triển duy nhất, lợi ích của việc thực thi khớp nối lỏng lẻo ở mọi cấp độ có thể không đáng để nỗ lực. Mặt khác, các ứng dụng phức tạp lớn hơn với nhiều nhà phát triển là điều bắt buộc. Ban đầu, có một chi phí phát sinh trong việc giới thiệu các khái niệm trừu tượng và giáo dục các nhà phát triển không quen thuộc với mã liên quan đến kiến ​​trúc của nó. Tuy nhiên, về lâu dài, khớp nối lỏng lẻo mang lại lợi thế vượt xa chi phí.

Nếu bạn nghiêm túc về việc thiết kế các hệ thống ghép lỏng lẻo, hãy đọc các nguyên tắc RẮN và các mẫu thiết kế.

Tuy nhiên, điều quan trọng cần nhận ra là những mô hình và nguyên tắc này chỉ có thế - mô hình và nguyên tắc. Chúng không phải là quy tắc. Điều này có nghĩa là chúng cần được áp dụng một cách thực tế và thông minh

Khi các mẫu được quan tâm, điều quan trọng là phải hiểu rằng không có triển khai "chính xác" duy nhất cho bất kỳ mẫu nào. Chúng cũng không phải là các mẫu cắt cookie để thiết kế triển khai của riêng bạn. Họ ở đó để cho bạn biết hình dạng của một giải pháp tốt có thể có và cung cấp cho bạn một ngôn ngữ chung để truyền đạt các quyết định thiết kế với các nhà phát triển khác.

Tất cả tốt nhất.


1

Sử dụng tiêm phụ thuộc, mô hình chiến lược và sự kiện. Nói chung: đọc các mẫu thiết kế, tất cả đều về khớp nối lỏng lẻo và giảm sự phụ thuộc. Tôi muốn nói rằng các sự kiện được kết nối một cách lỏng lẻo như bạn nhận được trong khi các phần tử tiêm chích và chiến lược phụ thuộc yêu cầu một số giao diện.

Một mẹo hay là đặt các lớp trong các thư viện / tập hợp khác nhau và để chúng phụ thuộc vào càng ít thư viện khác càng tốt, điều đó sẽ buộc bạn phải cấu trúc lại để sử dụng ít phụ thuộc hơn


4
Là bao cao su một số thuật ngữ CNTT trừu tượng hay đơn giản là tôi không nhận được sự chơi chữ?
Darren Young

3
Đó là một tên khác cho container tiêm phụ thuộc.
Mchl

2
Cũng là một cách tuyệt vời để ngăn chặn sự lây lan của virus. Chúng ta đang nói về những điều tương tự?
sova

1
Khớp nối nặng thường được thực hiện vào phần phụ trợ
Homde

1
Đặt tiêu đề hầu như không lạm dụng định dạng
Homde

0

Hãy để tôi cung cấp một cái nhìn thay thế. Tôi chỉ nghĩ về điều này trong điều kiện mỗi lớp là một API tốt. Thứ tự các phương thức được gọi là rõ ràng. Những gì họ làm là rõ ràng. Bạn đã giảm số lượng phương thức xuống mức tối thiểu cần thiết. Ví dụ như,

init, mở, đóng

đấu với

setTheFoo, setBar, initX, getConnection, đóng

Đầu tiên là rõ ràng và trông giống như API tốt đẹp. Thứ hai có thể gây ra lỗi nếu gọi sai thứ tự.

Tôi không lo lắng quá nhiều về việc phải sửa đổi và biên dịch lại người gọi. Tôi duy trì RẤT NHIỀU mã mới và một số 15 năm tuổi. Tôi thường muốn lỗi trình biên dịch khi tôi thực hiện thay đổi. Đôi khi tôi cố tình phá vỡ một API vì lý do đó. Nó cho tôi cơ hội để xem xét sự phân chia trên mỗi người gọi. Tôi không phải là một fan hâm mộ lớn của việc tiêm phụ thuộc vì tôi muốn có thể theo dõi trực quan thông qua mã của mình mà không có hộp đen và tôi muốn trình biên dịch bắt được càng nhiều lỗi càng tốt.

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.