2013-01-21 23 views
8

Chúng tôi chỉ đang bắt đầu thực hiện một nỗ lực phối hợp để sử dụng tiêm phụ thuộc thống nhất trong dự án của chúng tôi và tôi đã gặp phải vấn đề.PHP Dependency injection khi các đối số cho hàm tạo không có sẵn

Tôi đang viết một lớp để xử lý các truy vấn MongoDB của mình. Tôi vượt qua trong MongoClient như là một phụ thuộc vào các nhà xây dựng, không có vấn đề. Nhưng làm thế nào để xử lý một phụ thuộc khi biến cần thiết để khởi tạo đối tượng là không có sẵn tại thời điểm instantiation?

Cụ thể, chúng tôi có trình bao bọc cho phương thức MongoCollection, findOne, nếu bạn chuyển một chuỗi vào, hiện tại (trong mã cũ) biến chuỗi đó thành MongoId bằng "MongoId mới ($ _ id)", và sử dụng nó cho hàm find. Từ những gì tôi đã học về tiêm phụ thuộc, có "MongoId mới" là một ý tưởng tồi, và tôi biết rằng nó sẽ làm cho nó khó khăn hơn để viết các trường hợp thử nghiệm cho hàm chuyển đổi một chuỗi thành MongoId.

Nhưng làm cách nào để xử lý việc tiêm, khi lớp MongoId nhận chuỗi id trên hàm tạo?

Điều duy nhất tôi đã nghĩ về điều đó sẽ làm việc là để vượt qua trong một đóng cửa vào constructor lớp đó làm điều gì đó như:

$getMongoId = function($id){ 
    return new MongoId($id); 
}; 

với

class MyMongo 
{ 
    function __construct(MongoClient $client, Closure $mongoIdGetter){...} 
} 

[chỉnh sửa để sửa lỗi này phần cuối cùng]

Nhưng đây có phải là cách phù hợp để xử lý không? Tất nhiên, nếu chúng ta đang sử dụng một DiC, chúng ta có thể làm điều đó, nhưng đòi hỏi một đóng cửa cho constructor có vẻ hơi nhiều. Tôi chỉ là quá giáo điều về việc tiêm phụ thuộc của tôi? Tôi có thể sửa lỗi này một cách dễ dàng bằng cách sử dụng "MongoId mới ($ _ id)" trong lớp mới, tôi cho là vậy.

Trả lời

1

Nhưng làm cách nào để xử lý sự phụ thuộc khi biến cần thiết để khởi tạo đối tượng không có sẵn tại thời điểm diễn ra?

PHP sẽ gây lỗi nghiêm trọng trước khi bạn có cơ hội tự xử lý. Nếu bạn sử dụng các tham số kiểu và/hoặc không xác định chúng như, theo mặc định, null PHP sẽ gây lỗi khi tham số đó không được truyền cho bất kỳ hàm nào.

Từ những gì tôi đã học về tiêm phụ thuộc, có "MongoId mới" là một ý tưởng tồi và tôi biết rằng nó sẽ gây khó khăn hơn khi viết các trường hợp thử nghiệm cho hàm chuyển đổi chuỗi thành MongoId .

Nó sẽ (trong PHPUnit)?

$this->assertInstanceOf('\MongoId', $getMongoId($id_string)); 

Nhưng làm cách nào để xử lý các tiêm, khi lớp MongoId mất chuỗi id trên các nhà xây dựng?

Dunno ý bạn là gì nhưng bạn chỉ nên kiểm tra kết quả xử lý MongoId s.

Câu hỏi cuối cùng của bạn làm tôi thất vọng một chút, tôi nghĩ đó là vì nó không đúng PHP (ví dụ: $__construct).

Tôi không chắc chắn lý do tại sao bạn cần phải chuyển hàm vào lớp như vậy. Ý tôi là những gì tôi có hầu hết thời gian là:

function findById($id){ 
    if(!$id instanceof \MongoId) $id = new MongoId($id); 
    return $this->getCollection()->findOne($id); 
} 

Bạn không cần bất cứ điều gì nhiều hơn thế và bạn không cần phải kiểm tra các nhà xây dựng của MongoId kể từ đó đã được đơn vị kiểm tra, bạn nên thay vì đơn vị thử nghiệm API công cộng của bạn không phải của một số khác.

+0

Cảm ơn - cấu trúc $ __ chỉ là một rắm não, được sửa ở trên. Tôi nghĩ rằng bạn một phần đọc sai câu hỏi của tôi bởi vì khi tôi nói "xử lý" ở trên, tôi không đề cập đến xử lý lỗi, chỉ là ý nghĩa chung của từ đó. – Karptonite

+0

@Karptonite Oh ok, vậy bạn có thể làm rõ tại sao bạn muốn đặt bộ cài MongoId vào trong cấu trúc, tôi hiểu sự phụ thuộc nhưng nó sẽ không cần thiết cho đến khi bạn thực sự sử dụng hàm 'find'. Ý tôi là để kiểm tra đơn vị tất cả những gì bạn cần là kiểm tra phản hồi của chức năng công cộng của bạn rằng nó trả về một tài liệu cần tồn tại trong khi nhập một chuỗi cho '_id', bạn không nên mở rộng thử nghiệm đơn vị của mình tới trình điều khiển MongoDB – Sammaye

+0

Tôi mới dùng tiêm phụ thuộc - nhưng sự hiểu biết của tôi là sử dụng một hàm như bạn đã viết, với "MongoId mới" ngay trong mã, thường là một ý tưởng tồi - ví dụ, nếu tôi sử dụng bất kỳ phương thức nào của MongoId trong mã, tôi không thể giả lập nó để đảm bảo rằng mã của tôi được gọi là các phương thức đó đúng cách. Phải thừa nhận rằng, đó không phải là điều tôi đang làm bây giờ. – Karptonite

2

Thay vì đóng cửa bạn có thể sử dụng một máy:

class MongoFactory 
{ 
    public function createMongoDb($id) 
    { 
     return new MongoId($id); 
    } 
} 

Trong nhà máy nó được coi là không quan trọng để có phụ thuộc cứng mã hoá "một cái gì đó mới" bởi vì việc tạo ra các đối tượng là mục đích duy nhất của họ và bạn có thể dễ dàng thay thế chúng với một nhà máy khác.

Lớp người tiêu dùng (MyMongo) của bạn bây giờ sẽ có sự phụ thuộc vào MongoFactory (hoặc giao diện nếu bạn muốn), bạn có thể dễ dàng "tiêm".

Các vấn đề liên quan