Tách các giao diện lớn


9

Tôi đang sử dụng một giao diện lớn với khoảng 50 phương thức để truy cập cơ sở dữ liệu. Giao diện đã được viết bởi một đồng nghiệp của tôi. Chúng tôi đã thảo luận về điều này:

Tôi: 50 phương pháp là quá nhiều. Đó là một mùi mã.
Đồng nghiệp: Tôi nên làm gì về nó? Bạn muốn truy cập DB - bạn có nó.
Tôi: Vâng, nhưng nó không rõ ràng và khó có thể duy trì trong tương lai.
Đồng nghiệp: OK, bạn nói đúng, nó không hay. Giao diện nên như thế nào sau đó?
Tôi: Làm thế nào về 5 phương thức trả về các đối tượng có, như, 10 phương thức mỗi phương thức?

Mmmh, nhưng điều này sẽ không giống nhau? Điều này thực sự dẫn đến sự rõ ràng hơn? Có đáng nỗ lực không?

Thỉnh thoảng tôi đang ở trong một tình huống mà tôi muốn có một giao diện và điều đầu tiên tôi nghĩ đến là một giao diện lớn . Có một mẫu thiết kế chung cho việc này?


Cập nhật (trả lời bình luận của SJuan):

"Loại phương thức": Đây là giao diện để tìm nạp dữ liệu từ cơ sở dữ liệu. Tất cả các phương thức đều có dạng (mã giả)

List<Typename> createTablenameList()

Các phương thức và bảng không chính xác trong mối quan hệ 1-1, sự nhấn mạnh nhiều hơn vào thực tế là bạn luôn nhận được một số loại danh sách xuất phát từ cơ sở dữ liệu.


12
Thiếu thông tin liên quan (loại phương pháp nào bạn có). Dù sao, tôi đoán: nếu bạn chỉ chia theo số thì đồng nghiệp của bạn đúng, bạn không cải thiện được gì. Một tiêu chí phân chia có thể sẽ do "thực thể" (gần tương đương với một bảng) được trả về (vì vậy, a UserDaovà a CustomerDaovà a ProductDao)
SJuan76

Thật vậy, một số bảng gần giống về mặt ngữ nghĩa với các bảng khác tạo thành "bè phái". Vì vậy, làm các phương pháp.
TobiMcNamobi

Có thể xem mã? Tôi biết nó đã 4 tuổi và có lẽ bạn đã sửa nó rồi: D Nhưng tôi rất thích nghĩ về vấn đề này. Tôi đã giải quyết một cái gì đó như thế này trước đây.
clankill3r

@ clankill3r Quả thực tôi không còn quyền truy cập vào giao diện cụ thể khiến tôi đăng câu hỏi ở trên. Vấn đề là tổng quát hơn mặc dù. Hãy tưởng tượng một DB với khoảng 50 bảng và cho mỗi bảng một phương thức nhưList<WeatherDataRecord> createWeatherDataTable() {db.open(); return db.select("*", "tbl_weatherData");}
TobiMcNamobi

Câu trả lời:


16

Đúng, 50 phương thức là mùi mã, nhưng mùi mã có nghĩa là nhìn lại lần thứ hai, không phải nó tự động sai. Nếu mọi khách hàng sử dụng lớp đó có khả năng cần tất cả 50 phương thức, có thể không có trường hợp nào để phân tách nó. Tuy nhiên, điều này là không thể. Quan điểm của tôi là, việc chia tách một giao diện tùy ý có thể tồi tệ hơn là không chia tách nó.

Không có một mẫu nào để sửa nó, nhưng nguyên tắc mô tả trạng thái mong muốn là Nguyên tắc phân chia giao diện ('Tôi' trong RẮN), nói rằng không khách hàng nào bị buộc phải phụ thuộc vào các phương thức mà nó không sử dụng .

Mô tả ISP cung cấp cho bạn một gợi ý về cách khắc phục: nhìn vào máy khách . Thông thường, chỉ bằng cách nhìn vào một lớp, có vẻ như mọi thứ thuộc về nhau, nhưng sự phân chia rõ ràng xuất hiện khi bạn nhìn vào các khách hàng sử dụng lớp đó. Luôn luôn xem xét các khách hàng đầu tiên khi thiết kế một giao diện.

