Related
After reading about SOLID in a few places, I was having trouble mapping between explanations with different vocabularies and code. To generalize a bit, I created the diagrams below, and I was hoping that people could point out any 'bugs' in my understanding.
Of course, feel free to reuse/remix/redistribute as you'd like!
I think your diagrams look quite nice, but I'm afraid that I couldn't understand them (particularly the interface one), so I'll comment on the text.
It's not really clear to me what you mean by layer, in the Open/closed I thought you might mean interface, but the interface and dependency items suggest you don't mean that.
Open/closed : actually your text from the Liskov item is closer to describing open/closed. If the code is open for extension, we can make use of it (by extending it) to implement new requirements, but by not modifying the existing code (it's closed for modification) we know we wont break any existing code that made use of it.
"Only depend on outer layer" - if this means only depend on an interface not the implementation, then yes, that's an important principle for SOLID code even though it doesn't map directly to any of the 5 letters.
Dependency inversion uses that but goes beyond it. A piece of code can make use of another via its interface and this is has great maintainability benefits over relying on the implementation, but if the calling code still has the responsibility for creating the object (and therefore choosing the class) that implements the interface then it still has a dependency. If we create the concrete object outside the class or method and pass it in as an interface, then the called code no longer depends on the concrete class, just the interface
void SomeFunction()
{
IThing myIthing* = new ConcreteThing();
// code below can use the interface but this function depends on the Concrete class
}
void SomeFunctionDependencyInjectedVersion(IThing myIthing*)
{
// this version should be able to work with any class that implements the IThing interface,
// whether it really can might depend on some of the other SOLID principles
}
Single responsibility : this isn't about classes intersecting, this is about not giving a code more than one responsibility. If you have a function where you can't think of a better name than doSomethingAndSomethingElse this might be a sign its got more than one responsibility and could be better if it was split (the point I'm making is about the "and" in the name even when the "somethings" are better named).
You should try to define that responsibility so that the class can perform it entirely, (although it make may use of other classes that perform sub-responsibilities for it) but at each level of responsibility that a class is defined it should have one clear reason to exist. When it has more than one it can make code harder to understand, and changes to code related to one responsibility can have unwanted side-effects on other responsibilities.
Iterface segregation: Consider a class implementing a collection. The class will implement code to add to the collection or to read from it. We could put all this in one interface, but if we separate it then when we have consuming code that only needs to read and doesn't need to add to the collection then it can use the interface made of the reading methods. This can make the code clearer in that it shows quickly that the code only needs those methods, and, if we've injected the collection by interface we could also use that code with a different source of items that doesn't have the ability to add items
(consider IEnumerable vs ICollection vs IList)
Liskov substitution is all about making sure that objects that inherit from an interface/base class behave in the way that the interface/base class promised to behave. In the strictest interpretation of the original definition they'd need to behave exactly the same, but that's not all that useful. More generally its about behaving in a consistent and expected way, the derived classes may add functionality, but they should be able to do the job of the base objects (they can be substituted for them)
I have a class which represents a set of numbers. The constructor takes three arguments: startValue, endValue and stepSize.
The class is responsible for holding a list containing all values between start and end value taking the stepSize into consideration.
Example: startValue: 3, endValue: 1, stepSize = -1, Collection = { 3,2,1 }
I am currently creating the collection and some info strings about the object in the constructor. The public members are read only info strings and the collection.
My constructor does three things at the moment:
Checks the arguments; this could throw an exception from the constructor
Fills values into the collection
Generates the information strings
I can see that my constructor does real work but how can I fix this, or, should I fix this? If I move the "methods" out of the constructor it is like having init function and leaving me with an not fully initialized object. Is the existence of my object doubtful? Or is it not that bad to have some work done in the constructor because it is still possible to test the constructor because no object references are created.
For me it looks wrong but it seems that I just can't find a solution. I also have taken a builder into account but I am not sure if that's right because you can't choose between different types of creations. However single unit tests would have less responsibility.
I am writing my code in C# but I would prefer a general solution, that's why the text contains no code.
EDIT: Thanks for editing my poor text (: I changed the title back because it represents my opinion and the edited title did not. I am not asking if real work is a flaw or not. For me, it is. Take a look at this reference.
http://misko.hevery.com/code-reviewers-guide/flaw-constructor-does-real-work/
The blog states the problems quite well. Still I can't find a solution.
Concepts that urge you to keep your constructors light weight:
Inversion of control (Dependency Injection)
Single responsibility principle (as applied to the constructor rather than a class)
Lazy initialization
Testing
K.I.S.S.
D.R.Y.
Links to arguments of why:
How much work should be done in a constructor?
What (not) to do in a constructor
Should a C++ constructor do real work?
http://misko.hevery.com/code-reviewers-guide/flaw-constructor-does-real-work/
If you check the arguments in the constructor that validation code can't be shared if those arguments come in from any other source (setter, constructor, parameter object)
If you fill values into the collection or generate the information strings in the constructor that code can't be shared with other constructors you may need to add later.
In addition to not being able to be shared there is also being delayed until really needed (lazy init). There is also overriding thru inheritance that offers more options with many methods that just do one thing rather then one do everything constructor.
Your constructor only needs to put your class into a usable state. It does NOT have to be fully initialized. But it is perfectly free to use other methods to do the real work. That just doesn't take advantage of the "lazy init" idea. Sometimes you need it, sometimes you don't.
Just keep in mind anything that the constructor does or calls is being shoved down the users / testers throat.
EDIT:
You still haven't accepted an answer and I've had some sleep so I'll take a stab at a design. A good design is flexible so I'm going to assume it's OK that I'm not sure what the information strings are, or whether our object is required to represent a set of numbers by being a collection (and so provides iterators, size(), add(), remove(), etc) or is merely backed by a collection and provides some narrow specialized access to those numbers (such as being immutable).
This little guy is the Parameter Object pattern
/** Throws exception if sign of endValue - startValue != stepSize */
ListDefinition(T startValue, T endValue, T stepSize);
T can be int or long or short or char. Have fun but be consistent.
/** An interface, independent from any one collection implementation */
ListFactory(ListDefinition ld){
/** Make as many as you like */
List<T> build();
}
If we don't need to narrow access to the collection, we're done. If we do, wrap it in a facade before exposing it.
/** Provides read access only. Immutable if List l kept private. */
ImmutableFacade(List l);
Oh wait, requirements change, forgot about 'information strings'. :)
/** Build list of info strings */
InformationStrings(String infoFilePath) {
List<String> read();
}
Have no idea if this is what you had in mind but if you want the power to count line numbers by twos you now have it. :)
/** Assuming information strings have a 1 to 1 relationship with our numbers */
MapFactory(List l, List infoStrings){
/** Make as many as you like */
Map<T, String> build();
}
So, yes I'd use the builder pattern to wire all that together. Or you could try to use one object to do all that. Up to you. But I think you'll find few of these constructors doing much of anything.
EDIT2
I know this answer's already been accepted but I've realized there's room for improvement and I can't resist. The ListDefinition above works by exposing it's contents with getters, ick. There is a "Tell, don't ask" design principle that is being violated here for no good reason.
ListDefinition(T startValue, T endValue, T stepSize) {
List<T> buildList(List<T> l);
}
This let's us build any kind of list implementation and have it initialized according to the definition. Now we don't need ListFactory. buildList is something I call a shunt. It returns the same reference it accepted after having done something with it. It simply allows you to skip giving the new ArrayList a name. Making a list now looks like this:
ListDefinition<int> ld = new ListDefinition<int>(3, 1, -1);
List<int> l = new ImmutableFacade<int>( ld.buildList( new ArrayList<int>() ) );
Which works fine. Bit hard to read. So why not add a static factory method:
List<int> l = ImmutableRangeOfNumbers.over(3, 1, -1);
This doesn't accept dependency injections but it's built on classes that do. It's effectively a dependency injection container. This makes it a nice shorthand for popular combinations and configurations of the underlying classes. You don't have to make one for every combination. The point of doing this with many classes is now you can put together whatever combination you need.
Well, that's my 2 cents. I'm gonna find something else to obsess on. Feedback welcome.
As far as cohesion is concerned, there's no "real work", only work that's in line (or not) with the class/method's responsibility.
A constructor's responsibility is to create an instance of a class. And a valid instance for that matter. I'm a big fan of keeping the validation part as intrinsic as possible, so that you can see the invariants every time you look at the class. In other words, that the class "contains its own definition".
However, there are cases when an object is a complex assemblage of multiple other objects, with conditional logic, non-trivial validation or other creation sub-tasks involved. This is when I'd delegate the object creation to another class (Factory or Builder pattern) and restrain the accessibility scope of the constructor, but I think twice before doing it.
In your case, I see no conditionals (except argument checking), no composition or inspection of complex objects. The work done by your constructor is cohesive with the class because it essentially only populates its internals. While you may (and should) of course extract atomic, well identified construction steps into private methods inside the same class, I don't see the need for a separate builder class.
The constructor is a special member function, in a way that it constructor, but after all - it is a member function. As such, it is allowed to do things.
Consider for example c++ std::fstream. It opens a file in the constructor. Can throw an exception, but doesn't have to.
As long as you can test the class, it is all good.
It's true, a constructur should do minimum of work oriented to a single aim - successful creaation of the valid object. Whatever it takes is ok. But not more.
In your example, creating this collection in the constructor is perfectly valid, as object of your class represent a set of numbers (your words). If an object is set of numbers, you should clearly create it in the constructor! On the contrary - the constructur does not perform what it is made for - a fresh, valid object construction.
These info strings call my attention. What is their purpose? What exactly do you do? This sounds like something periferic, something that can be left for later and exposed through a method, like
String getInfo()
or similar.
If you want to use Microsoft's .NET Framework was an example here, it is perfectly valid both semantically and in terms of common practice, for a constructor to do some real work.
An example of where Microsoft does this is in their implementation of System.IO.FileStream. This class performs string processing on path names, opens new file handles, opens threads, binds all sorts of things, and invokes many system functions. The constructor is actually, in effect, about 1,200 lines of code.
I believe your example, where you are creating a list, is absolutely fine and valid. I would just make sure that you fail as often as possible. Say if you the minimum size higher than the maximum size, you could get stuck in an infinite loop with a poorly written loop condition, thus exhausting all available memory.
The takeaway is "it depends" and you should use your best judgement. If all you wanted was a second opinion, then I say you're fine.
It's not a good practice to do "real work" in the constructor: you can initialize class members, but you shouldn't call other methods or do more "heavy lifting" in the constructor.
If you need to do some initialization which requires a big amount of code running, a good practice will be to do it in an init() method which will be called after the object was constructed.
The reasoning for not doing heavy lifting inside the constructor is: in case something bad happens, and fails silently, you'll end up having a messed up object and it'll be a nightmare to debug and realize where the issues are coming from.
In the case you describe above I would only do the assignments in the constructor and then, in two separate methods, I would implement the validations and generate the string-information.
Implementing it this way also conforms with SRP: "Single Responsibility Principle" which suggests that any method/function should do one thing, and one thing only.
This is a rather basic OO question, but one that's been bugging me for some time.
I tend to avoid using the 'private' visibility modifier for my fields and methods in favor of protected.
This is because, generally, I don't see any use in hiding the implementation between base class and child class, except when I want to set specific guidelines for the extension of my classes (i.e. in frameworks). For the majority of cases I think trying to limit how my class will be extended either by me or by other users is not beneficial.
But, for the majority of people, the private modifier is usually the default choice when defining a non-public field/method.
So, can you list use cases for private? Is there a major reason for always using private? Or do you also think it's overused?
There is some consensus that one should prefer composition over inheritance in OOP. There are several reasons for this (google if you're interested), but the main part is that:
inheritance is seldom the best tool and is not as flexible as other solutions
the protected members/fields form an interface towards your subclasses
interfaces (and assumptions about their future use) are tricky to get right and document properly
Therefore, if you choose to make your class inheritable, you should do so conciously and with all the pros and cons in mind.
Hence, it's better not to make the class inheritable and instead make sure it's as flexible as possible (and no more) by using other means.
This is mostly obvious in larger frameworks where your class's usage is beyond your control. For your own little app, you won't notice this as much, but it (inheritance-by-default) will bite you in the behind sooner or later if you're not careful.
Alternatives
Composition means that you'd expose customizability through explicit (fully abstract) interfaces (virtual or template-based).
So, instead of having an Vehicle base class with a virtual drive() function (along with everything else, such as an integer for price, etc.), you'd have a Vehicle class taking a Motor interface object, and that Motor interface only exposes the drive() function. Now you can add and re-use any sort of motor anywhere (more or less. :).
There are two situations where it matters whether a member is protected or private:
If a derived class could benefit from using a member, making the member `protected` would allow it to do so, while making it `private` would deny it that benefit.
If a future version of the base class could benefit by not having the member behave as it does in the present version, making the member `private` would allow that future version to change the behavior (or eliminate the member entirely), while making it `protected` would require all future versions of the class to keep the same behavior, thus denying them the benefit that could be reaped from changing it.
If one can imagine a realistic scenario where a derived class might benefit from being able to access the member, and cannot imagine a scenario where the base class might benefit from changing its behavior, then the member should be protected [assuming, of course, that it shouldn't be public]. If one cannot imagine a scenario where a derived class would get much benefit from accessing the member directly, but one can imagine scenarios where a future version of the base class might benefit by changing it, then it should be private. Those cases are pretty clear and straightforward.
If there isn't any plausible scenario where the base class would benefit from changing the member, I would suggest that one should lean toward making it protected. Some would say the "YAGNI" (You Ain't Gonna Need It) principle favors private, but I disagree. If you're is expecting others to inherit the class, making a member private doesn't assume "YAGNI", but rather "HAGNI" (He's Not Gonna Need It). Unless "you" are going to need to change the behavior of the item in a future version of the class, "you" ain't gonna need it to be private. By contrast, in many cases you'll have no way of predicting what consumers of your class might need. That doesn't mean one should make members protected without first trying to identify ways one might benefit from changing them, since YAGNI isn't really applicable to either decision. YAGNI applies in cases where it will be possible to deal with a future need if and when it is encountered, so there's no need to deal with it now. A decision to make a member of a class which is given to other programmers private or protected implies a decision as to which type of potential future need will be provided for, and will make it difficult to provide for the other.
Sometimes both scenarios will be plausible, in which case it may be helpful to offer two classes--one of which exposes the members in question and a class derived from that which does not (there's no standard idiomatic was for a derived class to hide members inherited from its parent, though declaring new members which have the same names but no compilable functionality and are marked with an Obsolete attribute would have that effect). As an example of the trade-offs involved, consider List<T>. If the type exposed the backing array as a protected member, it would be possible to define a derived type CompareExchangeableList<T> where T:Class which included a member T CompareExchangeItem(index, T T newValue, T oldvalue) which would return Interlocked.CompareExchange(_backingArray[index], newValue, oldValue); such a type could be used by any code which expected a List<T>, but code which knew the instance was a CompareExchangeableList<T> could use the CompareExchangeItem on it. Unfortunately, because List<T> does not expose the backing array to derived classes, it is impossible to define a type which allows CompareExchange on list items but which would still be useable by code expecting a List<T>.
Still, that's not to imply that exposing the backing array would have been completely without cost; even though all extant implementations of List<T> use a single backing array, Microsoft might implement future versions to use multiple arrays when a list would otherwise grow beyond 84K, so as to avoid the inefficiencies associated with the Large Object Heap. If the backing array was exposed as protected member, it would be impossible to implement such a change without breaking any code that relied upon that member.
Actually, the ideal thing might have been to balance those interests by providing a protected member which, given a list-item index, will return an array segment which contains the indicated item. If there's only one array, the method would always return a reference to that array, with an offset of zero, a starting subscript of zero, and a length equal to the list length. If a future version of List<T> split the array into multiple pieces, the method could allow derived classes to efficiently access segments of the array in ways that would not be possible without such access [e.g. using Array.Copy] but List<T> could change the way it manages its backing store without breaking properly-written derived classes. Improperly-written derived classes could get broken if the base implementation changes, but that's the fault of the derived class, not the base.
I just prefer private than protected in the default case because I'm following the principle to hide as much as possibility and that's why set the visibility as low as possible.
I am reaching here. However, I think that the use of Protected member variables should be made conciously, because you not only plan to inherit, but also because there is a solid reason derived classed shouldn't use the Property Setters/Getters defined on the base class.
In OOP, we "encapsulate" the member fields so that we can excercise control over how they properties the represent are accessed and changed. When we define a getter/setter on our base for a member variable, we are essentially saying that THIS is how I want this variable to be referenced/used.
While there are design-driven exceptions in which one might need to alter the behavior created in the base class getter/setter methods, it seems to me that this would be a decision made after careful consideration of alternatives.
For Example, when I find myself needing to access a member field from a derived class directly, instead of through the getter/setter, I start thinking maybe that particular Property should be defined as abstract, or even moved to the derived class. This depends upon how broad the hierarchy is, and any number of additional considerations. But to me, stepping around the public Property defined on the base class begins to smell.
Of course, in many cases, it "doesn't matter" because we are not implementing anything within the getter/setter beyond access to the variable. But again, if this is the case, the derived class can just as easily access through the getter/setter. This also protects against hard-to-find bugs later, if employed consistently. If the behgavior of the getter/setter for a member field on the base class is changed in some way, and a derived class references the Protected field directly, there is the potential for trouble.
You are on the right track. You make something private, because your implementation is dependant on it not being changed either by a user or descendant.
I default to private and then make a conscious decision about whether and how much of the inner workings I'm going to expose, you seem to work on the basis, that it will be exposed anyway, so get on with it. As long as we both remember to cross all the eyes and dot all the tees, we are good.
Another way to look at it is this.
If you make it private, some one might not be able to do what they want with your implementation.
If you don't make it private, someone may be able to do something you really don't want them to do with your implementation.
I've been programming OOP since C++ in 1993 and Java in 1995. Time and again I've seen a need to augment or revise a class, typically adding extra functionality tightly integrated with the class. The OOP way to do so is to subclass the base class and make the changes in the subclass. For example a base class field originally referred to only elsewhere in the base class is needed for some other action, or some other activity must change a value of the field (or one of the field's contained members). If that field is private in the base class then the subclass cannot access it, cannot extend the functionality. If the field is protected it can do so.
Subclasses have a special relationship to the base class that other classes elsewhere in the class hierarchy don't have: they inherit the base class members. The purpose of inheritance is to access base class members; private thwarts inheritance. How is the base class developer supposed to know that no subclasses will ever need to access a member? In some cases that can be clear, but private should be the exception rather than the rule. Developers subclassing the base class have the base class source code, so their alternative is to revise the base class directly (perhaps just changing private status to protected before subclassing). That's not clean, good practice, but that's what private makes you do.
I am a beginner at OOP but have been around since the first articles in ACM and IEEE. From what I remember, this style of development was more for modelling something. In the real world, things including processes and operations would have "private, protected, and public" elements. So to be true to the object .....
Out side of modelling something, programming is more about solving a problem. The issue of "private, protected, and public" elements is only a concern when it relates to making a reliable solution. As a problem solver, I would not make the mistake of getting cough up in how others are using MY solution to solve their own problems. Now keep in mind that a main reason for the issue of ...., was to allow a place for data checking (i.e., verifying the data is in a valid range and structure before using it in your object).
With that in mind, if your code solves the problem it was designed for, you have done your job. If others need your solution to solve the same or a simular problem - Well, do you really need to control how they do it. I would say, "only if you are getting some benefit for it or you know the weaknesses in your design, so you need to protect some things."
In my idea, if you are using DI (Dependency Injection) in your project and you are using it to inject some interfaces in your class (by constructor) to use them in your code, then they should be protected, cause usually these types of classes are more like services not data keepers.
But if you want to use attributes to save some data in your class, then privates would be better.
My understanding of the Liskov substitution principle is that some property of the base class that is true or some implemented behaviour of the base class, should be true for the derived class as well.
I guess this would mean when a method is defined in a base class, it should never be overrided in the derived class - since then substituting the base class instead of the derived class would give different results. I guess this would also mean, having (non-pure) virtual methods is a bad thing?
I think I might have a wrong understanding of the principle. If I don't, I do not understand why is this principle good practice. Can someone explain this to me? Thanks
Subclasses overriding methods in the base class are totally allowed by the Liskov Substituion Principle.
This might be simplifying it too much, but I remember it as "a subclass should require nothing more and promise nothing less"
If a client is using a superclass ABC with a method something(int i), then the client should be able to substitute any subclass of ABC without problems. Instead of thinking about this in terms of variable types, perhaps think about it in terms of preconditions and postconditions.
If our something() method in the ABC base class above has a relaxed precondition that permits any integer, then all subclasses of ABC must also permit any integer. A subclass GreenABC is not allowed to add an additional precondition to the something() method that requires the parameter to be a positive integer. This would violate the Liskov Substitution Principle (i.e., requiring more). Thus if a client is using subclass BlueABC and passing negative integers to something() the client won't break if we need to switch to GreenABC.
In reverse, if the base ABC class something() method has a postcondition - such as guaranteeing it will never return a value of zero - then all subclasses must also obey that same postcondition or they violate the Liskov Substitution Principle (i.e., promising less).
I hope this helps.
There is one popular example which says if it swims like a duck, quack likes a duck but requires batteries, then it breaks Liskov Substitution Principle.
Put it simply, you have a base Duck class which is being used by someone. Then you add hierarchy by introduction PlasticDuck with same overridden behaviors (like swimming, quacking etc.) as of a Duck but requires batteries to simulate those behaviors. This essentially means that you are introducing an extra pre-condition to the behavior of Sub Class to require batteries to do the same behavior that was earlier done by the Base Duck class without batteries. This might catch the consumer of your Duck class by surprise and might break the functionality built around the expected behavior of Base Duck class.
Here is a good link - http://lassala.net/2010/11/04/a-good-example-of-liskov-substitution-principle/
No, it tells that you should be able to use derived class in the same way as its base. There're many ways you can override a method without breaking this. A simple example, GetHashCode() in C# is in base for ALL classes, and still ALL of them can be used as "object" to calculate the hash code. A classic example of breaking the rule, as far as I remember, is derivin Square from Rectangle, since Square can't have both Width and Height - because setting one would change another and thus it's no more conforms to Rectangle rules. You can, however, still have base Shape with .GetSize() since ALL shapes can do this - and thus any derived shape can be substituted and used as Shape.
Overriding breaks Liskov Substitution Principle if you change any behavior defined by a base method. Which means that:
The weakest precondition for a
child method should be not stronger
than for the base method.
A postcondition for the child method
implies a postcondition for the
parent method. Where a postcondition
is formed by: a) all side
effects caused by a method execution and b)
type and value of a returned expression.
From these two requirements you can imply that any new functionality in a child method that does not affect what is expected from a super method does not violate the principle. These conditions allow you to use a subclass instance where a superclass instance is required.
If these rules are not obeyed a class violates LSP. A classical example is the following hierarchy: class Point(x,y), class ColoredPoint(x,y,color) that extends Point(x,y) and overridden method equals(obj) in ColoredPoint that reflects equality by color. Now if one have an instance of Set<Point> he can assume that two points with the same coordinates are equal in this set. Which is not the case with the overridden method equals and, in general, there is just no way to extend an instantiable class and add an aspect used in equals method without breaking LSP.
Thus every time you break this principle you implicitly introduce a potential bug that reveals when invariant for a parent class that is expected by the code is not satisfied. However, in real world often there is no obvious design solution that does not violate LSP, so one can use, for example, #ViolatesLSP class annotation to warn a client that it is not safe to use class instances in a polymorphic set or in any other kind of cases that rely on the Liskov substitution principle.
I think that you're literally correct in the way you describe the principle and only overriding pure virtual, or abstract methods will ensure that you don't violate it.
However, if you look at the principle from a client's point of view, that is, a method that takes a reference to the base class. If this method cannot tell (and certainly does not attempt to and does not need to find out) the class of any instance that is passed in, then you are also not violating the principle. So it may not matter that you override a base class method (some sorts of decorators might do this, calling the base class method in the process).
If a client seems to need to find out the class of an instance passed in, then you're in for a maintenance nightmare, as you should really just be adding new classes as part of your maintenance effort, not modifying an existing routine. (see also OCP)
The original principle:
"What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.".
Barbara Liskov, 1987
The word is behavior. The "preconditions and postconditions" understanding is useful for a good design but is not related to LSP.
Let's check this summary of "preconditions and postconditions" theory:
Don’t implement any stricter validation rules on input parameters than implemented by the parent class.
Apply at the least the same rules to all output parameters as applied by the parent class.
An indication that it has nothing to do with LSP is: what about VOID methods? VOID does not have OUTPUT parameters. How could this rule be applied to VOID methods? How, according to this rule, could we guarantee to be complying with LSP in VOID methods?
LSP refers to Behavior. When a subclass inherits from a superclass and you have to use some trick to make this work, and the result change the behavior of the program you are breaking LSP.
LSP is about behaviour and the clasic example of Square x Rectangle help us to understand. In fact is the example used by Uncle Bob.
The you inherit Square from Rectangle and overrides SetHeight and SetWidth to force Square act as a Square even if it's a rectangle (by inheritance).
When the user calls SetHeight do not expect Width change.... but will change and this change the expected behavior and break LSP.
This is the problem with Virtuals x LSP
I asked a similar question yesterday that was specific to a technology, but now I find myself wondering about the topic in the broad sense.
For simplicity's sake, we have two classes, A and B, where B is derived from A. B truly "is a" A, and all of the routines defined in A have the same meaning in B.
Let's say we want to display a list of As, some of which are actually Bs. As we traverse our list of As, if the current object is actually a B, we want to display some of Bs additional properties....or maybe we just want to color the Bs differently, but neither A nor B have any notion of "color" or "display stuff".
Solutions:
Make the A class semi-aware of B by basically including a method called isB() in A that returns false. B will override the method and return true. Display code would have a check like: if (currentA.isB()) B b = currentA;
Provide a display() method in A that B can override.... but then we start merging the UI and the model. I won't consider this unless there is some cool trick I'm not seeing.
Use instanceof to check if the current A object to be displayed is really a B.
Just add all the junk from B to A, even though it doesn't apply to A. Basically just contain a B (that does not inherit from A) in A and set it to null until it applies. This is somewhat attractive. This is similar to #1 I guess w/ composition over inheritance.
It seems like this particular problem should come up from time to time and have an obvious solution.
So I guess the question maybe really boils down to:
If I have a subclass that extends a base class by adding additional functionality (not just changing the existing behavior of the base class), am I doing something tragically wrong? It all seems to instantly fall apart as soon as we try to act on a collection of objects that may be A or B.
A variant of option 2 (or hybrid of 1 and 2) may make sense: after all, polymorphism is the standard solution to "Bs are As but need to behave differently in situation X." Agreed, a display() method would probably tie the model to the UI too closely, but presumably the different renderings you want at the UI level reflect semantic or behavioural differences at the model level. Could those be captured in a method? For example, instead of an outright getDisplayColour() method, could it be a getPriority() (for example) method, to which A and B return different values but it is still up to the UI to decide how to translate that into a colour?
Given your more general question, however, of "how can we handle additional behaviour that we can't or won't allow to be accessed polymorphically via the base class," for example if the base class isn't under our control, your options are probably option 3, the Visitor pattern or a helper class. In both cases you are effectively farming out the polymorphism to an external entity -- in option 3, the UI (e.g. the presenter or controller), which performs an instanceOf check and does different things depending on whether it's a B or not; in Visitor or the helper case, the new class. Given your example, Visitor is probably overkill (also, if you were not able/willing to change the base class to accommodate it, it wouldn't be possible to implement it I think), so I'd suggest a simple class called something like "renderer":
public abstract class Renderer {
public static Renderer Create(A obj) {
if (obj instanceOf B)
return new BRenderer();
else
return new ARenderer();
}
public abstract Color getColor();
}
// implementations of ARenderer and BRenderer per your UI logic
This encapsulates the run-time type checking and bundles the code up into reasonably well-defined classes with clear responsibilities, without the conceptual overhead of Visitor. (Per GrizzlyNyo's answer, though, if your hierarchy or function set is more complex than what you've shown here, Visitor could well be more appropriate, but many people find Visitor hard to get their heads around and I would tend to avoid it for simple situations -- but your mileage may vary.)
The answer given by itowlson covers pretty well most part of the question. I will now deal with the very last paragraph as simply as I can.
Inheritance should be implemented for reuse, for your derived class to be reused in old code, not for your class reusing parts of the base class (you can use aggregation for that).
From that standpoint, if you have a class that is to be used on new code with some new functionality, but should be used transparently as a former class, then inheritance is your solution. New code can use the new functionality and old code will seamlessly use your new objects.
While this is the general intention, there are some common pitfals, the line here is subtle and your question is about precisely that line. If you have a collection of objects of type base, that should be because those objects are meant to be used only with base's methods. They are 'bases', behave like bases.
Using techniques as 'instanceof' or downcasts (dynamic_cast<>() in C++) to detect the real runtime type is something that I would flag in a code review and only accept after having the programmer explain to great detail why any other option is worse than that solution. I would accept it, for example, in itowlson's answer under the premises that the information is not available with the given operations in base. That is, the base type does not have any method that would offer enough information for the caller to determine the color. And if it does not make sense to include such operation: besides the prepresentation color, are you going to perform any operation on the objects based on that same information? If logic depends on the real type, then the operation should be in base class to be overriden in derived classes. If that is not possible (the operation is new and only for some given subtypes) there should at least be an operation in the base to allow the caller to determine that a downcast will not fail. And then again, I would really require a sound reason for the caller code to require knowledge of the real type. Why does the user want to see it in different colors? Will the user perform different operations on each one of the types?
If you endup requiring to use code to bypass the type system, your design has a strange smell to it. Of course, never say never, but you can surely say: avoid depending on instanceof or downcasts for logic.
This looks like text book case for the Visitor design pattern (also known as "Double Dispatch").
See this answer for link to a thorough explanation on the Visitor and Composite patterns.