代码完整 2ed、组合和委托

发布于 2024-08-25 04:15:08 字数 1426 浏览 9 评论 0原文

在这个论坛上阅读了几周后,我认为是时候发表我的第一篇文章了。

我目前正在重读《Code Complete》。我想距离上次已经有 15 年了,我发现我仍然无法编写代码;-)

无论如何,在 Code Complete 的第 138 页上,您可以找到这个可怕的编码示例。 (我已经删除了一些代码)

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

 bool IsZipCodeValid( Address address);
 ...

private: 
   ...
}

史蒂夫认为不好的是功能相关性松散。或者他写道“员工和检查邮政编码、电话号码或工作分类的例程之间没有逻辑联系”

好吧,我完全同意他的观点。也许像下面的例子这样更好。

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

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

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

检查 zip 是否有效时,您需要执行类似的操作。

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

这对于德米特法则来说并不好。

因此,如果您想删除三个点中的两个,则需要使用委托和几个像这样的包装函数。

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();

但话又说回来,你的例程没有逻辑联系。

我个人认为这篇文章中的三个例子都很糟糕。难道还有其他我没有想到的方式吗?

After a couple of weeks reading on this forum I thought it was time for me to do my first post.

I'm currently rereading Code Complete. I think it's 15 years since the last time, and I find that I still can't write code ;-)

Anyway on page 138 in Code Complete you find this coding horror example. (I have removed some of the code)

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

 bool IsZipCodeValid( Address address);
 ...

private: 
   ...
}

What Steve thinks is bad is that the functions are loosely related. Or has he writes "There's no logical connection between employees and routines that check ZIP codes, phone numbers or job classifications"

Ok I totally agree with him. Maybe something like the below example is better.

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

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

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

When checking if the zip is valid you would need to do something like this.

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

And that is not good regarding to the Law of Demeter.

So if you like to remove two of the three dots, you need to use delegation and a couple of wrapper functions like this.

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();

But then again you have routines that has no logical connection.

I personally think that all three examples in this post are bad. Is it some other way that I haven't thought about?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

燃情 2024-09-01 04:15:08

您缺少逻辑连接:

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();

You are missing the logical connection:

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();
南巷近海 2024-09-01 04:15:08

现在付款与以后付款。

您可以预先编写委托和包装函数(立即付款),然后在稍后更改employee.IsZipCodeValid() 的内部结构即可减少工作量。或者,您可以通过编写隧道到达 IsZipCodeValid

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

everywhere you need it in the code, but pay later should you decide to change your class design in a way which breaks this code.

你可以选择你的毒药。 ;)

It's pay now vs. pay later.

You can write the delegation and wrapper functions up front (pay now) and then have less work changing the innards of employee.IsZipCodeValid() later. Or, you can tunnel through to IsZipCodeValid by writing

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

everywhere you need it in the code, but pay later should you decide to change your class design in a way which breaks this code.

You get to choose your poison. ;)

坦然微笑 2024-09-01 04:15:08

由于 Employee 类和邮政编码验证之间没有逻辑联系,因此您可以将邮政编码验证放入其更逻辑所属的 Address 类中。然后您可以要求 Address 类为您验证邮政编码。

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

那么你做的

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

我认为在你的逻辑联想和德墨忒尔法则的约束下这已经是令人满意的了。

Since there's no logical connection between the Employee class and zip-code validation, you could put the Zip code validation into the Address class where it more logically belongs. Then you can ask the Address class to validate the Zip code for you.

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

Then you do

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

I think this is satisfactory under your constraints of logical association and Law of Demeter.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文