Cách khác để xác định xem và nơi nên chia giao diện là bằng cách thực hiện lần thứ hai. Điều thường xảy ra là việc triển khai thứ hai của bạn không cần nhiều phương thức, vì vậy những phương thức đó rõ ràng nên được tách ra thành giao diện riêng của chúng.


Câu trả lời này và utnapistim thực sự tuyệt vời.
TobiMcNamobi

13

Đồng nghiệp: OK, bạn nói đúng, nó không hay. Giao diện nên như thế nào sau đó?

Tôi: Làm thế nào về 5 phương thức trả về các đối tượng có, như, 10 phương thức mỗi phương thức?

Đó không phải là tiêu chí tốt (thực tế không có tiêu chí nào trong tuyên bố đó). Bạn có thể nhóm chúng theo (giả sử ứng dụng của bạn là ứng dụng giao dịch tài chính, ví dụ của tôi):

  • chức năng (chèn, cập nhật, chọn, giao dịch, siêu dữ liệu, lược đồ, v.v.)
  • thực thể (người dùng DAO , tiền gửi DAO, v.v.)
  • khu vực ứng dụng (giao dịch tài chính, quản lý người dùng, tổng số, v.v.)
  • mức độ trừu tượng (tất cả mã truy cập bảng là một mô-đun riêng biệt; tất cả các API được chọn đều nằm trong hệ thống phân cấp riêng, hỗ trợ giao dịch riêng biệt, tất cả mã chuyển đổi trong một mô-đun, tất cả mã xác thực trong mô-đun, v.v.)

Mmmh, nhưng điều này sẽ không giống nhau? Điều này thực sự dẫn đến sự rõ ràng hơn? Có đáng nỗ lực không?

Nếu bạn chọn đúng tiêu chí, chắc chắn. Nếu bạn không, chắc chắn là không :).

