Lớp chống tham nhũng là gì và nó được sử dụng như thế nào?


151

Tôi đang cố gắng tìm hiểu ý nghĩa của lớp Chống tham nhũng. Tôi biết rằng đó là một cách để chuyển đổi / làm việc xung quanh mã kế thừa hoặc các API xấu. Những gì tôi không hiểu là làm thế nào nó hoạt động và những gì làm cho nó tách biệt khỏi lớp không mong muốn.

Tôi đã thực hiện một số tìm kiếm, nhưng tôi không thể tìm thấy bất kỳ ví dụ hoặc giải thích đơn giản nào, vì vậy tôi đang tìm kiếm một người hiểu nó và có thể giải thích nó bằng các ví dụ đơn giản. Một câu trả lời thỏa mãn câu hỏi của tôi nên đơn giản (không nhất thiết phải ngắn) và cung cấp các ví dụ dễ hiểu về việc thực hiện và sử dụng.

Xem câu hỏi này , cho trường hợp sử dụng của tôi.

Câu trả lời:


147

Hãy tưởng tượng bạn phải sử dụng mã của người khác được thiết kế như hình dưới đây:

    class Messy {
        String concat(String param, String str) { /* ... */ }
        boolean contains(String param, String s) { /* ... */ }
        boolean isEmpty(String param) { /* ... */ }
        boolean matches(String param, String regex) { /* ... */ }
        boolean startsWith(String param, String prefix) { /* ... */ }
    }

Bây giờ hãy tưởng tượng bạn phát hiện ra rằng mã của bạn phụ thuộc vào nó trông giống như sau:

String process(String param) {
    Messy messy = new Messy();
    if (messy.contains(param, "whatever")) {
        return messy.concat(param, "-contains");
    }
    if (messy.isEmpty(param)) {
        return messy.concat(param, "-empty");
    }
    if (messy.matches(param, "[whatever]")) {
        return messy.concat(param, "-matches");
    }
    if (messy.startsWith(param, "whatever")) {
        return messy.concat(param, "-startsWith");
    }
    return messy.concat(param, "-whatever");
    // WTF do I really need to repeat bloody "param" 9 times above?
}

... Và rằng bạn muốn làm cho nó dễ sử dụng hơn, đặc biệt, để loại bỏ việc sử dụng lặp đi lặp lại các tham số không cần thiết cho ứng dụng của bạn.

Được rồi, vì vậy bạn bắt đầu xây dựng một lớp chống tham nhũng.

  1. Điều đầu tiên là đảm bảo rằng "mã chính" của bạn không tham chiếu Messytrực tiếp. Ví dụ: bạn sắp xếp quản lý phụ thuộc theo cách cố gắng truy cập Messykhông biên dịch được.

  2. Thứ hai, bạn tạo một mô-đun "lớp" chuyên dụng, là người duy nhất truy cập Messyvà đưa nó ra "mã chính" theo cách có ý nghĩa tốt hơn với bạn.

Mã lớp sẽ trông như sau:

    class Reasonable { // anti-corruption layer
        String param;
        Messy messy = new Messy();
        Reasonable(String param) {
            this.param = param;
        }
        String concat(String str) { return messy.concat(param, str); }
        boolean contains(String s) { return messy.contains(param, s); }
        boolean isEmpty() { return messy.isEmpty(param); }
        boolean matches(String regex) { return messy.matches(param, regex); }
        boolean startsWith(String prefix) { return messy.startsWith(param, prefix); }
    }

Do đó, "mã chính" của bạn không gây rối Messy, Reasonablethay vào đó, sử dụng như sau:

String process(String param) {
    Reasonable reasonable = new Reasonable(param);
    // single use of "param" above and voila, you're free
    if (reasonable.contains("whatever")) {
        return reasonable.concat("-contains");
    }
    if (reasonable.isEmpty()) {
        return reasonable.concat("-empty");
    }
    if (reasonable.matches("[whatever]")) {
        return reasonable.concat("-matches");
    }
    if (reasonable.startsWith("whatever")) {
        return reasonable.concat("-startsWith");
    }
    return reasonable.concat("-whatever");
}

