Tránh các nhà xây dựng có nhiều đối số


10

Vì vậy, tôi có một nhà máy tạo ra các đối tượng của các lớp khác nhau. Các lớp có thể đều bắt nguồn từ một tổ tiên trừu tượng. Nhà máy có tệp cấu hình (cú pháp JSON) và quyết định lớp nào sẽ được tạo, tùy thuộc vào cấu hình của người dùng.

Để đạt được điều này, nhà máy sử dụng boost :: property_tree để phân tích cú pháp JSON. Anh ta đi qua ptree và quyết định sẽ tạo ra vật thể cụ thể nào.

Tuy nhiên, các đối tượng sản phẩm có nhiều trường (thuộc tính). Tùy thuộc vào lớp cụ thể, đối tượng có khoảng 5-10 thuộc tính, trong tương lai có thể còn nhiều hơn nữa.

Vì vậy, tôi không chắc chắn cách xây dựng của các đối tượng sẽ trông như thế nào. Tôi có thể nghĩ về hai giải pháp:

1) Hàm tạo của sản phẩm hy vọng mọi thuộc tính là tham số, do đó, hàm tạo sẽ kết thúc với hơn 10 tham số. Điều này sẽ xấu và dẫn đến các dòng mã dài, không thể đọc được. Tuy nhiên, lợi thế là nhà máy có thể phân tích cú pháp JSON và gọi hàm tạo với các tham số chính xác. Lớp sản phẩm không cần biết rằng nó đã được tạo do cấu hình JSON. Không cần biết có JSON hay cấu hình nào liên quan.

2) Hàm tạo của sản phẩm chỉ mong đợi một đối số, đối tượng property_tree. Sau đó, nó có thể phân tích các thông tin cần thiết. Nếu thông tin trong cấu hình bị thiếu hoặc nằm ngoài giới hạn, mỗi lớp sản phẩm có thể phản ứng đúng. Nhà máy không cần biết những đối số nào cần thiết cho một số sản phẩm. Nhà máy cũng không cần biết cách phản ứng trong trường hợp cấu hình sai. Và giao diện constructor là thống nhất và nhỏ. Nhưng, như một bất lợi, sản phẩm cần trích xuất thông tin cần thiết từ JSON, do đó, nó biết cách nó được xây dựng.

Tôi có xu hướng thích giải pháp 2). Tuy nhiên, tôi không chắc đây có phải là mẫu nhà máy tốt không. Cảm thấy có phần sai khi cho sản phẩm biết rằng nó được tạo bằng cấu hình JSON. Mặt khác, các sản phẩm mới có thể được giới thiệu rất đơn giản.

Bất kỳ ý kiến ​​về điều đó?



1
Tôi theo liên kết của bạn. Có một ví dụ trong câu trả lời được đánh giá cao nhất từ ​​quái vật ratchet. Nhưng vấn đề nào "người xây dựng" -approach này giải quyết? Có dữ liệu dòng mã DataClass = builder.createResult ();. Nhưng phương thức createResults () - vẫn phải lấy 10 tham số vào đối tượng DataClass. Nhưng bằng cách nào? Có vẻ như bạn chỉ có thêm một lớp trừu tượng, nhưng hàm tạo của DataClass không trở nên nhỏ hơn.
lugge86

Có một cái nhìn vào xây dựng và nguyên mẫu.
Silviu Burcea

Silviu Burcea, tôi đã làm. Tuy nhiên, khi sử dụng trình xây dựng, làm thế nào để người xây dựng có được các tham số vào sản phẩm? Ở đâu đó đã có một giao diện béo. Trình xây dựng chỉ là một lớp nữa, nhưng bằng cách nào đó các tham số phải tìm đường vào lớp sản phẩm.
lugge86

1
Nếu lớp của bạn quá lớn, việc thay đổi xung quanh các đối số của hàm tạo sẽ không làm cho nó không quá lớn .
Telastyn

Câu trả lời:


10

