Tĩnh là xấu, nhưng còn mẫu Factory thì sao?


13

Tôi đang tham gia một dự án TDD, vì vậy tôi cố gắng gắn bó hết mức có thể với những điều tốt đẹp liên quan đến loại phát triển đó. Một trong số đó là tránh càng nhiều càng tốt tĩnh và toàn cầu.

Tôi đang đối mặt với vấn đề này: Tôi có một "bài báo" đối tượng có thể có "tùy chọn" (bổ sung "bài báo vi mô") liên kết với nó.

Tôi không thể tìm ra cách để có một cách tiếp cận tốt sẽ không phản tác dụng hoặc tạo ra quá nhiều truy vấn vì tôi sẽ ở trong tình huống mọi thứ bị tách rời đến mức về cơ bản tôi sẽ cần thực hiện 1 truy vấn cho mỗi đối tượng.

Từ quan điểm thực tế của tôi, tôi thấy 3 tùy chọn:

1) Xây dựng bên trong bài viết:

class Article
{
    //[...]
    public function getArrOption(){
        //Build an array of Options instance.
        //return an array of Options.
    }
}

Pro: Thẳng tiến

Const: Khả năng bảo trì: Đối tượng bài viết hiện chứa logic xây dựng cho đối tượng Tùy chọn. Điều này có thể sẽ dẫn đến sao chép mã.

2) Sử dụng tùy chọnFactory

class Article
{
    //[...]
    public function getArrOption(){
        return OptionFactory::buildFromArticleId($this->getId());
    }
}

Pro: Logic xây dựng không nằm ngoài lớp Article

Const: Tôi đang phá vỡ quy tắc "tĩnh rất khó để chế giễu", khiến lớp Bài viết của tôi khó kiểm tra.

3) Tách tất cả các logic.

//Build the array of Option instance in a controller somewhere, using a Factory:
$arrOption = OptionFactory::buildFromArticleId($article->getId());

Pro: Bài viết chỉ xử lý khả năng đáp ứng của chính anh ấy và không quan tâm đến liên kết "cha" của anh ấy với các tùy chọn. Mọi thứ thực sự tách rời

Const: Sẽ yêu cầu nhiều mã hơn trong Bộ điều khiển mọi lúc tôi sẽ cần truy cập Tùy chọn. Điều đó có nghĩa là tôi không bao giờ nên sử dụng Factory bên trong một vật thể, và điều đó nghe có vẻ không tưởng với tôi ...

Cách tốt nhất để đi là gì? (Tôi đã bỏ lỡ điều gì à?) Cảm ơn.

Biên tập:

Chưa kể rằng nếu tôi không thể gọi nhà máy bên trong lớp, tôi có thể không bao giờ sử dụng mô hình khởi tạo lười biếng ...


Tôi không chắc nó có thích hợp không, nhưng tôi đang viết mã bằng PHP, vì vậy "ứng dụng" ở trạng thái ít hơn. Chúng tôi phải tải lại tất cả dữ liệu giữa mỗi trang nếu nó không được lưu trong cookie phiên. Điều đó có nghĩa là chúng ta không thể tải trước mọi thứ như trong ngôn ngữ ứng dụng.
FMaz008

@job: Vâng, bởi vì một cuộc gọi tĩnh bên trong một phương thức hầu như không thể thay thế khi kiểm tra đơn vị. Mục tiêu là sử dụng tiêm phụ thuộc. Nhưng một nhà máy thường là tĩnh, vì vậy nó không thể được tiêm.
FMaz008

Câu trả lời:


12
  1. Tĩnh không "xấu", nó không thể thay đổi. Bạn vẫn có thể sử dụng nó khi chế nhạo không có ý nghĩa.

  2. Đó không phải là mẫu Factory, nó trông giống như mẫu Rep Storage, mặc dù có thể không phải vậy. Factory là nơi bạn có nhiều lớp với cùng một lớp giao diện / lớp cơ sở và bạn muốn tách ra logic để quyết định lớp nào sẽ trả về. Kho lưu trữ lấy dữ liệu từ kho lưu trữ của nó, trừu tượng hóa việc triển khai kho lưu trữ đó (Điều không cần biết nếu các tùy chọn của nó được lưu trữ trong cùng một DB, một tệp khác, tệp XML, tệp CSV, bất cứ điều gì).

  3. Bạn đã bỏ qua khả năng cung cấp cho lớp Article một đối tượng ObjectFactory (hoặc Kho lưu trữ hoặc bất cứ thứ gì) trong hàm tạo mà nó có thể gọi phương thức buildFromArticle.

PHP của tôi bị gỉ, nhưng tôi nghĩ nó trông như thế này:

class Article
{
    private $_option_repository;

    public function __construct($option_repository) {
        $_option_repository = $option_repository;
    }

    //[...]

    public function getArrOption(){
        return $_option_repository->buildFromArticleId($this->getId());
    }
}

Tôi nghĩ rằng điều này đáp ứng tất cả các ưu điểm của bạn ở trên.


Vì vậy, có thể có các phiên bản của Nhà máy / Kho lưu trữ / Mapper không? Tôi sẽ cần một thùng chứa phụ thuộc hoặc một cái gì đó bởi vì nếu chúng ta cần tiêm tất cả nhà máy / kho lưu trữ / ánh xạ cho tất cả các đối tượng có thể có thể được trả về bởi một đối tượng, điều đó sẽ nhanh chóng tạo ra rất nhiều. (Bài viết -> Nhóm tùy chọn -> Tùy chọn -> Bài viết, v.v.)
FMaz008

1
Nó tốt hơn ok, nó là tốt hơn. Tôi thường bảo lưu việc sử dụng tĩnh để loại bỏ mã lặp lại, trong đó nó đủ nhỏ để được kiểm tra trong nhiều lớp. Và vâng, một IOC / DI Container sẽ giúp cuộc sống của bạn dễ dàng hơn rất nhiều. Sử dụng một.
pdr

1

Đây là một trích dẫn từ bài báo cho rằng bạn không bao giờ cần các phương pháp tĩnh, rằng các nhà máy trừu tượng đã được chứng minh là khó hiểu và gợi ý một sự thay đổi ngôn ngữ nhỏ đối với việc tiêm phụ thuộc là giải pháp.

Sự kết hợp chặt chẽ giữa các thể hiện và các lớp của chúng phá vỡ sự đóng gói và cùng với khả năng hiển thị toàn cầu của các phương thức tĩnh, làm phức tạp việc kiểm tra. Bằng cách biến nội dung phụ thuộc thành một tính năng của ngôn ngữ lập trình, chúng ta có thể loại bỏ hoàn toàn các phương thức tĩnh. Chúng tôi sử dụng các thay đổi ngữ nghĩa sau:

(1) Thay thế mọi sự xuất hiện của toàn cầu bằng quyền truy cập vào một biến thể hiện;

(2) Để biến cá thể đó được tự động đưa vào đối tượng khi nó được khởi tạo.

"Seuss: Phân tách trách nhiệm từ các phương thức tĩnh đối với cấu hình hạt mịn"

Liên kết máy Wayback


3
Mặc dù liên kết này có thể trả lời câu hỏi, tốt hơn là bao gồm các phần thiết yếu của câu trả lời ở đây và cung cấp liên kết để tham khảo. Câu trả lời chỉ liên kết có thể trở nên không hợp lệ nếu trang được liên kết thay đổi.
gnat
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.