2010-03-11 30 views
5

Sau một vài tuần đọc trên diễn đàn này, tôi nghĩ đã đến lúc tôi đăng bài đầu tiên.Mã Hoàn thành 2ed, thành phần và phái đoàn

Tôi hiện đang đọc lại Mã hoàn thành. Tôi nghĩ rằng đó là 15 năm kể từ lần cuối cùng, và tôi thấy rằng tôi vẫn không thể viết mã ;-)

Dù sao ở trang 138 trong mã Hoàn thành bạn tìm thấy ví dụ kinh dị mã hóa này. (Tôi đã xóa một số mã)

class Emplyee { 
public: 
FullName GetName() const; 
Address GetAddress() const; 
PhoneNumber GetWorkPhone() const; 
... 

bool IsZipCodeValid(Address address); 
... 

private: 
    ... 
} 

Điều Steve cho rằng các chức năng có liên quan lỏng lẻo. Hoặc anh ấy viết "Không có kết nối logic giữa nhân viên và thói quen kiểm tra mã ZIP, số điện thoại hoặc phân loại công việc"

Ok Tôi hoàn toàn đồng ý với anh ấy. Có thể một cái gì đó giống như ví dụ dưới đây là tốt hơn.

class ZipCode 
{ 
public: 
bool IsValid() const; 
    ... 
} 

class Address { 
public: 
    ZipCode GetZipCode() const; 
    ... 
} 

class Employee { 
public: 
Address GetAddress() const; 
    ... 
} 

Khi kiểm tra xem mã zip có hợp lệ thì bạn sẽ cần phải làm điều gì đó như thế này không.

employee.GetAddress().GetZipCode().IsValid(); 

Và điều đó không tốt liên quan đến Law of Demeter.

Vì vậy, nếu bạn muốn loại bỏ hai trong ba dấu chấm, bạn cần phải sử dụng ủy nhiệm và một vài hàm bao bọc như thế này.

class ZipCode 
{ 
public: 
bool IsValid(); 
} 

class Address { 
public: 
    ZipCode GetZipCode() const; 
    bool IsZipCodeValid() {return GetZipCode()->IsValid()); 
} 

class Employee { 
public: 
FullName GetName() const; 
Address GetAddress() const; 
bool IsZipCodeValid() {return GetAddress()->IsZipCodeValid()); 
PhoneNumber GetWorkPhone() const; 
} 

employee.IsZipCodeValid(); 

Nhưng sau đó lại có các quy trình không có kết nối logic.

Cá nhân tôi nghĩ rằng cả ba ví dụ trong bài đăng này đều không hợp lệ. Có cách nào khác mà tôi chưa từng nghĩ đến không?

+0

Tôi biết rất nhiều lập trình viên yêu mã hoàn chỉnh, nhưng thành thực mà tôi chưa từng làm. Đó là một đọc rất nhàm chán. – JonH

+0

Điều đó tùy thuộc vào thời điểm bạn đọc. Nếu bạn là một nhà phát triển cơ sở thì đó là một bài đọc tốt.Nếu bạn là một nhà phát triển có kinh nghiệm tôi đoán những điều được viết trong cuốn sách chỉ có ý nghĩa, mà không có một cái gì đó phi thường. –

+1

@ JonH Tôi đồng ý - cuốn sách hay nhất của ông thực sự là "Phát triển nhanh", mà ít người dường như đã đọc - nó rất tuyệt. –

Trả lời

1

Đó là trả tiền ngay vs trả sau.

Bạn có thể viết các hàm đại biểu và hàm bao lên phía trước (trả tiền ngay bây giờ) và sau đó có ít công việc thay đổi nội bộ của nhân viên.IsZipCodeValid() sau này. Hoặc, bạn có thể hầm qua IsZipCodeValid bằng cách viết

employee.GetAddress().GetZipCode().IsValid();
ở mọi nơi bạn cần trong mã, nhưng thanh toán sau đó bạn nên quyết định thay đổi thiết kế lớp theo cách phá vỡ mã này.

Bạn có thể chọn chất độc. ;)

+0