Lưu ý rằng vẫn còn một mớ hỗn độn lộn xộn Messynhưng hiện tại nó được ẩn sâu một cách hợp lý bên trong Reasonable, làm cho "mã chính" của bạn hợp lý sạch sẽ và không có tham nhũng sẽ được đưa đến đó bằng cách sử dụng Messycông cụ trực tiếp .


Ví dụ trên được dựa trên cách giải thích Lớp chống tham nhũng tại c2 wiki:

Nếu ứng dụng của bạn cần xử lý cơ sở dữ liệu hoặc ứng dụng khác có mô hình không mong muốn hoặc không thể áp dụng được cho mô hình bạn muốn trong ứng dụng của riêng bạn, hãy sử dụng AnticorruptionLayer để dịch sang / từ mô hình đó và của bạn.

Lưu ý ví dụ được cố ý làm đơn giản và cô đọng để giữ cho lời giải thích ngắn gọn.

Nếu bạn có một mớ hỗn độn API lớn hơn để che giấu lớp chống tham nhũng, thì cách tiếp cận tương tự cũng được áp dụng: thứ nhất, đảm bảo "mã chính" của bạn không truy cập trực tiếp vào thứ bị hỏng và thứ hai, phơi bày nó theo cách nhiều hơn thuận tiện trong bối cảnh sử dụng của bạn.

Khi "nhân rộng" lớp của bạn ngoài một ví dụ đơn giản ở trên, hãy tính đến việc làm cho API của bạn thuận tiện không nhất thiết phải là một nhiệm vụ tầm thường. Đầu tư một nỗ lực để thiết kế lớp của bạn đúng cách , xác minh mục đích sử dụng của nó với các bài kiểm tra đơn vị, v.v.

Nói cách khác, đảm bảo rằng API của bạn thực sự là một cải tiến so với API mà nó ẩn, hãy đảm bảo rằng bạn không chỉ giới thiệu một lớp tham nhũng khác.


Để hoàn thiện, hãy chú ý sự khác biệt tinh tế nhưng quan trọng giữa mẫu này và các mẫu có liên quan Bộ điều hợpMặt tiền . Như được chỉ định bởi tên của nó, lớp chống tham nhũng giả định rằng API cơ bảnvấn đề về chất lượng (bị "hỏng") và có ý định bảo vệ các vấn đề được đề cập.

Bạn có thể nghĩ về nó theo cách này: nếu bạn có thể biện minh rằng nhà thiết kế thư viện sẽ tốt hơn là phơi bày chức năng của nó Reasonablethay vì Messy, điều này có nghĩa là bạn đang làm việc trên lớp chống tham nhũng, thực hiện công việc của họ , sửa lỗi thiết kế của họ .

Trái ngược với điều đó, AdaptorFacade không đưa ra các giả định về chất lượng của thiết kế cơ bản. Chúng có thể được áp dụng cho API được thiết kế tốt để bắt đầu, chỉ cần điều chỉnh nó cho các nhu cầu cụ thể của bạn.

Trên thực tế, thậm chí có thể hiệu quả hơn khi giả định rằng các mẫu như AdaptorFacade mong muốn mã cơ bản được thiết kế tốt. Bạn có thể nghĩ về nó theo cách này: mã được thiết kế tốt không quá khó để điều chỉnh cho trường hợp sử dụng cụ thể. Nếu nó chỉ ra rằng thiết kế bộ điều hợp của bạn tốn nhiều công sức hơn dự kiến, điều này có thể chỉ ra rằng mã cơ bản, bằng cách nào đó, "bị lỗi". Trong trường hợp đó, bạn có thể xem xét phân tách công việc để tách các giai đoạn: trước tiên, thiết lập lớp chống tham nhũng để trình bày API cơ bản theo cách có cấu trúc đúng và tiếp theo, thiết kế bộ điều hợp / mặt tiền của bạn trên lớp bảo vệ đó.


1
Làm thế nào để mở rộng quy mô này nếu có toàn bộ cấu trúc của các lớp API phụ thuộc? Có còn dễ quản lý hơn lớp bảo vệ phần còn lại của ứng dụng không?
biết đến

