Does this code violate open-closed principle? - java

I want to know if the below code is violating open closed principle.
Animal is a parent class of Dog, however Animal has jackson annotations that help ObjectMapper (de)serialize the classes. Anyone who extends Animal will have to edit only annotations present on Animal to make sure (de)serialization works as intended leaving the class untouched.
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
#JsonSubTypes({
// all subclasses
#Type(value = Dog.class, name = "dog")
})
public abstract class Animal {
// fields, constructors, getters and setters
}
public class Dog extends Animal {
}

Indeed it does. The idea of the open-close principle is to make objects extendable without having to modify them internally. Since any new child of Animal would have to modify it to work properly, it breaks the principle.

Theoretical point of view
Open/closed principle like the whole SOLID is Utopia. We should continually upgrade our code in that direction but probably we will never end up there because this is not possible. Let's read below articles to see how classical getters and annotation constructs can be debatable.
Printers Instead of Getters
Java Annotations Are a Big Mistake
Practical point of view
Like every practical programmer I like to use good tools to solve problems instead of implementing something new myself. When I am asked to serialise given model to JSON files I am checking whether it is:
Open-source
Fast
Under active development
It is easy to use
When we are talking about Jackson and it's annotations, I think, we can find golden middle way between theory and practice. And this is thanks to MixIn feature. You can separate model from the way how it is serialised to JSON. Of course when you add new class which extends base class you need to change MixIn interface with annotations but this is a price we need to pay.
Edit or Why I forgot to answer a question?
Sorry, I forgot to answer a question whether above example violates Open/Closed principle or not. First, get definition from Wikipedia article:
A class is closed, since it may be compiled, stored in a library,
baselined, and used by client classes. But it is also open, since any
new class may use it as parent, adding new features. When a descendant
class is defined, there is no need to change the original or to
disturb its clients.
Above example violates When a descendant class is defined, there is no need to change the original part. Even if we use MixIn there is a need to change other part of app. Even more, if your solution uses annotations in 99.99% of cases you violate this part because there is a need to configure somehow functionality which is hidden behind them.

Open/closed means a class should be open for extension, but closed for modification.
In other words... if you want to change the behavior of a class you should extend it in some way, but you should not modify it.
You can extent a class by
creating a subclass. This is usually done using e.g. the template method pattern.
defining an interface that class A uses so that it's behavior can be extended by passing it another instance of that interface, e.g. a strategy pattern. A good real life example is a TreeSet(Comparator<? super E> comparator), because it's sorting behavior can be changed without modifying TreeSet itself.
From my point of view the #JsonSubTypes annotation is not part of the behavior of the Animal class. It changes the behavior of another class - the object mapper. Thus it is not really a violation. Not really means that even if you don't change the behavior, you have to touch the Animal class and recompile it.
It is a really weird design of the annotation. Why did that json developers not allow you to put an annotation on the subclass, e.g. like JPA does when it comes to hierarchy mapping. See DiscriminatorValue
It is a strange design that a supertype references subtypes.
Abstract types should not depend on concrete ones. In my opinion that is a principle that should always be applied.

Related

Creating an object based on the subclasses of two other objects

My design problem is as follows.
I have two classes, each with a number of subclasses. I have a factory, which needs to create an object based on the subclass of each of these objects.
This is an authentication problem. The factory generates a rule object based on the type of person and the type of resource they wish to access. The rule has alwaysAllow, NeverAllow and timeBasedAllow subclasses. With the potential for more if a more complex access system is needed in the future.
So in future ideally a new person could be created with a new subclass, a new resource with a new subclass. The parameters on which access is determined could be changed with a new rule subclass, and the specific access of each person type and room type could be changed within the rule factory.
So far the only way I can think to do this would be to have an enumeration inside the subclasses, which defeats the point because then adding a new person or room requires a new class and a change in the enum class which seems messy.
I also am very keen to keep the data and the logic separate so I can’t just move authentication methods into the person class because this would require the person class to know how many room types there were, which is definitely not ideal.
I may be after something that isn’t realistically achievable but I can’t help the feeling that there is a nice clean solution just out of my grasp.
Any help would be greatly appreciated.
Your question title makes it sound as if you are searching for multiple-inheiritance, which is not allowed in Java. Unlike in C++, a class may extend one and only one class. However, Java also has interface, which I suspect may be what you seek.
An interface class cannot be instantiated, and may have abstract methods. A
concrete class may implement as many interfaces as desired, and the concrete class must implement each abstract method the interface declares. Abstract classes may also implement interfaces, and abstract methods they do not implement must be implemented by concrete classes extending them.
I suggest extracting your authentication methods into aninterface, perhaps called AuthRule or somesuch. AuthRule can have abstract methods with represent authenticating, without exposing the exact style used to authenticate. So, you would implement AlwaysAllow implements AuthRule and then the authenticate methods on AlwaysAllow would always return true.
The second thing, however, is that you appear to be attempting to use inheritance when composition would better suit your needs. Now instread of having a Person inherit his authentication-rule, the rule should instead be a member field inside Person. So, for example:
class Person extends User {
AuthRule rule;
Person(AuthRule myrule) {
rule = myrule;
}
bool authenticate(...) {
return rule.authenticate(...);
}
}
If you follow a design pattern based on injecting objects into other objects to mix in the functionality you desire, your code will become far more usable and extensible. I hope this helps your problem.

