2

Is it a sign that something is wrong with the code design if you end up with a layer of functions that just forward request to a component? Exposing the component would avoid this but hurts encapsulation.

An example in a C++ like language.

class AnimalManager
{
    public:
    int GetNumAnimalsOfType(EAnimalType AnimalType) { return 77; } 
    
    // Other animal related stuff
}

class Zoo
{
public:
    int GetNumAnimalsOfType(EAnimalType AnimalType) { return m_AnimalManager.GetNumAnimalsOfType(); } 
    
private:
    AnimalManager m_AnimalManager; 
    
    // Other Zoo related stuff
}
gjcapl
  • 29
  • 1
  • 1
    Short answer: sometimes, it is, and there may be nothing wrong with it. – Doc Brown Sep 25 '21 at 13:21
  • Related: [Why do we need so many classes in design patterns?](https://softwareengineering.stackexchange.com/q/369154/115084) – John Wu Sep 29 '21 at 07:38
  • "We can solve any problem by introducing an extra level of indirection ... except for the problem of too many levels of indirection." - from Wikipedia, [Fundamental theorem of software engineering](https://en.wikipedia.org/wiki/Fundamental_theorem_of_software_engineering) – Doc Brown Sep 29 '21 at 08:53

2 Answers2

3

I see this most when people add a layer which might be best practice, but they dont have enough logic to fill it out.

eg in a MVC design

MyController 
{
   GetThings() { return myService.GetThings(); }
}
MyService
{
   GetThings() { return myRepository.GetThings(); }
}
MyRepository
{
   GetThings() { return myOffTheShelfDAL.Get<Thing>("select * from thing"); }
}

So yeah, best practice says all these layers are good, maybe you will fill them out some day, maybe you are just doing them from muscle memory and its not taken any more time. You cant say its bad per-se. But is the same app had had been written with...

MyController 
{
   GetThings() { return myOffTheShelfDAL.Get<Thing>("select * from thing"); }
}

No-one would be saying "Oh! you need a service layer and a repository!!"

Ewan
  • 70,664
  • 5
  • 76
  • 161
  • I used to work on a large MVC application that had controllers going right through to the raw data access layer. Query logic is still logic. You would be surprised what pain is caused by hard-coding a SQL query *just* a little bit different in 5 different places. Hours. Days. Weeks, spent rooting out bugs that would have been prevented by a single method in a repository that encapsulates that query. So, I would say you need a repository in the controller. – Greg Burghardt Sep 25 '21 at 17:28
  • So, +1 for keeping it simple, but -1 for the code example recommending people hard-code a SQL query in the controller. But I get what you're saying. So +1 anyway. – Greg Burghardt Sep 25 '21 at 17:32
  • 1
    well, extreme example, and i do hate it when people say "YAGNI" when you have already written the dam code. But.. sometimes simple is best – Ewan Sep 25 '21 at 21:22
  • 1
    I'd say the simple solution wins in an ideal world, but you need the discipline to break things out when they start getting out of hand (and that discipline isn't easy to enforce on a team with more than a few people). – casablanca Sep 26 '21 at 20:14
3

You cannot make this judgement by looking at the AnimalManager and Zoo classes alone. If AnimalManager is used in other classes, the logic in that class may have originated in Zoo, but was refactored into another class to promote code reuse.

If AnimalManager is only used in Zoo, then yes, it is useless boilerplate code. Any code depending on Zoo is dealing with the abstraction that Zoo provides, which makes AnimalManager an implementation detail transparent to code outside Zoo.

Then again, if AnimalManager has non-trivial logic that reaches out to a database, file system or web service, and the purpose of Zoo is to provide an abstraction that separates other code from data access logic, then what you call boiler plate might be a necessary separation of concerns for code outside Zoo and AnimalManager.

So, this could be a bad design or a good design. Either way, you need to look at the entire Zoo and AnimalManager classes, as well as classes using Zoo and AnimalManager before making this determination.

Greg Burghardt
  • 34,276
  • 8
  • 63
  • 114