1
@Knownasilya đó là một câu hỏi rất hay, câu trả lời được mở rộng để giải quyết vấn đề đó
gnat

4
In other words, make sure that your API is indeed an improvement over one it hides, make sure that you don't just introduce another layer of corruption.Đó là toàn bộ phần xứng đáng với một thẻ đậm.
Lilienthal

19
Các lớp chống tham nhũng không liên quan gì đến việc xử lý các API chất lượng kém. Chúng là về việc xử lý các sự không phù hợp về mặt khái niệm, điều chỉnh các miền mà chúng ta chỉ có thể sử dụng bằng cách "làm hỏng" mã của chúng tôi thành các miền mà chúng ta có thể sử dụng dễ dàng hơn.
Ian Fairman

8
Ian Fairman đã hiểu đúng, trong khi tác giả của câu trả lời này chắc chắn là không. Nếu bạn đi đến nguồn của khái niệm (sách DDD), bạn sẽ tìm thấy ít nhất hai điều mâu thuẫn với câu trả lời này: 1) một lớp chống tham nhũng được tạo để tránh làm hỏng mô hình miền mới mà chúng tôi đang phát triển với các yếu tố từ mô hình của một hệ thống bên ngoài hiện có; không phải là hệ thống kia bị "hỏng", thực tế nó có thể hoàn toàn tốt và được thiết kế tốt; 2) một lớp chống tham nhũng thường sẽ chứa một số lớp, thường bao gồm Mặt tiềnBộ điều hợp , cũng như Dịch vụ .
Rogério

41

Để trích dẫn một nguồn khác:

Tạo một lớp cô lập để cung cấp cho khách hàng chức năng theo mô hình miền của riêng họ. Lớp nói chuyện với hệ thống khác thông qua giao diện hiện có của nó, yêu cầu ít hoặc không sửa đổi hệ thống khác. Trong nội bộ, lớp dịch theo cả hai hướng khi cần thiết giữa hai mô hình.

Eric Evans, Thiết kế hướng tên miền, in lần thứ 16, trang 365

Điều quan trọng nhất là các thuật ngữ khác nhau được sử dụng ở mỗi bên của lớp chống tham nhũng. Tôi đã từng làm việc trên một hệ thống cho hậu cần giao thông vận tải. Các vòng đã được lên kế hoạch. Bạn phải trang bị phương tiện tại một kho, lái xe đến các địa điểm khách hàng khác nhau và phục vụ họ và ghé thăm những nơi khác, như trạm dừng xe tăng. Nhưng từ cấp cao hơn, đây là tất cả về kế hoạch nhiệm vụ. Vì vậy, thật hợp lý khi tách các thuật ngữ lập kế hoạch nhiệm vụ tổng quát hơn khỏi các thuật ngữ logistic vận chuyển rất cụ thể.

Vì vậy, sự cô lập các lớp chống tham nhũng không chỉ là bảo vệ bạn khỏi mã lộn xộn, mà là tách các miền khác nhau và đảm bảo rằng chúng sẽ được tách ra trong tương lai.


6
Cái này rất quan trọng! Một ACL không chỉ được sử dụng với mã Messy, mà như một phương tiện để giao tiếp giữa các bối cảnh bị ràng buộc. Nó dịch từ ngữ cảnh này sang ngữ cảnh khác, để dữ liệu trong mỗi bối cảnh phản ánh ngôn ngữ và cách bối cảnh đó nghĩ và nói về dữ liệu.
Didier A.

29

Bộ chuyển đổi

Khi bạn có các giao diện không tương thích, thực hiện logic tương tự, để thích ứng cái này với cái kia, để bạn có thể sử dụng các triển khai của cái này với những thứ mong đợi cái kia.

Thí dụ:

Bạn có một đối tượng muốn có Xe, nhưng bạn chỉ có lớp 4WheelVehicle, vì vậy bạn tạo một CarBuiltUsing4WheelVehicle và sử dụng nó làm Xe của bạn.

Mặt tiền

