2010-06-25 18 views
7

Giả sử bạn phân chia các hệ thống của bạn trong các đối tượng Giá trị và Dịch vụ (như được đề xuất trong "Phát triển phần mềm hướng đối tượng, được hướng dẫn bằng thử nghiệm" .Misko Hevery gọi đây là "newables" và "injectables".Tiêm phụ thuộc khi lớp được tạo ra cũng cần giá trị thời gian chạy?

Điều gì sẽ xảy ra khi một đối tượng giá trị của bạn đột nhiên cần truy cập dịch vụ để thực hiện các phương thức của nó?

Giả sử bạn có một đối tượng Giá trị đơn giản tốt đẹp, nó không thay đổi, chứa một vài thông tin và đó là về nó. này:

CreditCard card = new CreditCard("4111-1111-1111-1111", "07/10"); 
if (card.isValid()) 
{ 
    // do stuff 
} 
else 
{ 
    // don't do stuff 
} 

Cho đến nay rất tốt. isValid() thực hiện một thuật toán kiểm tra chữ số trên số thẻ và trả về true/false.

Bây giờ, giả sử tôi muốn nâng cao hệ thống bằng cách xác thực ngày hết hạn so với thời gian hiện tại. Làm thế nào bạn sẽ đề nghị điều này được thực hiện mà không vi phạm đối tượng Value/Service object paradim? Tôi muốn lớp này tiếp tục là đơn vị có thể kiểm chứng được.

  • CreditCard hiện có phụ thuộc, nhưng do cách tạo ra nó không thể được tiêm, do đó việc tiêm phụ thuộc bị loại bỏ.
  • Lớp CreditCard không nên được gọi ra để Singletons (tôi của vị trí đó truy cập toàn cầu tới một Singleton là xấu thực hành)
  • Đưa hành vi trên CreditCardVerificationService.validateCard() nghĩa là tất cả các mã hiện có phải được xem xét lại. Việc thực thi isValid() bị rò rỉ.

Tôi biết có những điều có thể được thực hiện để giải quyết vấn đề này, nhưng cách sạch nhất là gì?

Trả lời

4

Tôi cho rằng đó không phải là công việc của đối tượng CreditCard để xác thực bất kỳ điều gì. Một nhà máy sẽ xác nhận các chữ số kiểm tra để đảm bảo rằng nó đang tạo ra một thẻ phù hợp, trong khi một dịch vụ xác minh sẽ xác nhận thẻ cho hết hạn/$ giới hạn.

+0

Thú vị. Nó có vẻ tự nhiên với tôi rằng hành vi (xác nhận) nên sống với dữ liệu thay vì đối tượng CreditCard. –

+4

Điều đó biến thế giới thực trên đầu của nó, mặc dù. Một thẻ tín dụng không có bất kỳ cách nào để xác nhận chính nó - giả mạo, thẻ hết hạn sống trong tự nhiên và không có ý tưởng nếu chúng là hợp lệ hay không. Nếu bạn gửi yêu cầu đến một bộ xử lý thanh toán, họ sẽ không hỏi bạn xem thẻ của bạn có hợp lệ hay không - hãy xác định bản thân và chỉ yêu cầu dữ liệu cần thiết để thực hiện điều đó. – expedient

+0

@WW: Cũng Robert C. Martin "Chú Bob" nói về điều này khi mô tả Nguyên tắc Trách nhiệm duy nhất của SOLID trong ví dụ modem của mình (6 bài viết: http://www.objectmentor.com/resources/articles/srp.pdf). Tôi nghĩ rằng trong quá khứ CreditCard.Validate() sẽ được coi là thiết kế theo hướng đối tượng tốt nhưng xu hướng có vẻ là xa khỏi đó đối với nhiều lớp riêng biệt. Ngoài ra tôi đã hỏi một câu hỏi về điều này trên ProgrammersSE http://programmers.stackexchange.com/questions/77690/design-object-method-vs-separate-classs-method-which-takes-object-as-parameter – User

1

Tôi sẽ bị cám dỗ khi nói rằng CreditCard không phải là đối tượng giá trị.

Từ C2 wiki:

Ví dụ về các đối tượng có giá trị là những thứ số như thế nào, ngày tháng, tiền và chuỗi. Thông thường, chúng nhỏ đối tượng được sử dụng khá rộng rãi. Danh tính của họ dựa trên tiểu bang của họ thay vì trên danh tính đối tượng của họ. Bằng cách này, bạn có thể có nhiều bản sao của cùng một đối tượng giá trị khái niệm.

Đối tượng giá trị không phải là BusinessObject/ReferenceObject. A BusinessObject/ReferenceObject là thứ bạn tìm thấy trên thế giới, trong khi một ValueObject là một thước đo hoặc mô tả về một cái gì đó.

Nếu CreditCardNumber có thể là đối tượng giá trị, CreditCard trông giống một đối tượng kinh doanh có chứa một số logic nghiệp vụ, ví dụ: xác thực.

Tôi thường có đối tượng Giá trị, Dịch vụ và Đối tượng kinh doanh. Tôi không biết về "Phát triển phần mềm hướng đối tượng", nhưng hạn chế bản thân để chỉ đối tượng giá trị và dịch vụ có vẻ kỳ lạ với tôi.

+0

Vì vậy, nếu CreditCard là đối tượng kinh doanh, bạn xử lý tình huống như thế nào trong câu hỏi? –

+0

@WW Tôi khuyên bạn nên xem "Thiết kế Driven Miền". Có rất nhiều tài nguyên về nó. Đây là một cuộc thảo luận về DDD với ví dụ về một thẻ tín dụng http://misko.hevery.com/2009/03/16/design-for-testability-and-domain-driven-design/ – ewernli

0

tôi sẽ gọi CreditCard một thực thể chứ không phải là một đối tượng giá trị , vì nó có khả năng kiên trì và có một bản sắc độc đáo.

Dù sao, nó sẽ là hoàn toàn tốt đẹp cho một lớp thực thể để sử dụng các lớp dịch vụ. Nếu việc triển khai các dịch vụ nói trên không cần phải được chọn khi chạy dựa trên cấu hình bên ngoài, thì tôi sẽ đơn giản khởi tạo và sử dụng lớp dịch vụ mong muốn bên trong phương thức máy khách. Trái ngược với những gì một số người có thể nghĩ, điều này không loại trừ kiểm tra đơn vị, như một công cụ chế nhạo có thể được sử dụng để cô lập.

Nếu triển khai dịch vụ thì cần được chọn khi chạy, so với Dịch vụ định vị có thể được sử dụng. Mô hình này có thể cung cấp hỗ trợ trực tiếp cho chế nhạo/giả mạo, mà không cần một công cụ chế nhạo chuyên dụng. Sử dụng một khuôn khổ DI hỗ trợ tiêm vào các đối tượng "mới" sẽ là một thay thế khác.