简体   繁体   English

代码完成2ed,组成和委托

[英]Code Complete 2ed, composition and delegation

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. 我目前正在重读Code Complete。 I think it's 15 years since the last time, and I find that I still can't write code ;-) 我认为这是自上次以来的15年,我发现我仍然无法编写代码;-)

Anyway on page 138 in Code Complete you find this coding horror example. 无论如何,在Code Complete的第138页,你会发现这个编码恐怖的例子。 (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? 这是我没想过的其他方式吗?

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

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. 您可以预先编写委托和包装函数(立即付款),然后更少的工作更改employee.IsZipCodeValid()的内部。 Or, you can tunnel through to IsZipCodeValid by writing 或者,您可以通过写入隧道传输到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. 您需要在代码中的任何地方,但如果您决定以破坏此代码的方式更改您的类设计,请稍后付款。

You get to choose your poison. 你可以选择你的毒药。 ;) ;)

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. 由于Employee类和zip-code验证之间没有逻辑连接,因此您可以将Zip代码验证放入更符合逻辑的Address类中。 Then you can ask the Address class to validate the Zip code for you. 然后,您可以要求Address类为您验证Zip代码。

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. 我认为在你的逻辑关联和德米特定律的约束下,这是令人满意的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM