Generic tunnels through layers

One of the oldest discussions in writing software is how generic a piece of code needs to be. For instance, consider this extremely simple example. Suppose that you would provide a number of searches. It would be possible to expose the various methods implementing the searches,

Collection<Person> findByName(String name);
Collection<Person> findByAgeGreaterThan(int age);
Collection<Person> findByNameAndProfession(String name, String profession);

Another possibility is to provide one - more generic - search method, where the name of the actual search is just another argument. Of course, because you do not know the number and actual types of the search arguments, this would force you to use some weakly typed generic search argument:

Collection<Person> find(String searchName, Object searchParams);

Such a generic solution is tempting for many programmers, as it looks elegant and intellectually sophisticated to most of them. One should however not underestimate the dangers of such a generic approach. For instance, you have to create a lot of code to interpret the arguments, and it is very hard to protect such a generic piece of software from run-time errors due to arguments being inconsistent or even of the wrong type. In fact, this is one of the rationales of the NS expanders, to create specific and strongly typed code, without having to code manually lots of instances of similar code.

However, in certain circumstances, such a generic scheme is nevertheless used in the NS elements architecture. Consider for instance this example of various search methods. Such methods typically need to be available to custom programmers in the view layer, while they need to be implemented in the data layer. Often, they only need to be passed through the other layers, without actually using these methods in the intermediate layers. In other words, it is not really necessary to distinguish the various specific and strongly typed methods in these intermediate layers. Therefore, it does make sense to pass them through these layers using a single generic find method. Such a mechanism is schematically represented in the following drawing, and could be considered as a generic tunnel through the layers.


This would limit the amount of really similar code in the various intermediate layers, and would for instance avoid the necessity to introduce additional code in every one of those layers in case a new search method is introduced. One could argue that this additional coding is not an issue through the use of code generators or expanders that would create this code automatically. However, it would still require manual coding in the intermediate layers in case the search method would be very specific and outside the scope of the model of the expanders. On a more fundamental level, we could even make a conceptual argument for such a generic tunnel through the layers. Duplication of similar code is a typical symptom of lack of separation of concerns. And indeed, by creating the generic tunnel, the concern of passing a search method through the various layers, becomes separated from the concern of the actual nature and logic of the search method.