A design confusion about inheritance and interfaces

I'm stuck with a rather peculiar design problem. I'm using a Java ORM, and have defined one of my model classes as follows:
class User extends Model {
// . . .
}
Now, there are more models, and I'd like them all to support data validations. The idea is simple: As each setter method is called, an internal ArrayList of errors keeps getting populated.
Now, the mechanism of error handling is exactly the same for all the model classes. I can envision the following interface:
public interface ErrorReportable {
ArrayList<String> errors = new ArrayList<String>();
boolean hasErrors();
ArrayList<String> getErrors();
void resetErrors();
}
Now I have a problem: All the methods are abstract, which means I'll have to provide an implementation for all of them in my classes. This is sad, because all these methods are going to be implemented in exactly the same way. Ideally, this would've been another class I would've neatly inherited from, but sadly, there's no multiple inheritance in Java.
My next option is use default methods in interfaces, but here the problem is the errors field, which will become static whereas I need a regular field for each instance.
It looks like the only solution is composition, but then I'll have to have a hasErrors() method on User, which will go return this.error_obj.hasErrors(). This is fine, but not really neat in my opinion as I'm having to write things twice.
How can I do better?
I think it would be better for the model classes to only expose List<Error> validate() method, and to have a stand-alone validator that validates all the fields and collects the errors.
That way, the collected messages are not part of the model's state, you have explicit control over when will the validation happen, you're preferring composition (which is almost always a good thing), and the only method you need to implement in model class is the entity-specific validation.
If you ever need to add any cross-field validations, it will also be probably quite easy to extend this design to also perform those alongside with field validations.
If I get your need right, I would implement an own Model-class, that implements all neceaasary Interfaces and extends the Model-ancestor, but still is Abstract.
Then all your normal model-classes inherit from your abstract model-class to get the implementation for the interface and also the inheritance from the model-class (2nd Generation would that be). Any framework checking with 'instance of' will still check true for the later model-class.
The abstract class does not even have to have any abstract methods/members, but it should stay abstract to prevent direct instanciating from that class.
public abstract class myModel extends Model implements ErrorReportable{ ... }
public class User extends myModel { ... }

Why is having an abstract subclass of concrete class bad design?

After all ANY java abstract is an abstract subclass of Object. Sometimes we need to force the subclass to implement some methods, but may already have a pretty well defined hierarchy with concrete classes.
For example: I have a well functioning hierarchy with
Vehicle<--- Car
and now I want to add ElectricCar to this hierarchy.
vehicle<--Car<--ElectricCar.
I also want all the different types of electric cars to implement certain behaviors like getBatteryLife or something-
Why would it be a bad idea to make ElectricCar abstract ?
there's nothing wrong in making it abstract. if your business requires you to make it abstract, it's fine. Like you said, lots of classes in Java lib are abstract and still extending Object.
It's not bad, per se. Not common, but not bad. The only thing I can think of is understandability: if I saw a concrete class Car that I could instantiate, I would normally assume that any child of it was also instantiable, because 99% of code works this way.Then I'd be confused, for a second, about not being able to instantiate an ElectricCar.
It could be argued that this pattern breaks the Liskov Substituion Principle since you can't pass "ElectricCar" wherever "Car" is expected if it's declared abstract (you could pass instances of ElectricCar subclasses of course).
In this particular example, the concrete electric cars (hydrogen powered/plug-in/etc?) I would expect to inherit directly from "Car" since they satisfy an "is-a" relationship and are a proper specialisation of "Car". If you wanted to described some common behaviours and traits they should provide then they should also implement an ElectricCar interface.
It seems what you really want is the ability to inherit from Car (since that is what they are) and share/re-use common implementations of electric car related methods. In this case you are looking at a multiple inheritance problem or a need for mixins, neither of which are directly supported in Java.
Providing an abstract class in the middle of a concrete hierarchy may be one way around this, but it's not pretty.
Personally I would prefer to define an Interface for ElectricCar and then allow the implementing class to define the methods. Then you can share the behavior of getBatteryLife through another mechanism.
I've built some pretty deep hierarchies of Inheritance and I tend to avoid them do to the brittle nature they tend to build up over time. One Base class might make sense, but I would think about how you can compose your object model to share behavior w/o inheritance if possible.
In you example I would say that supposedly the Car class should be abstract (or an interface), too. But there is nothing wrong with the ElectricCar being abstract.