Một vài ví dụ:

  • nhìn vào các đối tượng ADODB để biết ví dụ đơn giản về các nguyên thủy OO (API DB của bạn có thể đã cung cấp điều này)

  • nhìn vào mô hình dữ liệu Django ( https://docs.djangoproject.com/en/dev/topics/db/models/ ) để biết ý tưởng mô hình dữ liệu với mức độ trừu tượng cao (trong C ++, bạn có thể sẽ cần thêm một chút nồi hơi mã, nhưng đó là một ý tưởng tốt). Việc triển khai này được thiết kế với vai trò "mô hình", trong mẫu thiết kế MVC.

  • hãy xem API sqlite để biết ý tưởng API phẳng ( http://www.sqlite.org/c3ref/funclist.html ), chỉ bao gồm các nguyên hàm chức năng (API C).


3

Thỉnh thoảng tôi đang ở trong một tình huống mà tôi muốn có một giao diện và điều đầu tiên tôi nghĩ đến là một giao diện lớn. Có một mẫu thiết kế chung cho việc này?

Đó là một mẫu chống thiết kế được gọi là lớp nguyên khối . Có 50 phương thức trong một lớp hoặc giao diện là vi phạm có thể xảy ra đối với SRP . Lớp học nguyên khối xuất hiện bởi vì nó cố gắng là tất cả mọi thứ cho mọi người.

DCI giải quyết phương pháp phình to. Về cơ bản, nhiều trách nhiệm của một lớp có thể được phân bổ cho các vai trò (được giảm tải cho các lớp khác) chỉ liên quan đến các bối cảnh nhất định. Việc áp dụng các vai trò có thể đạt được theo một số cách bao gồm mixin hoặc trang trí . Cách tiếp cận này giữ cho các lớp tập trung và nạc.

Làm thế nào về 5 phương thức trả về các đối tượng có, như, 10 phương thức mỗi phương thức?

Điều này cho thấy việc khởi tạo tất cả các vai trò khi đối tượng được khởi tạo. Nhưng tại sao khởi tạo vai trò bạn có thể không cần? Thay vào đó, khởi tạo một vai trò trong bối cảnh mà bạn thực sự cần nó.

Nếu bạn thấy rằng tái cấu trúc đối với DCI là không rõ ràng, bạn có thể đi với một mẫu khách truy cập đơn giản hơn . Nó cung cấp một lợi ích tương tự mà không nhấn mạnh việc tạo bối cảnh ca sử dụng.

EDIT: Suy nghĩ của tôi về điều này đã thay đổi một số. Tôi đã cung cấp một câu trả lời thay thế.


1

Dường như với tôi mọi câu trả lời khác là thiếu điểm. Vấn đề là một giao diện nên xác định lý tưởng một đoạn hành vi nguyên tử. Đó là cái tôi trong RẮN.

Một lớp nên có một trách nhiệm nhưng điều này vẫn có thể bao gồm nhiều hành vi. Để gắn bó với một đối tượng khách hàng cơ sở dữ liệu điển hình, điều này có thể cung cấp chức năng CRUD đầy đủ. Đó sẽ là bốn hành vi: tạo, đọc, cập nhật và xóa. Trong một thế giới RẮN thuần túy, máy khách cơ sở dữ liệu sẽ triển khai không phải IDatabaseClient mà là ICreator, IReader, IUpdater và IDeleter không ổn định.

Điều này sẽ có một số lợi ích. Đầu tiên, chỉ bằng cách đọc khai báo lớp, người ta sẽ ngay lập tức tìm hiểu rất nhiều về lớp, các giao diện mà nó thực hiện đã nói lên toàn bộ câu chuyện. Thứ hai, nếu đối tượng khách được chuyển qua làm đối số, giờ đây có một tùy chọn hữu ích khác nhau. Nó có thể được thông qua với tư cách là một IReader và người ta có thể tin rằng callee chỉ có thể đọc được. Các hành vi khác nhau có thể được kiểm tra riêng.

Tuy nhiên, khi nói đến thử nghiệm, thực tế phổ biến là chỉ cần tát một giao diện trên một lớp là bản sao 1-1 của giao diện lớp đầy đủ. Nếu kiểm tra là tất cả những gì bạn quan tâm về điều này có thể là một cách tiếp cận hợp lệ. Nó cho phép bạn làm cho người giả khá nhanh chóng. Nhưng nó hầu như không bao giờ RẮN và thực sự lạm dụng các giao diện cho mục đích chuyên dụng.

Vì vậy, có, 50 phương pháp là một mùi nhưng nó phụ thuộc vào ý định và mục đích cho dù nó xấu hay không. Nó chắc chắn không lý tưởng.


0

Các lớp truy cập dữ liệu có xu hướng có rất nhiều phương thức được gắn vào một lớp. Nếu bạn đã từng làm việc với Entity Framework hoặc các công cụ ORM khác, bạn sẽ thấy họ tạo ra 100 phương thức. Tôi giả sử bạn và đồng nghiệp của bạn đang tự thực hiện nó. Nó không cần thiết một mùi mã, nhưng nó không đẹp để nhìn. Không biết tên miền của bạn, thật khó để nói.


Phương pháp hay tính chất?
JeffO

0

Tôi sử dụng các giao thức (gọi chúng là giao diện nếu bạn muốn) gần như phổ biến cho tất cả các apis với cả FP và OOP. (Ghi nhớ Ma trận? Không có sự cụ thể hóa!) Tất nhiên, có các loại cụ thể nhưng trong phạm vi của một chương trình, mọi loại đều được coi là một cái gì đó đóng vai trò trong một số bối cảnh.

Điều này có nghĩa là các đối tượng được truyền qua các chương trình, vào các chức năng, v.v. có thể được coi là các thực thể trừu tượng với các tập hợp hành vi được đặt tên. Đối tượng có thể được coi là đóng một vai trò là một số giao thức. Một người (loại cụ thể) có thể là một người đàn ông, một người cha, một người chồng, một người bạn và một nhân viên nhưng tôi không thể tưởng tượng được nhiều chức năng sẽ coi thực thể là tổng của hơn 2 trong số đó.

Tôi đoán có thể một đối tượng phức tạp có thể tuân theo một số giao thức khác nhau, nhưng bạn vẫn khó có thể đạt được một api 50 phương thức. Hầu hết các giao thức có 1 hoặc 2 phương thức, có thể 3, nhưng không bao giờ 50! Bất kỳ thực thể nào có 50 phương thức nên được tổng hợp thành một nhóm các thành phần nhỏ hơn, mỗi thành phần có trách nhiệm riêng. Các thực thể nói chung sẽ trình bày một giao diện đơn giản hơn, trừu tượng hóa tổng số apis trong nó.

Thay vì suy nghĩ về các đối tượng và phương pháp, hãy bắt đầu suy nghĩ về mặt trừu tượng và hợp đồng và vai trò của một chủ đề trong một số bối cảnh.

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.