Tôi sẽ không thực hiện tùy chọn 2, vì sau đó bạn đã kết thúc việc xây dựng đối tượng của mình bằng cách phân tích cú pháp cây thuộc tính. Nếu bạn cảm thấy thoải mái với một lớp cần nhiều tham số đó, bạn nên thoải mái với một hàm tạo cần nhiều tham số đó, chẳng hạn như cuộc sống!

Nếu mối quan tâm chính của bạn là khả năng đọc mã, bạn có thể sử dụng mẫu trình xây dựng, về cơ bản đó là điểm dừng c ++ / java vì thiếu các đối số được đặt tên. Bạn kết thúc với những thứ trông như thế này:

MyObject o = MyObject::Builder()
               .setParam1(val1)
               .setParam2(val2)
               .setParam3(val3)
             .build();

Vì vậy, bây giờ MyObject sẽ có một hàm tạo riêng, được gọi trong Builder :: build. Điều tuyệt vời là đó sẽ là nơi duy nhất bạn từng phải gọi một hàm tạo với 10 tham số. Nhà máy cây thuộc tính boost sẽ sử dụng trình xây dựng và sau đó nếu bạn muốn xây dựng MyObject trực tiếp hoặc từ một nguồn khác, bạn sẽ đi qua trình xây dựng. Và trình xây dựng về cơ bản cho phép bạn đặt tên rõ ràng cho từng tham số khi bạn chuyển nó vào, vì vậy nó dễ đọc hơn. Điều này rõ ràng sẽ thêm một số mẫu soạn sẵn, vì vậy bạn sẽ phải quyết định xem nó có đáng không so với việc chỉ gọi hàm tạo lộn xộn hoặc gộp một số tham số hiện có của bạn vào các cấu trúc, v.v. Chỉ cần ném một tùy chọn khác lên bàn.

https://en.wikipedia.org/wiki/Builder_potype#C.2B.2B_Example


5

KHÔNG sử dụng cách tiếp cận thứ hai.

Nó chắc chắn không phải là giải pháp và sẽ chỉ dẫn đến các lớp khởi tạo trong logic kinh doanh của bạn, thay vì một phần của ứng dụng của bạn nơi các nhà máy đang ở.

Hoặc:

  • cố gắng nhóm các tham số nhất định dường như thể hiện những điều tương tự thành các đối tượng
  • chia lớp hiện tại thành nhiều lớp nhỏ hơn (có một lớp dịch vụ với 10 tham số có vẻ như lớp đó làm quá nhiều thứ)
  • cứ để nguyên như vậy, nếu lớp của bạn không thực sự là một dịch vụ, mà là một đối tượng giá trị thay thế

Trừ khi đối tượng bạn đang tạo thực sự là một lớp chịu trách nhiệm lưu trữ dữ liệu, bạn nên cố gắng cấu trúc lại mã và chia lớp lớn thành các lớp nhỏ hơn.


Chà, logic bsiness đang sử dụng một nhà máy trả về các sản phẩm, do đó, logic nghiệp vụ không nhìn thấy các công cụ JSON / ptree. Nhưng tôi thấy quan điểm của bạn, có mã Parser trong construcotr cảm thấy sai.
lugge86

Lớp này đại diện cho một widget trong GUI cho một hệ thống nhúng, do đó, 5+ thuộc tính có vẻ ổn đối với tôi: x_coord, y_coord, backgroundcolor, framesize, framecolor, văn bản ...
lugge86

1
@ lugge86 Mặc dù bạn đang sử dụng một nhà máy để phân tích JSON, và do đó tránh gọi newhoặc xây dựng các đối tượng bên trong logic nghiệp vụ của bạn, nó không phải là một thiết kế tốt. Kiểm tra Đừng tìm kiếm những điều được nói bởi Miško Hevery , người giải thích sâu hơn lý do tại sao cách tiếp cận nhà máy mà bạn gợi ý là không tốt từ cả quan điểm kiểm tra và đọc. Ngoài ra, lớp của bạn dường như là một đối tượng dữ liệu và đối với những người đó thường có nhiều tham số hơn so với lớp dịch vụ thông thường. Tôi sẽ không quá bận tâm.
Andy

