开发者

When should you encapsulate generic types?

I've seen a number of people suggest that you should encapsulate generic types with a class closer to your domain, for example Steve and Nat suggest in Growing Object-Oriented Software, Guided by Tests that:

Our rule of thumb is that we try to limit passing around types with generics [...]. Particularly when applied to collections, we view it as a form of duplication. It’s a hint that there’s a domain concept that should be extracted into a type.

In general, when is it a good idea to do something like this ..

class PersonL开发者_如何学运维ist : List<Person>

.. rather than just using List<Person> directly?


What you are looking for is a typedef operator for Java or C#.

Unfortunately subclassing approach is not a good substitute for typedef.

The following article "Java theory and practice: The pseudo-typedef antipattern" explains why in full detail.

I will copy verbatim the conclusion of that article here:

The motivation for the pseudo-typedef antipattern is straightforward enough -- developers want a way to define more compact type identifiers, especially as generics make type identifiers more verbose. The problem is that this idiom creates tight coupling between code that employs it and that code's clients, inhibiting reuse. You may not like the verbosity of generic type identifiers, but this is not the way to solve it.


I disagree with that philosophy. List<Person> is a type just like PersonList is. The domain concept of a list of persons is encapsulated in it just as well. If you ask me, it's better to use generics as much as possible unless using them limits you (see below) or makes the code hard to understand. For example, a function that works on PersonList will be harder to generalize than one that works on List<Person>, if you even notice that it's doing something general.

That said, specifically in Java there is a limitation on generics that makes them a lot less attractive. Due to type erasure, you cannot fully utilize generics when static methods / members of a type are involved, and you may need to extract a specific type that is not generic to be able to use it for certain things. Bottom line is, in Java you do need to extract a specific type in many cases, if that allows you to remain type-safe.


Because leaving type parameter as it is isn't really DRY. Consider this class:

class Muffin {
    List<string> _peopleWhoLikeMuffins = new List<string>();

    public Muffin(List<string> peopleWhoLikeMuffins) {
        _peopleWhoLikeMuffins = peopleWhoLikeMuffins);
    }

    public void AddMuffinLiker(string p) {
        _peopleWhoLikeMuffins.Add(p);
    } 
}

It's really short and only contains basic functionality, but I had to use string - genertic type parameter - four times. And it will always be the same. And if I decide to go to change the type later, I'll have to replace all four occurences.

In real world scenarios we are talking hundreds, not 4. So, it's not a no-brainer to always incapsulate it, but it's definitely worth considering.

Now, my example is not very good (and not only because of silly names), but you get the idea - you'll have a lot of field and variables declaration and instantiation, and every time you'll have to pass a type parameter which will always be the same throughout your codebase unless your other classes are also generic.

Another advantage of this is that you'll have much less work if you ever need to add some additional state/behavior to your collection.

That all being said, I myself don't use this kind of abstraction very often.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