I am troubled lately about the use of abstract classes.
Sometimes an abstract class is created in advance and work as a template of how the derived classes would work. That means, more or less, that they provide some high level functionality but leaves out certain details to be implemented by derived classes. The abstract class defines the need for these details by putting in place some abstract methods. In such cases, an abstract class works like a blueprint, a high level description of the functionality or whatever you wanna call it. It cannot be used on its own, but must be specialized to define the details that have been left out of the high level implementation.
Some other times, it happen that the abstract class is created after the creation of some "derived" classes (since the parent/abstract class is not there they have not been derived, yet, but you know what I mean). In these cases, the abstract class is usually used as a place where you can put any kind of common code that current derived classes contain.
Having made the above observations, I am wondering which of these two cases should be the rule. Should any kind of details be bubbled up to the abstract class just because they currently happen to be common in all the derived classes? Should common code that is not part of a high-level functionality be there ?
Should code that may have no meaning for the abstract class itself be there just because it happens to be common for the derived classes?
Let me give an example: Abstract class A has a method a() and an abstract method aq(). The method aq(), in both derived classes AB and AC, uses a method b(). Should b() moved to A ? If yes, then in case someone looks only at A (let's pretend AB and AC are not there), the existence of b() would make no much sense! Is this a bad thing? Should someone be able to have a look in an abstract class and understand what is going on without visiting the derived classes?
To be honest, at the moment of asking this, I tend to believe that writing an abstract class that makes sense without having to look in the derived classes it is a matter of clean code and clean architecture. Ι don't really like the idea of an abstract class that acts like a dump for any kind of code happens to be common in all derived classes.
What do you think/practice ?