Cách tránh vi phạm Luật của Demeter (Các đối tượng có thể tạo mới không nên giữ tham chiếu trường đến một đối tượng có thể tiêm chích)


7

Trong Quy tắc sử dụng phép nội xạ phụ thuộc , trạng thái devdocs Magento 2:

Các đối tượng mới có thể không giữ tham chiếu trường đến một đối tượng có thể tiêm và cũng không nên yêu cầu một đối tượng trong hàm tạo của chúng. Đây là một luật của Demeter vi phạm.

Tôi hiểu rằng đây là một mục tiêu tốt để có, nhưng làm thế nào điều này thực sự có thể với các mô hình Magento 2?

Nếu chúng ta nhìn vào mô-đun Khách hàng, được trình bày như một ví dụ sáng chói cho kiến ​​trúc mới, chữ ký của nhà xây dựng mô hình khách hàng trông như thế này:

public function __construct(
    \Magento\Framework\Model\Context $context,
    \Magento\Framework\Registry $registry,
    \Magento\Store\Model\StoreManagerInterface $storeManager,
    \Magento\Eav\Model\Config $config,
    \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
    \Magento\Customer\Model\ResourceModel\Customer $resource,
    \Magento\Customer\Model\Config\Share $configShare,
    \Magento\Customer\Model\AddressFactory $addressFactory,
    \Magento\Customer\Model\ResourceModel\Address\CollectionFactory $addressesFactory,
    \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder,
    GroupRepositoryInterface $groupRepository,
    \Magento\Framework\Encryption\EncryptorInterface $encryptor,
    \Magento\Framework\Stdlib\DateTime $dateTime,
    CustomerInterfaceFactory $customerDataFactory,
    DataObjectProcessor $dataObjectProcessor,
    \Magento\Framework\Api\DataObjectHelper $dataObjectHelper,
    \Magento\Customer\Api\CustomerMetadataInterface $metadataService,
    \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
    \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
    array $data = []
)

Magento\Framework\Model\Contextmột mình, được sử dụng bởi tất cả các mô hình, có năm đối số có thể tiêm được .

Rõ ràng mô hình, mặc dù newable , không phải là một tấm gương tốt ở tất cả cho quy tắc này.

Tôi muốn tuân theo các thực tiễn tốt nhất với các lớp của riêng tôi (thậm chí không phải mô hình), nhưng tôi cần quyền truy cập vào những thứ như kho lưu trữ của các thực thể liên quan hoặc cho người quản lý sự kiện. Điều gì sẽ là cách ưa thích để xử lý việc này mà không vi phạm quy tắc từ trên?

Tôi hiện đang có xu hướng bỏ qua nó hoặc tốt nhất xem nó là hướng dẫn thân thiện, không phải là một quy tắc.

Câu trả lời:


2

Trong ví dụ này, tôi nghĩ rằng một phần lớn của logic mô hình phải được trích xuất vào các lớp dịch vụ bên ngoài, thực thi mã trên mô hình.

Theo cách này, ví dụ khi tải mô hình qua kho lưu trữ, lớp kho lưu trữ sẽ có các phụ thuộc vào các lớp dịch vụ mới có các phụ thuộc vào các lớp hiện có trong hàm tạo của mô hình.

Tôi nghĩ với tư cách là nhà phát triển mở rộng, chúng tôi có thể cố gắng tuân thủ các quy tắc, nhưng vẫn còn nhiều thao tác tái cấu trúc được thực hiện bởi magento.

=== chỉnh sửa ===

Chúng tôi tìm thấy một cái gì đó mới. Trong Mô-đun khách hàng, Mô hình được chia thành Mô hình dữ liệu và Lớp dịch vụ (Mô hình ban đầu).

Đối với DataInterface, bây giờ DataModel đã được chèn: https://github.com/magento/magento2/blob/develop/app/code/Magento/Customer/etc/di.xml#L17

Mô hình Dữ liệu chỉ chứa dữ liệu và không có logic nghiệp vụ: https://github.com/magento/magento2/blob/develop/app/code/Magento/Customer/Model/Data/Customer.php

