Where might I find a concise, well-written argument against this initialization anti-pattern, and possibly others? [closed]
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 4 years ago.
Improve this questionA coworker of mine tends to design classes like:
class ImportantClass
{
public SomeClass ImportantField;
public SomeOtherClass OtherImportantField;
// etc.
}
He'll write no constructor. Then wherever he instantiates this type his code will look like this:
ImportantClass x;
try
{
// This is problematic enough to begin with, as every field (which is public)
// is set manually, which causes code duplication wherever this type is
// instantiated as well as maintenance problems in the event new fields are
// introduced or internal implementation is changed.
x = new ImportantClass();
x.ImportantField = new SomeClass();
x.OtherImportantField = new SomeOtherClass();
}
catch (Exception ex)
{
// ...what's even worse: now x can easily be in a totally invalid state,
// with some fields initialized and some not.
HandleAnyException(ex);
}
Obviously the above is an oversimplified (and exaggerated) example; but I think you get the point.
I'm not posting this to criticize my coworker; rather, I want to get across to him the开发者_开发知识库 many problems in developing classes like this and point him in the right direction. I personally feel that this design, while quite poor, is something that is easily "fixed."
My main concern is that if I want to convince him, it will be important for me to have an argument that is strong (well-supported), easy to understand, and concise (he's not going to want to read a 2-page e-mail telling him why I think his code needs to change).
Are there any good resources out there that provide such well-crafted arguments, addressing the drawbacks of this and perhaps other ill-advised design anti-patterns? Something like a compendium of "common software design mistakes" would be extremely helpful, if it exists.
Note: I realize that simply talking about it is the most direct and probably least disruptive way to give advice; I'm just thinking, it would be nice to also have this resource that I can point to as a reference—again, if such a resource exists.
It violates responsibility principles. If ImportantClass
needs the other two instances in order to work properly, then it is ImportantClass
's responsibility to make sure that they are in a known good state before anything else should happen.
That code violates several principles described in the excellent book Effective Java by Joshua Bloch, which I highly recommend. For example, on public instance fields:
If an instance field is non-final, or is a final reference to a mutable object, then by making the field public, you give up the ability to limit the values that can be stored in the field. This means you also give up the ability to enforce invariants involving the field. Also, you give up the ability to take any action when the field is modified, so classes with public mutable fields are not thread-safe. Even if a field is final and refers to an immutable object, by making the field public you give up the flexibility to switch to a new internal data representation in which the field does not exist.
Furthermore, you are not achieving encapsulation with these fields public.
The book has a lot to say about how to do object initialization safely and correctly, as well. Suffice it to say, the code you posted is highly problematic.
I would point your coworker to an article regarding SOLID principles.
You can mention to him that this coding approach violates one of the three fundamental concepts of object oriented development which of course is encapsulation.
The fact that the state of his object can be modified directly by its users which makes debugging really hard as opposed to a private method that will be the single way to access internal data...
More than this, his clients are tightly coupled with his class so in the case that he wants to make some internal changes his clients need to be recompiled despite that fact that the changed occurred do not affect their use....
The truth though, is that during the latest years the application of data encapsulation in OO systems has been relaxed in comparison with the past.
Technologies like SPRING or LINQ for example, directly violate the privacy of implementation details trying to archive IOC or 'functional like' behavior.
A direct result of this tendency is the recent adoption from C# of automatic properties that are used to simplify direct exposure of private data as set/get properties...
It violates the Principle of Least Astonishment because as a consumer of the class I would require working knowledge of the class to make it work without exceptions (or run it until I get no exceptions which would be a huge pain in the a$$).
Some quotes from http://portal.acm.org/citation.cfm?id=1176622:
APIs should be easy to use and hard to misuse. It should be easy to do simple things; possible to do complex things; and impossible, or at least difficult, to do wrong things.
Keep APIs free of implementations details. They confuse users and inhibit the flexibility to evolve. It isn't always obvious what's an implementation detail: Be wary of overspecification.
精彩评论