Is this the right understanding of SOLID Object Oriented principles? - oop

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)

Related

Should concrete implementation provide any public API not present in the interface it implements?

"Code to interfaces" is considered good practice. Such code is easy to unit test and enables loose coupling. Users only know the interfaces and the onus of wiring concrete objects is upon the top-most level (this can be done in some init code or with the help of frameworks).
My question is about following the practice of code to interfaces: does it imply that a concrete class can never declare any public method which is not present in its interface?
Otherwise, it will force users to depend upon the concrete implementation. This will make such methods difficult for unit testing; if the test fails, determining if it failed due to an issue in the caller code or due to the concrete method will require extra effort. This will also break the Dependency Inversion Principle. It will induce type-checking and down-casting, which are considered bad practice.
That is totally acceptable provided that the new methods aren't crucial to the operating of the class, and in particular to how it functions when someone thinks of it as the superclass or interface.
ArrayList provides good examples. It has methods that let you manage its internal memory, like ensureCapacity(int) or trimToSize(). Those are sometimes helpful if you know you're working with an ArrayList and need to be more precise about memory allocation, but they're not required for the basic operation of the ArrayList, and in particular, they're not required for having it operate as a general List.
In fact, interfaces themselves can add new methods in this way. Consider NavigableSet, which extends Set. It adds a whole bunch of methods that rely on the ordering of the set's elements (give me the first, the last, a subtree starting from here, etc). None of those methods are defined on Set, and even the fact that the elements are ordered isn't defined by the Set contract; but the Set methods all work just fine without the additional methods and ordering.
The advice to "code to the interface" is a good start, but it's a bit over-generalized. A refinement of that advice would be, "code to the most general interface that you need." If you don't need ArrayLists's methods (or its contract, such as its random-access performance), code to List; but if you do need them, then by all means use them.
#yshavit's third paragraph hits it right. Implement an extension of the "not enough" base interface, as exampled with public interface NavigableSet<E> extends SortedSet<E> (which, BTW, extends Set<E> extends Collection<E> extends Iterable<E>).
It's his second paragraph that troubles me. Why have "non-crucial" methods of the API that are not surfaced in some interface being implemented? In the ArrayList example, why not have the size management methods declared in an interface? Perhaps ManagedSize which would describe clear behavior for ArrayList (and other) classes to implement, along with the several other interfaces it implements (my JRE source says: public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable).
With such an approach, there is no need to decide which methods are "non-crucial," only to be surprised by some client code that depends on things like ensureSize to help avoid relocation during a time-critical phase, or trimToSize to release excessive overalloaction when it's algorthmically known that further growth will not be needed. Not that I'm promoting such algorthms as best practice, but even non-functional "behavior management" methods deserve their place in the light.
Finally, while I agree with sentiment of "Know Where the Lines Are, and yet Color As You See Fit" it doesn't give practical guidance. Here's attempt at such:
Always start by coding to an interface, ie. all concrete public methods should be declared in an interface:
Use multiple interfaces as needed
Each interface should partition the implemented API into coherent non-overlapping aspects, e.g. List, RandomAccess, Cloneable, Serializable
Tend to start with larger scoped interfaces and break them up as the design develops (before coding ala Waterfall, or as code evolves ala Agile); interfaces are one of the easier design artefacts to refactor.
If a given interface you are implementing is "insufficient":
Extend the base interface and add the methods you need, then implement that one, OR
Create an augmenting interface (like the ManagedSize idea, above) with just the additional methods and then implement them both
Only when you find you can't do that, then relax only as much of the rule as you need to make things work (often, this will be an experimental trial-error "does it work, yet?" cycle).
Reasons for #3's "can't" will vary, but I expect them to be external to the application design, e.g. the ORM I'm using becomes confused, the IDE plug-in doesn't refactor it correctly, the DSL translator I'm forced to use fails when a class implements more than three interfaces...

Composition and Inversion of Control