Đây có lẽ là câu trả lời hay nhất. Bởi vì họ không phải là giải pháp thanh lịch cho vấn đề. – Arlukin

7

Bạn đang thiếu các kết nối logic:

class ZipCode 
{ 
public: 
bool IsValid(); 
} 

class Address { 
public: 
    ZipCode GetZipCode() const; 
    bool IsAddressValid(); 
    bool IsValid() {return GetZipCode()->IsValid() && IsAddressValid()); 
} 

class Employee { 
public: 
FullName GetName() const; 
Address GetAddress() const; 
bool IsEmployeeValid(); 
bool IsValid() {return GetAddress()->IseValid() && IsEmployeeValid()); 
PhoneNumber GetWorkPhone() const; 
} 

employee.IsValid(); 
+0

Bạn vẫn sẽ cần phải đi sâu vào 'ZipCode :: IsValid()' cuối cùng. Bạn gọi 'employee.IsValid()' và nó trả về false. OK, tại sao nhân viên không hợp lệ? Vì vậy, bạn gọi 'employee.GetAddress(). IsValid()', và nó trả về false. OK, tại sao địa chỉ không hợp lệ? Vì vậy, bạn gọi 'employee.GetAddress(). GetZipCode(). IsValid()' và bạn quay trở lại vấn đề ban đầu. – indiv

+0

Ngoài ra, bạn có thể muốn gọi GetValue() trên Mã Zip, để xuất trong hộp thoại hoặc trang web. Điều đó sẽ cho bạn cùng một vấn đề. – Arlukin

+0

@indiv, nếu bạn định lấy ví dụ này theo giá trị khuôn mặt thì bạn cần phải xem chi tiết theo cách đó nhưng có thể bạn sẽ có phương pháp thay thế cho bạn và trình bày lại dữ liệu/thông báo lỗi cho dữ liệu màn hình nhập cảnh. Nếu trạng thái không hợp lệ này là kết quả của dữ liệu xấu trong ứng dụng thì tôi nghĩ rằng câu trả lời là tìm cách làm sạch dữ liệu trước khi tiêm nó vào mô hình của bạn. – Lazarus

0

Vì không có kết nối logic giữa lớp Employee và xác thực mã zip, bạn có thể đặt xác thực mã Zip vào lớp Địa chỉ nơi nó hợp lý hơn. Sau đó, bạn có thể yêu cầu lớp Địa chỉ xác thực mã Zip cho bạn.

class Address 
{ 
    public: 
     static IsZipValid(ZipCode zip) { return zip.isValid(); } 
}; 

Sau đó, bạn làm

Address::IsZipValid(employee.GetAddress().GetZipCode()); 

Tôi nghĩ rằng đây là thỏa đáng dưới khó khăn của bạn của hiệp hội hợp lý và Luật của Demeter.

+0

Nhưng bạn có thực sự thắng bất cứ điều gì với điều đó không? Có lẽ là một câu hỏi về sở thích cá nhân, nhưng tôi nghĩ rằng nhiều dấu chấm dễ đọc hơn. Địa chỉ :: IsZipValid (employee.GetAddress(). GetZipCode()); vs employee.GetAddress() GetZipCode(). IsZipValid(); – Arlukin

+0

@Arlukin: Không, tôi không tin bạn có được gì cả. Tôi chỉ trả lời câu hỏi như đặt ra. Demeter không áp đặt luật pháp cho tôi, vì vậy tôi sẽ thực hiện nó như là employee.GetAddress() GetZipCode.IsZipValid(). Bằng cách đó, tôi cảm thấy tự nhiên. – indiv

+0

@Arlukin, đây không phải là về chiến thắng hay thua, đó là về xây dựng mô hình có ý nghĩa. Nếu, vào cuối ngày, một cách cảm thấy tự nhiên hơn bạn và bạn không phải là thành viên của nhóm (nếu bạn đang hướng dẫn nhóm) thì hãy làm theo bất cứ điều gì có ý nghĩa với bạn. Tôi chắc chắn nếu bạn có hai người lập trình vào một căn phòng bạn sẽ nhận được sáu ý kiến ​​về cách viết mã một giải pháp nhất định;) – Lazarus

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