Khi bạn có một API phức tạp / khó hiểu / khổng lồ và bạn muốn làm cho nó đơn giản hơn / rõ ràng hơn / nhỏ hơn. Bạn sẽ tạo một Mặt tiền để che giấu sự phức tạp / nhầm lẫn / bổ sung và chỉ hiển thị một API đơn giản / rõ ràng / nhỏ mới.

Thí dụ:

Bạn đang sử dụng một thư viện có 100 phương thức và để thực hiện một số tác vụ nhất định, bạn cần thực hiện một loạt các khởi tạo, kết nối, mở / đóng mọi thứ, để cuối cùng có thể làm những gì bạn muốn và tất cả những gì bạn muốn là 1 tính năng của tất cả 50 thư viện đều có thể làm được, vì vậy bạn tạo một Mặt tiền chỉ có một phương thức cho 1 tính năng mà bạn cần và đó là tất cả việc khởi tạo, dọn dẹp, v.v. cho bạn.

Lớp chống tham nhũng

Khi bạn có một hệ thống nằm ngoài miền của mình, nhưng nhu cầu kinh doanh của bạn đòi hỏi bạn phải làm việc với tên miền khác đó. Bạn không muốn giới thiệu tên miền khác này thành tên miền của riêng mình, do đó làm hỏng nó, vì vậy bạn sẽ dịch khái niệm tên miền của mình, sang tên miền khác này và ngược lại.

Thí dụ:

Một hệ thống xem người quản lý có tên và danh sách các chuỗi, một chuỗi cho mỗi giao dịch. Bạn xem Hồ sơ là các lớp độc lập có tên và Giao dịch là các lớp độc lập có một chuỗi và Khách hàng có Hồ sơ và tập hợp các Giao dịch.

Vì vậy, bạn tạo một lớp ACL sẽ cho phép dịch giữa Khách hàng của bạn và Khách hàng của hệ thống khác. Bằng cách này, bạn không bao giờ phải sử dụng Khách hàng của hệ thống khác, bạn chỉ cần nói với ACL: "hãy đưa cho tôi Khách hàng có Hồ sơ X và ACL nói với hệ thống khác để cung cấp cho Khách hàng tên X.name và trả lại bạn là Khách hàng có Hồ sơ X.

====================

Cả ba đều tương đối giống nhau, bởi vì chúng đều là các mẫu không xác định. Nhưng chúng giải quyết các cấu trúc, lớp / đối tượng khác nhau so với API so với mô-đun / hệ thống con. Bạn có thể có tất cả chúng kết hợp nếu bạn cần. Hệ thống phụ có API phức tạp, do đó, bạn xây dựng FACADE cho nó, nó sử dụng một mô hình khác nhau, vì vậy với mỗi biểu diễn dữ liệu không phù hợp với mô hình của bạn, bạn sẽ CHUYỂN ĐỔI dữ liệu đó trở lại cách bạn mô hình hóa nó. Cuối cùng, có thể các giao diện cũng không tương thích, vì vậy bạn sẽ sử dụng QUẢNG CÁO để thích ứng từ cái này sang cái khác.


12

Rất nhiều câu trả lời ở đây nói rằng ACL "không chỉ" về việc bọc mã lộn xộn. Tôi sẽ đi xa hơn và nói rằng họ hoàn toàn không phải về điều đó, và nếu họ làm vậy thì đó là lợi ích phụ.

Một lớp chống tham nhũng là về việc ánh xạ một tên miền sang một tên miền khác để các dịch vụ sử dụng tên miền thứ hai không phải bị "làm hỏng" bởi các khái niệm từ cái đầu tiên. ACL là để mô hình miền các bộ điều hợp cho các lớp, nó chỉ xảy ra ở một cấp độ khác. Bộ điều hợp được cho là mẫu thiết kế quan trọng nhất - tôi sử dụng nó mọi lúc - nhưng đánh giá lớp bọc là có lộn xộn hay không là không liên quan. Đó là những gì nó có, tôi chỉ cần nó có một giao diện khác.

Tập trung vào sự lộn xộn là sai lệch và bỏ lỡ quan điểm của DDD là gì. ACL là về việc đối phó với sự không phù hợp về khái niệm, không phải là chất lượng kém.

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.