何时使用Encapsulate Collection?

时间:2014-04-28 13:26:31

标签: refactoring

在Martin Fowler在 Refactoring 中描述的气味Data Class中,他建议如果我的班级中有一个收集字段,我应该封装它。

模式 Encapsulate Collection(208)表示我们应该添加以下方法:

  • get_unmodified_collection
  • 方法add_item
  • remove_item

并删除这些:

  • get_collection
  • set_collection

要确保此集合的任何更改都需要通过课程。

我应该重构每个具有此模式的集合字段的类吗?或者它取决于其他一些原因,如使用频率?

我现在在项目中使用C ++。

任何建议都会有所帮助。感谢。

3 个答案:

答案 0 :(得分:2)

这些都是很好的问题,我的答案是:

  

我是否应该使用this重构具有集合字段的每个类   图案?

  • 不,你应该重构每个类都有一个集合字段。每一种原教旨主义都是一种下地狱的方式。使用常识,不要让你的设计太好,只要足够好
  

或者它取决于其他一些原因,如使用频率?

  • 第二个问题来自一个常见的错误。我们重构或使用设计模式的原因主要不是使用频率。我们这样做是为了使代码更清晰,更易于维护,更易于扩展,更易理解,有时(但并非总是如此!)更有效。增加这些目标的一切都很好。没有的一切都很糟糕。

您可能已经预料到是/否答案,但这样的答案是不可能的。如上所述,使用您的常识并从上述观点来衡量您的解决方案。


通常喜欢封装集合的想法。还将普通String封装到命名的业务类中。当这些类在业务域中有意义时,我几乎总是

我总是喜欢

public class People {
    private final Collection<Man> people;
    ... // useful methods
}
Collection<Man>是业务类(域对象)时,

通过普通Man。或者我有时会这样做:

public class People implements Collection<Man> {
    private final Collection<Man> people;

    ... // delegate methods, such as
    @Override
    public int size() {
        return people.size();
    }
    @Override
    public Man get(int index) {
        // Here might also be some manipulation with the returned data etc.
        return people.get(index);
    }
    @Override
    public boolean add(Man man) {
        // Decoration - added some validation
        if (/* man does not match some criteria */) {
            return false;
        }
        return people.add(man);
    }

    ... // useful methods
}

或类似地我更喜欢

public class StreetAddress {
    private final String value;
    public String getTextValue() { return value; }
    ...
    // later I may add more business logic, such as parsing the street address
    // to street name and house number etc.
}

仅仅使用普通String streetAddress - 因此我保持对未来任何基础逻辑变化的开放,并添加任何有用的方法。

但是,我不会在不需要时过度使用我的设计,因此我以及对普通集合和普通String感到满意它更适合。

答案 1 :(得分:1)

我认为这取决于您正在开发的语言。因为已经存在只有C#和Java的接口。在C#中,我们有ICollectionIEnumerableIList。在Java CollectionList

如果你的语言没有一个接口来引用一个集合,而不管它们的内部实现是什么,并且你需要拥有自己的那个类的抽象,那么这样做可能是个好主意。是的,你不应该直接修改集合,因为这完全违背了目的。

如果你告诉我们你正在开发哪种语言,那将会非常有帮助。当然,这是一种与语言无关的问题,但是那些熟悉该语言的人可能会向您推荐最佳实践,并且已经有了实现您所需要的方法。

答案 2 :(得分:1)

Encapsulate Collection背后的动机是减少集合所拥有的类与其客户的耦合。

每次重构都会尝试提高代码的可维护性,因此未来的更改会更容易。在这种情况下,例如,将集合类从向量更改为列表,更改所有客户端&#39;使用该类。如果使用此重构封装此内容,则可以更改集合而无需更改客户端。这遵循SOLID原则,dependency inversion principleDepend upon Abstractions. Do not depend upon concretions.

您必须决定自己的代码库,这是否与您相关,这意味着您的代码库仍然在被更改并且必须进行维护(然后是,为每个类执行)或者不是(不,保留代码。)