I just came across Inversion of Control approach (implemented using Dependency Injection) of designing loosely coupled software architecture. As per my understanding the IOC approach aims to solve problem related to tight coupling between classes by instantiating an object of a class inside another class which should ideally not happen (as per the pattern). Is my understanding correct here?
If above is true than what about composition or has-a relationship (the very basic important aspect of OO). For an example I write my stack class using a linked list class already defined so I instantiate a linked list class inside my stack class. But as per IOC this will result in tight coupling and hence a bad design. Is this true? I am bit confused here between composition or has-a relationship and IOC.
As per my understanding the IOC approach aims to solve problem related
to tight coupling between classes by instantiating an object of a
class inside another class which should ideally not happen (as per the
pattern). Is my understanding correct here?
Close, but you are slightly off. The problem of tight coupling is addressed when you define contracts between classes (interfaces in Java). Since you need implementations of your contracts(interfaces), at some point those implementations must be provided. IoC is one way of providing an implementation, but not the only way. So tight coupling is really orthogonal to Inversion of Control (meaning it's not directly related).
More specifically, you can have loose coupling but no IoC. The IoC part is that the implementations are coming from outside of the components. Consider the case where you define a class that uses an interface implementation. When you test that class, you might provide a mock. When you pass the mock to the class under test, you are not using IoC. However when you start your app, and the IoC container decides what to pass to your class, that's the IoC.
For an example I write my stack class using a linked list class
already defined so I instantiate a linked list class inside my stack
class. But as per IOC this will result in tight coupling and hence a
bad design. Is this true? I am bit confused here between composition
or has-a relationship and IOC.
Yes and No. In the general sense, you don't need to completely abstract every bit of functionality in your app. You can, and purists probably would, but it can be tedious and over-done.
In this case, you could treat your stack as a black box, and not manage it with IoC. Remember, the Stack itself is loosely couple because the Stack's behavior can be abstracted away. Also, consider the following two definitions
class StackImpl implements Stack {
private List backingList
vs
class StackImpl implements Stack {
private LinkedList backingList
The first is vastly superior to the second, precisely because it's easier to change List implementations; i.e. you have already provided a loose coupling.
That's as far as I would take it. Besides, if you are using composition, you can certainly configure most IoC containers (if not all) to pass things to the constructor or invoke setters, so you can still have a has-A relationship.
Good implementations of IoC can fulfill the "has a" pattern, but just abstract the implementation of the child.
For example, every business layer class may, by your design, "have a" exception handler; with IoC you can define it so that the exception handler that actually gets instantiated at runtime be different in different environments.
The most value in IoC is if you are doing lots of automated testing; in these scenarios you can instantiate mock data access components in your test environment, but have real data access components instantiated in production, which keeps your tests clean. The downside of IoC is that it's harder to debug, since everything is more abstract.
I have my doubts as to my understanding of Inversion of Control too. (It seems like an application of good OO design principles given a fancy name) So, let me assume you are a beginner, analyse your example and clarify my thoughts on the path.
We should start by defining an interface IStack.
interface IStack<T>
{
bool IsEmpty();
T Pop();
void Push(T item);
}
In a way we are already finished; the rest of the code probably will not care whether we implemented it with linked lists, or arrays, or whatever. StackWithLinkedList : IStack and StackWithArray : IStack will behave the same.
class StackWithLinkedList<T> : IStack<T>
{
private LinkedList<T> list;
public StackWithLinkedList<T>()
{
list = new LinkedList<T>();
}
}
So StackWithLinkedList totally owns the list; it does not need any help from outside to construct it, it does not need any flexibility (that line will never change) and the clients of StackWithLinkedList couldn't care less (they have no access to the list). In short, this is not a good example to discuss Inversion of Control: we don't need any.
Let's discuss a similar example, PriorityQueue<T> :
interface IPriorityQueue<T>
{
bool IsEmpty();
T Dequeue();
void Enqueue(T item);
}
Now we have a problem: we need to compare items of type T to provide an implementation of a IPriorityQueue. Clients still do not care whether we use an array, or a heap or whatever inside, but they do care about how we compare items. We could require T to implement IComparable<T> but that would be an unnecessary restriction. What we need is some piece of functionality that will compare T items by our request:
class PriorityQueue<T> : IPriorityQueue<T>
{
private Func<T,T,int> CompareTo;
private LinkedList<T> list;
//bla bla.
}
Such that:
if CompareTo(left,right) < 0 then left < right (in some sense)
if CompareTo(left,right) > 0 then left > right (in some sense)
if CompareTo(left,right) = 0 then left = right (in some sense)
(We would also require CompareTo to be consistent, etc. but that's another topic)
The problem is how to initialize CompareTo.
One option might be, -let's suppose there is a generic comparison creator somewhere- use the comparison creator. (I agree, the example is becoming a little silly)
public PriorityQueue()
{
this.CompareTo = ComparisonCreator<T>.CreateComparison();
this.list = new LinkedList<T>();
}
Or, perhaps even something like: ServiceLocator.Instance.ComparisonCreator<T>.CreateComparison();
This is not an ideal solution for the following reasons:
PriorityQueue is now (very unnecessarily) dependant on ComparisonCreator. If it is on a different assembly, it has to reference it. If someone changes ComparisonCreator he has to make sure PriorityQueue is not affected.
The clients will have a difficult time to use the PriorityQueue. They will first need to make sure that the ComparisonCreator is constructed and initialized.
The clients will have a difficult time to change the default behaviour. Suppose somewhere a client needs a different CompareTo function. There is no easy solution. For example, if it changes the ComparisonCreator<T>'s behaviour, it may affect other clients. What if there are other threads. Even in a single thread environment the client will probably need to undo the change on construction. It's too much effort just to make it work.
For the same reasons, it is difficult to unit test the PriorityQueue. One needs to set up the whole environment.
Of course, - and of course you knew this all along - there is a much easier way in this specific problem. Just provide the CompareTo function in the constructor:
public PriorityQueue(Func<T,T,int> CompareTo)
{
this.CompareTo = CompareTo;
this.list = new LinkedList<T>();
}
Let's check:
PriorityQueue is independent of ComparisonCreator.
For the clients, probably it is much easier to use PriorityQueue. They may need to provide a CompareTo function, but at the worst case they can always ask the ServiceLocator, so al least it is never more difficult.
Changing the default behaviour is very easy. Just give a different CompareTo function. What one client does, does not affect other clients.
It is very easy to unit test PriorityQueue. There is no complex environment to set up. We can easily test it with different CompareTo functions, etc.
What we did is called "constructor injection" because we injected a dependency in the constructor. By giving the needed dependency at the construction, we were able to change the PriorityQueue into a "self sufficient" class. We still create a LinkedList<T>, a concrete class in the construction for the same reasons in Stack example: it is not a real dependency.
The tight coupling in your stack example comes from the stack intantiating a specific list type. The IOC allows the creator of the stack type to provide which exact list implementation to use (e.g. for performance or testing purposes), realizing that the stack does not (at least should not) care what the exact type of the list is as long as it has a specific interface (the methods that stack wants to use) and the concetere implementation provides the required semantics (e.g. iterating through the list will give access to all elements added to the list in the order they were added).
As per my understanding the IOC approach aims to solve problem related
to tight coupling between classes by instantiating an object of a
class inside another class which should ideally not happen (as per the
pattern). Is my understanding correct here?
IoC is actually quite a broad concept, so let's restrict the field to the Dependency Injection approach that you are referring to. Yes, Dependency Injection does what you said.
I think the reason why hvgotcodes thinks that you are slightly off is that the concept of tight coupling can be thought as of having multiple levels. Programming to interfaces is the way to abstract from a particular implementation, which keeps the usage of some piece of code some client code interacts with and its implementation loosely coupled.
The implementation has to be created (instantiated) somewhere though: even if you program to an interface, if the implementation is created inside the client code you are bound to that particular implementation.
So we can abstract the implementation from the interface, but we can also abstract the choice of which implementation to use.
As soon as this detail is clear, you have to ask yourself when it makes sense to abstract the choice of the implementation, which is basically one of the fundamental questions of software engineering: when should you abstract what? The answer to the question is of course context dependent.
But as per IOC this will result in tight coupling and hence a bad
design. Is this true?
If tight coupling is bad design, why are you still relying on standard Java classes? We actually need to distinguish between stable and volatile dependencies.
Citing your example, if you are using the standard implementation of a list, you probably may not want to inject this dependency into your class. What would you achieve by doing this? Do you expect the standard implementation of the list to change any time soon, or do you want to be able to inject a different implementation of a standard list?
On the other hand, suppose you have a custom list with some sort of change tracking mechanism, so that you can perform undo and redo operations on it. Now it could make sense to inject it, because you may want to be able to unit test the client class in isolation, without incurring in potential bugs of your custom list implementation.
As you see, tight coupling is not always bad, sometimes it makes sense, sometimes it is to be avoided: in the end it comes down to the type of dependency.

OO principle: c#: design to interface and not concrete classes

I have some questions about the affects of using concrete classes and interfaces.
Say some chunk of code (call it chunkCode) uses concrete class A. Would I have to re-compile chunkCode if:
I add some new public methods to A? If so, isn't that a bit stange? After all I still provide the interface chunkCode relies on. (Or do I have to re-compile because chunkCode may never know otherwise that this is true and I haven't omitted some API)
I add some new private methods to A?
I add a new public field to A?
I add a new private field to A?
Factory Design Pattern:
The main code doesn't care what the concrete type of the object is. It relies only on the API. But what would you do if there are few methods which are relevant to only one concrete type? This type implements the interface but adds some more public methods? Would you use some if (A is type1) statements (or the like) the main code?
Thanks for any clarification
1) Compiling is not an activity in OO. It is a detail of specific OO implementations. If you want an answer for a specific implementation (e.g. Java), then you need to clarify.
In general, some would say that adding to an interface is not considered a breaking change, wheras others say you cannot change an interface once it is published, and you have to create a new interface.
Edit: You specified C#, so check out this question regarding breaking changes in .Net. I don't want to do that answer a disservice, so I won't try to replicate it here.
2) People often hack their designs to do this, but it is a sign that you have a poor design.
Good alternatives:
Create a method in your interface that allows you to invoke the custom behavior, but not be required to know what that behavior is.
Create an additional interface (and a new factory) that supports the new methods. The new interface does not have to inherit the old interface, but it can if it makes sense (if an is-a relationship can be expressed between the interfaces).
If your language supports it, use the Abstract Factory pattern, and take advantage of Covariant Return Types in the concrete factory. If you need a specific derived type, accept a concrete factory instead of an abstract one.
Bad alternatives (anti-patterns):
Adding a method to the interface that does nothing in other derived classed.
Throwing an exception in a method that doesn't make sense for your derived class.
Adding query methods to the interface that tell the user if they can call a certain method.
Unless the method name is generic enough that the user wouldn't expect it to do anything (e.g. DoExtraProcessing), then adding a method that is no-op in most derived classes breaks the contract defined by that interface.
E.g.: Someone invoking bird.Fly() would expect it to actually do something. We know that chickens can't fly. So either a Chicken isn't a Bird, or Birds don't Fly.
Adding query methods is a poor work-around for this. E.g. Adding a boolean CanFly() method or property in your interface. So is throwing an exception. Neither of them get around the fact that the type simply isn't substitutable. Check out the Liskov Substitution Principle (LSP).
For your first question the answer is NO for all your points. If it would be that way then backward compatibility would not make any sense. You have to recompile chunkCode only if you brake the API, that is remove some functionality that chunkCode is using, changing calling conventions, modifying number of parameters, these sort of things == breaking changes.
For the second I usually, but only if I really have to, use dynamic_cast in those situations.
Note my answer is valid in the context of C++;I just saw the question is language agnostic(kind of tired at this hour; I'll remove the answer if it offenses anybody).
Question 1: Depends on what language you are talking about. Its always safer to recompile both languages though. Mostly because chuckCode does not know what actually exists inside A. Recompiling refreshes its memory. But it should work in Java without recompiling.
Question 2: No. The entire point of writing a Factory is to get rid of if(A is type1). These if statements are terrible from maintenance perspective.
Factory is designed to build objects of similar type. If you are having a situation where you are using this statement then that object is either not a similar type to rest of the classes. If you are sure it is of similar type and have similar interfaces. I would write an extra function in all the concrete base classes and implement it only on this one.
Ideally All these concrete classes should have a common abstract base class or a Interface to define what the API is. Nothing other than what is designed in this Interface should be expected to be called anywhere in the code unless you are writing functions that takes this specific class.

Purpose of final and sealed

Why would anyone want to mark a class as final or sealed?
According to Wikipedia, "Sealed classes are primarily used to prevent derivation. They add another level of strictness during compile-time, improve memory usage, and trigger certain optimizations that improve run-time efficiency."
Also, from Patrick Smacchia's blog:
Versioning: When a class is originally sealed, it can change to unsealed in the future without breaking compatibility. (…)
Performance: (…) if the JIT compiler sees a call to a virtual method using a sealed types, the JIT compiler can produce more efficient code by calling the method non-virtually.(…)
Security and Predictability: A class must protect its own state and not allow itself to ever become corrupted. When a class is unsealed, a derived class can access and manipulate the base class’s state if any data fields or methods that internally manipulate fields are accessible and not private.(…)
Those are all pretty good reasons - I actually wasn't aware of the performance benefit implications until I looked it up just now :)
The versioning and security points seem like a huge benefit in terms of code confidence, which is very well justified on any kind of large project. It's no drop-in for unit testing, of course, but it would help.
Because creating a type for inheritance is much harder work than most folks think. It is best to mark all types this way by default as this will prevent others from inheriting from a type that was never intended to be extended.
Whether or not a type should be extended is a decision of the developer who created it, not the developer who comes along later and wants to extend it.
Joshua Bloch in his book Effective Java talks about it. He says "document for inheritance or disallow it".
The point is that class is sort of a contract between author and client. Allowing client to inherit from base class makes this contract much more strict. If you are going to inherit from it, you most likely are going to override some methods, otherwise you can replace inheritance with composition. Which methods are allowed to be overridden, and what you have to do implementing them - should be documented, or your code can lead to unpredictable results. As far as I remember, he shows such example - here is a collection class with methods
public interface Collection<E> extends Iterable<E> {
...
boolean add(E e);
boolean addAll(Collection<? extends E> c);
...
}
There is some implementation, i.e. ArrayList. Now you want to inherit from it and override some methods, so it prints to console a message when element is added. Now, do you need to override both add and addAll, or only add? It depends on how addAll is implemented - does it work with internal state directly (as ArrayList does) or calls add (as AbstractCollection does). Or may be there is addInternal, which is called by both add and addAll. There were no such questions until you decided to inherit from this class. If you just use it - it does not bother you. So the author of the class has to document it, if he wants you to inherit from his class.
And what if he wants to change the implementation in the future? If his class is only used, never inherited from, nothing stops him from changing implementation to more efficient. Now, if you inherited from that class, looked at source and found that addAll calls add, you override only add. Later author changes implementation so addAll no longer calls add - your program is broken, message is not printed when addAll is called. Or you looked at source and found that addAll does not call add, so you override add and addAll. Now author changes implementation, so addAll calls add - your program is broken again, when addAll is called message is printed twice for each element.
So - if you want your class to be inherited from, you need to document how. If you think that you may need to change something in the future that may break some subclasses - you need to think how to avoid it. By letting your clients inherit from your class you expose much more of internal implementation details that you do when you just let them use your class - you expose internal workflow, that is often subject to changes in future versions.
If you expose some details and clients rely on them - you no longer can change them. If it is ok with you, or you documented what can and what can not be overriden - that's fine. Sometimes you just don't want it. Sometimes you just want to say - "just use this class, never inherit from it, because I want a freedom to change internal implementation details".
So basically comment "Because the class doesn't want to have any children and we should respect it's wishes" is correct.
So, someone wants to mark a class as final/sealed, when he thinks that possible implementation details changes are more valuable than inheritance. There are other ways to achieve results similar to inheritance.

Why should you prevent a class from being subclassed?

What can be reasons to prevent a class from being inherited? (e.g. using sealed on a c# class)
Right now I can't think of any.
Because writing classes to be substitutably extended is damn hard and requires you to make accurate predictions of how future users will want to extend what you've written.
Sealing your class forces them to use composition, which is much more robust.
How about if you are not sure about the interface yet and don't want any other code depending on the present interface? [That's off the top of my head, but I'd be interested in other reasons as well!]
Edit:
A bit of googling gave the following:
http://codebetter.com/blogs/patricksmacchia/archive/2008/01/05/rambling-on-the-sealed-keyword.aspx
Quoting:
There are three reasons why a sealed class is better than an unsealed class:
Versioning: When a class is originally sealed, it can change to unsealed in the future without breaking compatibility. (…)
Performance: (…) if the JIT compiler sees a call to a virtual method using a sealed types, the JIT compiler can produce more efficient code by calling the method non-virtually.(…)
Security and Predictability: A class must protect its own state and not allow itself to ever become corrupted. When a class is unsealed, a derived class can access and manipulate the base class’s state if any data fields or methods that internally manipulate fields are accessible and not private.(…)
I want to give you this message from "Code Complete":
Inheritance - subclasses - tends to
work against the primary technical
imperative you have as a programmer,
which is to manage complexity.For the sake of controlling complexity, you should maintain a heavy bias against inheritance.
The only legitimate use of inheritance is to define a particular case of a base class like, for example, when inherit from Shape to derive Circle. To check this look at the relation in opposite direction: is a Shape a generalization of Circle? If the answer is yes then it is ok to use inheritance.
So if you have a class for which there can not be any particular cases that specialize its behavior it should be sealed.
Also due to LSP (Liskov Substitution Principle) one can use derived class where base class is expected and this is actually imposes the greatest impact from use of inheritance: code using base class may be given an inherited class and it still has to work as expected. In order to protect external code when there is no obvious need for subclasses you seal the class and its clients can rely that its behavior will not be changed. Otherwise external code needs to be explicitly designed to expect possible changes in behavior in subclasses.
A more concrete example would be Singleton pattern. You need to seal singleton to ensure one can not break the "singletonness".
This may not apply to your code, but a lot of classes within the .NET framework are sealed purposely so that no one tries to create a sub-class.
There are certain situations where the internals are complex and require certain things to be controlled very specifically so the designer decided no one should inherit the class so that no one accidentally breaks functionality by using something in the wrong way.
#jjnguy
Another user may want to re-use your code by sub-classing your class. I don't see a reason to stop this.
If they want to use the functionality of my class they can achieve that with containment, and they will have much less brittle code as a result.
Composition seems to be often overlooked; all too often people want to jump on the inheritance bandwagon. They should not! Substitutability is difficult. Default to composition; you'll thank me in the long run.
I am in agreement with jjnguy... I think the reasons to seal a class are few and far between. Quite the contrary, I have been in the situation more than once where I want to extend a class, but couldn't because it was sealed.
As a perfect example, I was recently creating a small package (Java, not C#, but same principles) to wrap functionality around the memcached tool. I wanted an interface so in tests I could mock away the memcached client API I was using, and also so we could switch clients if the need arose (there are 2 clients listed on the memcached homepage). Additionally, I wanted to have the opportunity to replace the functionality altogether if the need or desire arose (such as if the memcached servers are down for some reason, we could potentially hot swap with a local cache implementation instead).
I exposed a minimal interface to interact with the client API, and it would have been awesome to extend the client API class and then just add an implements clause with my new interface. The methods that I had in the interface that matched the actual interface would then need no further details and so I wouldn't have to explicitly implement them. However, the class was sealed, so I had to instead proxy calls to an internal reference to this class. The result: more work and a lot more code for no real good reason.
That said, I think there are potential times when you might want to make a class sealed... and the best thing I can think of is an API that you will invoke directly, but allow clients to implement. For example, a game where you can program against the game... if your classes were not sealed, then the players who are adding features could potentially exploit the API to their advantage. This is a very narrow case though, and I think any time you have full control over the codebase, there really is little if any reason to make a class sealed.
This is one reason I really like the Ruby programming language... even the core classes are open, not just to extend but to ADD AND CHANGE functionality dynamically, TO THE CLASS ITSELF! It's called monkeypatching and can be a nightmare if abused, but it's damn fun to play with!
From an object-oriented perspective, sealing a class clearly documents the author's intent without the need for comments. When I seal a class I am trying to say that this class was designed to encapsulate some specific piece of knowledge or some specific service. It was not meant to be enhanced or subclassed further.
This goes well with the Template Method design pattern. I have an interface that says "I perform this service." I then have a class that implements that interface. But, what if performing that service relies on context that the base class doesn't know about (and shouldn't know about)? What happens is that the base class provides virtual methods, which are either protected or private, and these virtual methods are the hooks for subclasses to provide the piece of information or action that the base class does not know and cannot know. Meanwhile, the base class can contain code that is common for all the child classes. These subclasses would be sealed because they are meant to accomplish that one and only one concrete implementation of the service.
Can you make the argument that these subclasses should be further subclassed to enhance them? I would say no because if that subclass couldn't get the job done in the first place then it should never have derived from the base class. If you don't like it then you have the original interface, go write your own implementation class.
Sealing these subclasses also discourages deep levels of inheritence, which works well for GUI frameworks but works poorly for business logic layers.
Because you always want to be handed a reference to the class and not to a derived one for various reasons:
i. invariants that you have in some other part of your code
ii. security
etc
Also, because it's a safe bet with regards to backward compatibility - you'll never be able to close that class for inheritance if it's release unsealed.
Or maybe you didn't have enough time to test the interface that the class exposes to be sure that you can allow others to inherit from it.
Or maybe there's no point (that you see now) in having a subclass.
Or you don't want bug reports when people try to subclass and don't manage to get all the nitty-gritty details - cut support costs.
Sometimes your class interface just isn't meant to be inheirited. The public interface just isn't virtual and while someone could override the functionality that's in place it would just be wrong. Yes in general they shouldn't override the public interface, but you can insure that they don't by making the class non-inheritable.
The example I can think of right now are customized contained classes with deep clones in .Net. If you inherit from them you lose the deep clone ability.[I'm kind of fuzzy on this example, it's been a while since I worked with IClonable] If you have a true singelton class, you probably don't want inherited forms of it around, and a data persistence layer is not normally place you want a lot of inheritance.
Not everything that's important in a class is asserted easily in code. There can be semantics and relationships present that are easily broken by inheriting and overriding methods. Overriding one method at a time is an easy way to do this. You design a class/object as a single meaningful entity and then someone comes along and thinks if a method or two were 'better' it would do no harm. That may or may not be true. Maybe you can correctly separate all methods between private and not private or virtual and not virtual but that still may not be enough. Demanding inheritance of all classes also puts a huge additional burden on the original developer to foresee all the ways an inheriting class could screw things up.
I don't know of a perfect solution. I'm sympathetic to preventing inheritance but that's also a problem because it hinders unit testing.
I exposed a minimal interface to interact with the client API, and it would have been awesome to extend the client API class and then just add an implements clause with my new interface. The methods that I had in the interface that matched the actual interface would then need no further details and so I wouldn't have to explicitly implement them. However, the class was sealed, so I had to instead proxy calls to an internal reference to this class. The result: more work and a lot more code for no real good reason.
Well, there is a reason: your code is now somewhat insulated from changes to the memcached interface.
Performance: (…) if the JIT compiler sees a call to a virtual method using a sealed types, the JIT compiler can produce more efficient code by calling the method non-virtually.(…)
That's a great reason indeed. Thus, for performance-critical classes, sealed and friends make sense.
All the other reasons I've seen mentioned so far boil down to "nobody touches my class!". If you're worried someone might misunderstand its internals, you did a poor job documenting it. You can't possibly know that there's nothing useful to add to your class, or that you already know every imaginable use case for it. Even if you're right and the other developer shouldn't have used your class to solve their problem, using a keyword isn't a great way of preventing such a mistake. Documentation is. If they ignore the documentation, their loss.
Most of answers (when abstracted) state that sealed/finalized classes are tool to protect other programmers against potential mistakes. There is a blurry line between meaningful protection and pointless restriction. But as long as programmer is the one who is expected to understand the program, I see no hardly any reasons to restrict him from reusing parts of a class. Most of you talk about classes. But it's all about objects!
In his first post, DrPizza claims that designing inheritable class means anticipating possible extensions. Do I get it right that you think that class should be inheritable only if it's likely to be extended well? Looks as if you were used to design software from the most abstract classes. Allow me a brief explanation of how do I think when designing:
Starting from the very concrete objects, I find characteristics and [thus] functionality that they have in common and I abstract it to superclass of those particular objects. This is a way to reduce code duplicity.
Unless developing some specific product such as a framework, I should care about my code, not others (virtual) code. The fact that others might find it useful to reuse my code is a nice bonus, not my primary goal. If they decide to do so, it's their responsibility to ensure validity of extensions. This applies team-wide. Up-front design is crucial to productivity.
Getting back to my idea: Your objects should primarily serve your purposes, not some possible shoulda/woulda/coulda functionality of their subtypes. Your goal is to solve given problem. Object oriented languages uses fact that many problems (or more likely their subproblems) are similar and therefore existing code can be used to accelerate further development.
Sealing a class forces people who could possibly take advantage of existing code WITHOUT ACTUALLY MODIFYING YOUR PRODUCT to reinvent the wheel. (This is a crucial idea of my thesis: Inheriting a class doesn't modify it! Which seems quite pedestrian and obvious, but it's being commonly ignored).
People are often scared that their "open" classes will be twisted to something that can not substitute its ascendants. So what? Why should you care? No tool can prevent bad programmer from creating bad software!
I'm not trying to denote inheritable classes as the ultimately correct way of designing, consider this more like an explanation of my inclination to inheritable classes. That's the beauty of programming - virtually infinite set of correct solutions, each with its own cons and pros. Your comments and arguments are welcome.
And finally, my answer to the original question: I'd finalize a class to let others know that I consider the class a leaf of the hierarchical class tree and I see absolutely no possibility that it could become a parent node. (And if anyone thinks that it actually could, then either I was wrong or they don't get me).