Tôi cảm thấy ổn với cách tiếp cận nhà máy của mình, nhưng tôi sẽ theo liên kết của bạn và suy nghĩ về nó. Tuy nhiên, nhà máy không có vấn đề trong chủ đề này. Câu hỏi vẫn là làm thế nào để thiết lập các sản phẩm ...
lugge86

"Có một lớp dịch vụ với 10 tham số có vẻ như lớp đó làm quá nhiều thứ" Không phải trong học máy. Bất kỳ thuật toán ML sẽ có hàng tấn các tham số có thể điều chỉnh. Tôi tự hỏi đâu là cách đúng đắn để đối phó với điều đó khi mã hóa ML.
Siyuan Ren

0

Lựa chọn 2 là gần như đúng.

Một lựa chọn cải tiến 2

Tạo một lớp "mặt trước", công việc của nó là lấy đối tượng cấu trúc JSON đó và chọn ra các bit và gọi (các) hàm tạo của nhà máy. Nó lấy những gì nhà máy làm và đưa nó cho khách hàng.

  • Nhà máy hoàn toàn không biết rằng một thứ JSON như vậy thậm chí còn tồn tại.
  • Khách hàng không phải biết các bit cụ thể mà nhà máy cần.

Về cơ bản, "mặt trước" đang nói với 2 Bobs: "Tôi đối phó với các khách hàng đã được tái cấu trúc để các kỹ sư không phải! Tôi có kỹ năng của mọi người!" Tội nghiệp Tom. Nếu anh ta chỉ nói "Tôi tách khách hàng khỏi công trình. Kết quả này là một nhà máy rất gắn kết"; anh ấy có thể đã giữ công việc của mình.

Quá nhiều lý lẽ?

Không cho khách hàng - giao tiếp kết thúc.

Mặt trước - nhà máy? Nếu không phải là 10 tham số thì điều tốt nhất bạn có thể làm là tắt giải nén, nếu không phải là điều JSON ban đầu thì một số DTO. Điều này có tốt hơn việc chuyển JSON đến nhà máy không? Tôi nói khác nhau.

Tôi mạnh mẽ sẽ xem xét thông qua các tham số cá nhân. Bám sát mục tiêu của một nhà máy sạch sẽ, gắn kết. Tránh những mối quan tâm của câu trả lời @DavidPacker.

Giảm thiểu "quá nhiều tranh luận"

  • Xây dựng nhà máy hoặc lớp

    • chỉ lấy các đối số để xây dựng lớp / đối tượng cụ thể.
    • tham số mặc định
    • tham số tùy chọn
    • đối số được đặt tên
  • Nhóm đối số kết thúc

    • Kiểm tra, đánh giá, xác nhận, bộ, vv các giá trị đối số được hướng dẫn bởi các chữ ký của hàm tạo ở trên.

"Nhà máy hoàn toàn không biết rằng một thứ JSON như vậy thậm chí còn tồn tại" - vậy thì, nhà máy dùng để làm gì ?? Nó che giấu các chi tiết tạo ra sản phẩm từ cả, sản phẩm và người tiêu dùng. Tại sao một lớp học khác cần giúp đỡ? Tôi ổn với nhà máy nói JSON. Người ta có thể triển khai một nhà máy khác để phân tích cú pháp XML và triển khai "Nhà máy trừu tượng" trong tương lai ...
lugge86

Ông Factory: "Bạn muốn đối tượng nào? ... Đó là gì? Chỉ cần cho tôi biết đối tượng lớp nào sẽ được xây dựng." Tệp cấu hình JSON là một nguồn dữ liệu, như chú Bob nói "đó là một chi tiết triển khai." Nó có thể từ một nguồn khác và / hoặc ở dạng khác. Nói chung, chúng tôi muốn tách rời các chi tiết nguồn dữ liệu cụ thể. Nếu nguồn hoặc hình thức thay đổi, nhà máy sẽ không. Đưa ra một nguồn + trình phân tích cú pháp và một nhà máy dưới dạng các mô-đun tách rời làm cho cả hai có thể sử dụng lại.
radarbob
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.