Vì vậy, bây giờ Mô hình ban đầu có thể được xem như là một Lớp dịch vụ chứa logic nghiệp vụ chỉ làm cho nó hoàn toàn ổn khi nó tham chiếu các hàm tiêm khác.


Tìm tốt Nhưng mô hình ban đầu vẫn không được tiêm . Có lẽ đây chỉ là một bước tái cấu trúc? Và chúng ta không nên nhầm lẫn "không phụ thuộc vào dịch vụ" với "không logic kinh doanh". Làm giảm các mô hình xuống các đối tượng dữ liệu đơn giản đang trở nên cực đoan khác và IMHO không phải là thứ để phấn đấu.
Fabian Schmengler

1
ok, nhưng thật khó để bao gồm nhiều logic kinh doanh mà không tiêm chích (điều này nghe có vẻ khó hiểu). Vì vậy, tôi nghĩ rằng đó là một bước tốt để phân chia chúng. Mô hình ban đầu trở thành một mũi tiêm ngay khi nó mất đi bản sắc của nó phải không? Tôi nghĩ việc phản đối các phương thức lưu và tải và trích xuất mô hình dữ liệu là bước đầu tiên thực hiện việc này. Bước tiếp theo có thể là loại bỏ mô hình "cũ" hoàn chỉnh và ủy thác các chức năng cho các lớp nhỏ hơn, phù hợp hơn
David Verholen

1

Chúng tôi đang cố gắng để mọi người tránh khỏi việc truy cập trực tiếp vào mã bên trong một mô-đun và thay vào đó thông qua API được kiểm soát tốt hơn, được xác định rõ hơn. Mục tiêu là cho phép cập nhật mượt mà hơn giữa các bản phát hành - càng nhiều người sử dụng API được xác định, các bản nâng cấp sẽ càng mượt mà.

Một khái niệm quan trọng trong các tệp di.xml là phần tử "ưu tiên". Nó cho phép mã để tham chiếu các định nghĩa giao diện (và do đó không bị ràng buộc với một triển khai cụ thể), nhưng khi bạn hỏi một ví dụ, nó biết lớp nào sẽ sử dụng.

Vì vậy, nếu bạn muốn có một cá thể CustomerInterface (đó là một lớp thực hiện giao diện), thì bạn yêu cầu một thể hiện của giao diện (bạn không tìm kiếm lớp triển khai). Chúng tôi sẽ tìm kiếm một yếu tố cho bạn và sử dụng yếu tố đó để xác định lớp thực hiện. Bằng cách đó, một mô-đun khác có thể thay thế tùy chọn tệp di.xml và trao đổi trong một lớp triển khai khác (nếu có lý do chính đáng để làm như vậy).

Ngoài ra, khi bạn tạo các đối tượng thông qua trình quản lý đối tượng theo cách này, bạn không phải chỉ định các đối số cho danh sách hàm tạo. Trình quản lý đối tượng một lần nữa sử dụng tệp di.xml để tìm tất cả các cấu trúc dữ liệu cần thiết và tự động cung cấp chúng cho hàm tạo.

Sự khác biệt giữa "các lớp dịch vụ" và "mô hình dữ liệu" trong một câu trả lời riêng là "các lớp dịch vụ" (mà tôi giả sử có nghĩa là các giao diện trong thư mục Api) cung cấp các phương thức được gọi. "Các mô hình dữ liệu" (mà tôi giả sử có nghĩa là các giao diện trong thư mục Api / Dữ liệu) là các cấu trúc dữ liệu được truyền đến / từ "các lớp dịch vụ". Mục tiêu là để ai đó bên ngoài mô-đun không cần biết lớp nào đang thực hiện các giao diện. Nó có thể là một mô hình, nó có thể là một đối tượng giá trị, nó không quan trọng miễn là bạn lập trình với các giao diện và không bao giờ đề cập trực tiếp đến tên lớp (trừ tệp di.xml).

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.