Java Interfaces/Implementation naming convention [duplicate]

This question already has answers here:
Interface naming in Java [closed]
(11 answers)
Closed 7 years ago.
How do you name different classes / interfaces you create?
Sometimes I don't have implementation information to add to the implementation name - like interface FileHandler and class SqlFileHandler.
When this happens I usually name the interface in the "normal" name, like Truck and name the actual class TruckClass.
How do you name interfaces and classes in this regard?
Name your Interface what it is. Truck. Not ITruck because it isn't an ITruck it is a Truck.
An Interface in Java is a Type. Then you have DumpTruck, TransferTruck, WreckerTruck, CementTruck, etc that implements Truck.
When you are using the Interface in place of a sub-class you just cast it to Truck. As in List<Truck>. Putting I in front is just Hungarian style notation tautology that adds nothing but more stuff to type to your code.
All modern Java IDE's mark Interfaces and Implementations and what not without this silly notation. Don't call it TruckClass that is tautology just as bad as the IInterface tautology.
If it is an implementation it is a class. The only real exception to this rule, and there are always exceptions, could be something like AbstractTruck. Since only the sub-classes will ever see this and you should never cast to an Abstract class it does add some information that the class is abstract and to how it should be used. You could still come up with a better name than AbstractTruck and use BaseTruck or DefaultTruck instead since the abstract is in the definition. But since Abstract classes should never be part of any public facing interface I believe it is an acceptable exception to the rule. Making the constructors protected goes a long way to crossing this divide.
And the Impl suffix is just more noise as well. More tautology. Anything that isn't an interface is an implementation, even abstract classes which are partial implementations. Are you going to put that silly Impl suffix on every name of every Class?
The Interface is a contract on what the public methods and properties have to support, it is also Type information as well. Everything that implements Truck is a Type of Truck.
Look to the Java standard library itself. Do you see IList, ArrayListImpl, LinkedListImpl? No, you see List and ArrayList, and LinkedList. Here is a nice article about this exact question. Any of these silly prefix/suffix naming conventions all violate the DRY principle as well.
Also, if you find yourself adding DTO, JDO, BEAN or other silly repetitive suffixes to objects then they probably belong in a package instead of all those suffixes. Properly packaged namespaces are self documenting and reduce all the useless redundant information in these really poorly conceived proprietary naming schemes that most places don't even internally adhere to in a consistent manner.
If all you can come up with to make your Class name unique is suffixing it with Impl, then you need to rethink having an Interface at all. So when you have a situation where you have an Interface and a single Implementation that is not uniquely specialized from the Interface you probably don't need the Interface in most cases.
However, in general for maintainability, testability, mocking, it's best practice to provide interfaces. See this answer for more details.
Also Refer this interesting article by Martin Fowler on this topic of InterfaceImplementationPair
I've seen answers here that suggest that if you only have one implementation then you don't need an interface. This flies in the face of the Depencency Injection/Inversion of Control principle (don't call us, we'll call you!).
So yes, there are situations in which you wish to simplify your code and make it easily testable by relying on injected interface implementations (which may also be proxied - your code doesn't know!). Even if you only have two implementations - one a Mock for testing, and one that gets injected into the actual production code - this doesn't make having an interface superfluous. A well documented interface establishes a contract, which can also be maintained by a strict mock implementation for testing.
in fact, you can establish tests that have mocks implement the most strict interface contract (throwing exceptions for arguments that shouldn't be null, etc) and catch errors in testing, using a more efficient implementation in production code (not checking arguments that should not be null for being null since the mock threw exceptions in your tests and you know that the arguments aren't null due to fixing the code after these tests, for example).
Dependency Injection/IOC can be hard to grasp for a newcomer, but once you understand its potential you'll want to use it all over the place and you'll find yourself making interfaces all the time - even if there will only be one (actual production) implementation.
For this one implementation (you can infer, and you'd be correct, that I believe the mocks for testing should be called Mock(InterfaceName)), I prefer the name Default(InterfaceName). If a more specific implementation comes along, it can be named appropriately. This also avoids the Impl suffix that I particularly dislike (if it's not an abstract class, OF COURSE it is an "impl"!).
I also prefer "Base(InterfaceName)" as opposed to "Abstract(InterfaceName)" because there are some situations in which you want your base class to become instantiable later, but now you're stuck with the name "Abstract(InterfaceName)", and this forces you to rename the class, possibly causing a little minor confusion - but if it was always Base(InterfaceName), removing the abstract modifier doesn't change what the class was.
The name of the interface should describe the abstract concept the interface represents. Any implementation class should have some sort of specific traits that can be used to give it a more specific name.
If there is only one implementation class and you can't think of anything that makes it specific (implied by wanting to name it -Impl), then it looks like there is no justification to have an interface at all.
I tend to follow the pseudo-conventions established by Java Core/Sun, e.g. in the Collections classes:
List - interface for the "conceptual" object
ArrayList - concrete implementation of interface
LinkedList - concrete implementation of interface
AbstractList - abstract "partial" implementation to assist custom implementations
I used to do the same thing modeling my event classes after the AWT Event/Listener/Adapter paradigm.
The standard C# convention, which works well enough in Java too, is to prefix all interfaces with an I - so your file handler interface will be IFileHandler and your truck interface will be ITruck. It's consistent, and makes it easy to tell interfaces from classes.
I like interface names that indicate what contract an interface describes, such as "Comparable" or "Serializable". Nouns like "Truck" don't really describe truck-ness -- what are the Abilities of a truck?
Regarding conventions: I have worked on projects where every interface starts with an "I"; while this is somewhat alien to Java conventions, it makes finding interfaces very easy. Apart from that, the "Impl" suffix is a reasonable default name.
Some people don't like this, and it's more of a .NET convention than Java, but you can name your interfaces with a capital I prefix, for example:
IProductRepository - interface
ProductRepository, SqlProductRepository, etc. - implementations
The people opposed to this naming convention might argue that you shouldn't care whether you're working with an interface or an object in your code, but I find it easier to read and understand on-the-fly.
I wouldn't name the implementation class with a "Class" suffix. That may lead to confusion, because you can actually work with "class" (i.e. Type) objects in your code, but in your case, you're not working with the class object, you're just working with a plain-old object.
I use both conventions:
If the interface is a specific instance of a a well known pattern (e.g. Service, DAO), then it may not need an "I" (e.g UserService, AuditService, UserDao) all work fine without the "I", because the post-fix determines the meta pattern.
But, if you have something one-off or two-off (usually for a callback pattern), then it helps to distinguish it from a class (e.g. IAsynchCallbackHandler, IUpdateListener, IComputeDrone). These are special purpose interfaces designed for internal use, occasionally the IInterface calls out attention to the fact that an operand is actually an interface, so at first glance it is immediately clear.
In other cases you can use the I to avoid colliding with other commonly known concrete classes (ISubject, IPrincipal vs Subject or Principal).
TruckClass sounds like it were a class of Truck, I think that recommended solution is to add Impl suffix. In my opinion the best solution is to contain within implementation name some information, what's going on in that particular implementation (like we have with List interface and implementations: ArrayList or LinkedList), but sometimes you have just one implementation and have to have interface due to remote usage (for example), then (as mentioned at the beginning) Impl is the solution.

Why avoid the final keyword?

In java, is there ever a case for allowing a non-abstract class to be extended?
It always seems to indicate bad code when there are class hierarchies. Do you agree, and why/ why not?
There are certainly times when it makes sense to have non-final concrete classes. However, I agree with Kent - I believe that classes should be final (sealed in C#) by default, and that Java methods should be final by default (as they are in C#).
As Kent says, inheritance requires careful design and documentation - it's very easy to think you can just override a single method, but not know the situations in which that method may be called from the base class as part of the rest of the implementation.
See "How do you design a class for inheritance" for more discussion on this.
I agree with Jon and Kent but, like Scott Myers (in Effective C++), I go much further. I believe that every class should be either abstract, or final. That is, only leaf classes in any hierarchy are really apt for direct instantiation. All other classes (i.e. inner nodes in the inheritance) are “unfinished” and should consequently be abstract.
It simply makes no sense for usual classes to be further extended. If an aspect of the class is worth extending and/or modifying, the cleaner way would be to take that one class and separate it into one abstract base class and one concrete interchangeable implementation.
there a good reasons to keep your code non-final. many frameworks such as hibernate, spring, guice depend sometimes on non-final classes that they extends dynamically at runtime.
for example, hibernate uses proxies for lazy association fetching.
especially when it comes to AOP, you will want your classes non-final, so that the interceptors can attach to it.
see also the question at SO
This question is equally applicable to other platforms such as C# .NET. There are those (myself included) that believe types should be final/sealed by default and need to be explicitly unsealed to allow inheritance.
Extension via inheritance is something that needs careful design and is not as simple as just leaving a type unsealed. Therefore, I think it should be an explicit decision to allow inheritance.
Your best reference here is Item 15 of Joshua Bloch's excellent book "Effective Java", called "Design and document for inheritance or else prohibit it". However the key to whether extension of a class should be allowed is not "is it abstract" but "was it designed with inheritance in mind". There is sometimes a correlation between the two, but it's the second that is important. To take a simple example most of the AWT classes are designed to be extended, even those that are not abstract.
The summary of Bloch's chapter is that interaction of inherited classes with their parents can be surprising and unpredicatable if the ancestor wasn't designed to be inherited from. Classes should therefore come in two kinds a) classes designed to be extended, and with enough documentation to describe how it should be done b) classes marked final. Classes in (a) will often be abstract, but not always. For
I disagree. If hierarchies were bad, there'd be no reason for object oriented languages to exist. If you look at UI widget libraries from Microsoft and Sun, you're certain to find inheritance. Is that all "bad code" by definition? No, of course not.
Inheritance can be abused, but so can any language feature. The trick is to learn how to do things appropriately.
In some cases you want to make sure there's no subclassing, in other cases you want to ensure subclassing (abstract). But there's always a large subset of classes where you as the original author don't care and shouldn't care. It's part of being open/closed. Deciding that something should be closed is also to be done for a reason.
I couldn't disagree more. Class hierarchies make sense for concrete classes when the concrete classes know the possible return types of methods that they have not marked final. For instance, a concrete class may have a subclass hook:
protected SomeType doSomething() {
return null;
}
This doSomething is guarenteed to be either null or a SomeType instance. Say that you have the ability to process the SomeType instance but don't have a use case for using the SomeType instance in the current class, but know that this functionality would be really good to have in subclasses and most everything is concrete. It makes no sense to make the current class an abstract class if it can be used directly with the default of doing nothing with its null value. If you made it an abstract class, then you would have its children in this type of hierarchy:
Abstract base class
Default class (the class that could have been non-abstract, only implements the protected method and nothing else)
Other subclasses.
You thus have an abstract base class that can't be used directly, when the default class may be the most common case. In the other hierarchy, there is one less class, so that the functionality can be used without making an essentially useless default class because abstraction just had to be forced onto the class.
Default class
Other subclasses.
Now, sure, hierarchies can be used and abused, and if things are not documented clearly or classes not well designed, subclasses can run into problems. But these same problems exist with abstract classes as well, you don't get rid of the problem just because you add "abstract" to your class. For instance, if the contract of the "doSomething()" method above required SomeType to have populated x, y and z fields when they were accessed via getters and setters, your subclass would blow up regardless if you used the concrete class that returned null as your base class or an abstract class.
The general rule of thumb for designing a class hierarchy is pretty much a simple questionaire:
Do I need the behavior of my proposed superclass in my subclass? (Y/N)
This is the first question you need to ask yourself. If you don't need the behavior, there's no argument for subclassing.
Do I need the state of my proposed superclass in my subclass? (Y/N)
This is the second question. If the state fits the model of what you need, this may be a canidate for subclassing.
If the subclass was created from the proposed superclass, would it truly be an IS-A relation, or is it just a shortcut to inherit behavior and state?
This is the final question. If it is just a shortcut and you cannot qualify your proposed subclass "as-a" superclass, then inheritance should be avoided. The state and logic can be copied and pasted into the new class with a different root, or delegation can be used.
Only if a class needs the behavior, state and can be considered that the subclass IS-A(n) instance of the superclass should it be considered to inherit from a superclass. Otherwise, other options exist that would be better suited to the purpose, although it may require a little more work up front, it is cleaner in the long run.
There are a few cases where we dont want to allow to change the behavior. For instance, String class, Math.
I don't like inheritance because there's always a better way to do the same thing but when you're making maintenance changes in a huge system sometimes the best way to fix the code with minimum changes is to extend a class a little. Yes, it's usually leads to a bad code but to a working one and without months of rewriting first. So giving a maintenance man as much flexibility as he can handle is a good way to go.

Categories

Resources