When should you encapsulate generic types?

I saw how many people suggest that you should encapsulate generic types with a class closer to your domain, for example, Steve and Nath offer Growing Object-Oriented software guided by tests that:

Our rule of thumb is that we try to restrict the passage of types using generics [...]. In particular, when applied to collections, we see it as a form of duplication. Its a hint that theres a domain concept that needs to be extracted into a type.

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

class PersonList : List<Person> 

.. and not just use List<Person> directly?

+6
source share
3 answers

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

Unfortunately, the subclassical approach is not a good replacement for typedef .

The following article, “Java Theory and Practice: The Antipattern of the Pseudotype,” explains why fully.

I will copy the output of this article verbatim here:

The motivation for the antipatter pseudotypic is simple enough - developers need a way to define a more compact type of identifiers, especially since generics make type identifiers more detailed. The problem is that this idiom creates a tight connection between the code that uses it and these code clients, preventing reuse. You may not like the verbosity of generic type identifiers, but this is not a way to solve it.

+3
source

I do not agree with this philosophy. List<Person> is a type similar to PersonList . It encapsulates the concept of a domain of a list of persons. If you ask me, it is better to use generics as much as possible, unless their use limits you (see below) or makes code difficult to understand. For example, a function running on PersonList will be harder to generalize than a function running on List<Person> , even if you notice that it does something in common.

However, in particular, in Java there is a restriction on generics, which makes them much less attractive. Due to type erasure, you cannot fully use generics when static methods / type members are involved, and you may need to extract a specific type that is not generic in order to use it for certain things. In fact, in Java you need to extract a specific type in many cases, if that allows you to remain type safe.

+2
source

Because leaving the type parameter as it is not 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 is very short and contains only basic functions, but I had to use the string parameter - genertic type - four times. And it will always be the same. And if I decide to switch to a type change later, I will have to replace all four occurrences.

In real-world scenarios, we are talking about hundreds, not four. So it is not a problem to always encapsulate it, but it is definitely worth considering.

Now my example is not very good (and not only because of stupid names), but you get the idea - you will have many declarations and instances of fields and variables, and every time you have to go through a type parameter that will always be the same in all codebase if your other classes are also common.

Another advantage of this is that you will have much less work if you ever need to add extra state / behavior to your collection.

With everything said, I myself do not use this abstraction very often.

+1
source

Source: https://habr.com/ru/post/896193/


All Articles