How to automatically register new subclasses? - java

I'm working on the reporting module of our web-application. There are six reports available to the client, each of them has a code. The problem is that now the module is not closed for modification with respect to potential addition of new reports, thus violating OCP.
To elucidate, I have the following set of classes:
A generic report class, which all other reports inherit:
public abstract class Report
{
private final String code;
Report(String code)
{
this.code = code;
}
public String getCode() { return code; }
public abstract byte[] generate();
}
A servlet which manages POST requests for report generation:
public class ReportServlet extends HttpServlet
{
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
Report requested = ReportRegistry.lookup(req.getParameter("report_code"));
byte[] bytes = requested.generate();
// attach bytes to response
}
}
Report registry, which stores all existing reports for later access:
public class ReportRegistry
{
private static final Map<String, Report> registry = new HashMap<>();
static
{
// Violates OCP!
registerReport( GlobalReport.getInstance() );
registerReport( AvailablePackagesReport.getInstance() );
registerReport( BadgeReport.getInstance() );
registerReport( PlacementReport.getInstance() );
registerReport( TerminalReport.getInstance() );
registerReport( VerActReport.getInstance() );
}
private ReportRegistry() { }
static void registerReport(final Report report)
{
registry.put(report.getCode(), report);
}
public static Report lookup(final String reportCode)
{
return registry.get(reportCode);
}
}
However, ReportRegistry violates OCP, since we need to add an entry to its static block every time a new report is created.
My question is: how can I make any new subclass of Report to be registered automatically, without any explicit mentioning?

I would think OCP would be more applicable to Report itself, and that having ReportRegistry sitting outside of the class hierarchy would be a valid design.
That said, if you want to avoid modifying ReportRegistry each time you create a Report subclass, you could use some reflection tricks to seek out all such subclasses, or create an annotation that ReportRegistry could search for to register all classes with instances.

You should look at https://github.com/ronmamo/reflections. I have never tried this library but it looks like it does what you want (retrieving all subclasses of a known class).
You could then register them in your ReportRegistry static block.

Related

“if” statement vs OO Design

I have enum say ErrorCodes that
public enum ErrorCodes {
INVALID_LOGIN(100),
INVALID_PASSWORD(101),
SESSION_EXPIRED(102) ...;
private int errorCode;
private ErrorCodes(int error){
this.errorCode = error;
} //setter and getter and other codes
}
now I check my exception error codes with this error codes. I don't want to write if this do this, if this do this. How I can solve this problem (writing 10+ if blocks)
Is there any design patter to that situation ?
Thanks
As pointed out by Spoike, using polymorphism to pick the right error handling method is an option. This approach basically defers the 10+ if blocks to the JVM's virtual method lookup, by defining a class hierarchy.
But before going for a full-blown class hierarchy, also consider using enum methods. This option works well if what you plan to do in each case is fairly similar.
For example, if you want to return a different error message for each ErrorCode, you can simply do this:
// Note singular name for enum
public enum ErrorCode {
INVALID_LOGIN(100, "Your login is invalid"),
INVALID_PASSWORD(101, "Your password is invalid"),
SESSION_EXPIRED(102, "Your session has expired");
private final int code;
private final String
private ErrorCode(int code, String message){
this.code = code;
this.message = message;
}
public String getMessage() {
return message;
}
}
Then your error handling code becomes just:
ErrorCode errorCode = getErrorCode();
prompt(errorCode.getMessage());
One drawback of this approach is that if you want to add additional cases, you'll need to modify the enum itself, whereas with a class hierarchy you can add new cases without modifying existing code.
Either you do it with a if-statement or a switch, or you just implement the logic in question into the ErrorCode somehow.
In an OO fashion it all depends on how you want the application or system react to the error code. Lets say you just want it to output somekind of dialog:
public doSomethingWithError() {
ErrorCodes e = getError();
// the source of error, or originator, returns the enum
switch(e) {
case ErrorCodes.INVALID_LOGIN:
prompt('Invalid Login');
case ErrorCodes.INVALID_PASSWORD:
prompt('Invalid password');
// and so on
}
}
We could instead create an ErrorHandler class that does this instead:
// We'll implement this using OO instead
public doSomethingWithError() {
ErrorHandler e = getError();
// the originator now returns an ErrorHandler object instead
e.handleMessage();
}
// We will need the following abstract class:
public abstract class ErrorHandler {
// Lets say we have a prompter class that prompts the message
private Prompter prompter = new Prompter();
public final void handleMessage() {
String message = this.getMessage();
prompter.prompt(message);
}
// This needs to be implemented in subclasses because
// handleMessage() method is using it.
public abstract String getMessage();
}
// And you'll have the following implementations, e.g.
// for invalid logins:
public final class InvalidLoginHandler() {
public final String getMessage() {
return "Invalid login";
}
}
// E.g. for invalid password:
public final class InvalidPasswordHandler() {
public final String getMessage() {
return "Invalid password";
}
}
The former solution is easy to implement, but becomes difficult to maintain as the code grows larger. The latter solution is more complex, (aka. Template Method pattern following the Open-Closed Principle) but enables you to add more methods into the ErrorHandler when you need it (such as restoring resources or whatever). You can also implement this with the Strategy pattern.
You won't get away completely with the conditional statements, but in the latter the conditional is pushed to the part of the code where the error is originated. That way you won't have double maintenance on conditional statements both at the originator and the error handling code.
EDIT:
See this answer by Michael Borgwardt and this answer by oksayt for how to implement methods on Java Enums if you want to do that instead.
Java enums are very powerful and allow per-instance method implementations:
public enum ErrorCode {
INVALID_LOGIN {
public void handleError() {
// do something
}
},
INVALID_PASSWORD {
public void handleError() {
// do something else
}
},
SESSION_EXPIRED {
public void handleError() {
// do something else again
}
};
public abstract void handleError();
}
Then you can simply call errorCode.handleError();. However, it is questionable whether an ErrorCode enum is really the right place for that logic.
I believe the best you can do is implementing the strategy pattern. This way you won't have to change existing classes when adding new enums but will still be able to extend them. (Open-Closed-Principle).
Search for Strategy Pattern and Open Closed Principle.
You can create a map of error codes(Integer) against enum types
Edit
In this solution, once the map is prepared, you can look up an error code in the map and thus will not require if..else look ups.
E.g.
Map<Integer, ErrorCodes> errorMap = new HashMap<Integer, ErrorCodes>();
for (ErrorCodes error : ErrorCodes.values()) {
errorMap.put(error.getCode(), error);
}
Now when you want to check an error code coming from your aplpication, all you need to do is,
ErrorCodes error = errorMap.get(erro_code_from_application);
Thus removing the need for all the if..else.
You just need to set up the map in a way that adding error codes doesn't require changes in other code. Preparation of the map is one time activity and can be linked to a database, property file etc during the initialization of your application
In my opinion there is nothing wrong with ErrorCodes as enums and a switch statement to dispatch error handling. Enums and switch fit together really well.
However, maybe you find the following insteresting (kind of over-design), see an Example
or "Double dispatching" on Wikipedia.
Assumed requirements:
Error-handling should be encapsulated in an own class
Error-handling should be replacable
Type safety: Whenever an error is added, you are forced to add error handling at each error-handler implementation. It is not possible to "forget" an error in one (of maybe many) switch statments.
The code:
//Inteface for type-safe error handler
interface ErrorHandler {
void handleInvalidLoginError(InvalidLoginError error);
void handleInvalidPasswordError(InvalidLoginError error);
//One method must be added for each kind error. No chance to "forget" one.
}
//The error hierachy
public class AbstractError(Exception) {
private int code;
abstract public void handle(ErrorHandler);
}
public class InvalidLoginError(AbstractError) {
private String additionalStuff;
public void handle(ErrorHandler handler) {
handler.handleInvalidLoginError(this);
}
public String getAdditionalStuff();
}
public class InvalidPasswordError(AbstractError) {
private int code;
public void handle(ErrorHandler handler) {
handler.handleInvalidPasswordError(this);
}
}
//Test class
public class Test {
public void test() {
//Create an error handler instance.
ErrorHandler handler = new LoggingErrorHandler();
try {
doSomething();//throws AbstractError
}
catch (AbstractError e) {
e.handle(handler);
}
}
}

How to avoid sonarqube marking a code region as duplicate which is not a (harmful) repetition?

I have the following code setup (not all parts are shown in detail):
ClassInterface and its abstract implementation AbstractClassToBuild
BuilderInterface and its abstract implementation AbstractBuilder
There are several specific implementations of AbstractClassToBuild based on
different object types.
A simplified example of such an iplementation is the following ClassToBuild.
The relevant region which is marked as duplicate by sonarqube for all implementations looks the same for all of these implementations. The following code snippet uses comments to highlight the relevant region:
public final ClassToBuild extends AbstractClassToBuild {
// ... whatever belongs to the class ClassToBuild
// START OF DUPLICATE REGION
public static final class Builder extends AbstractBuilder {
private Builder() {
super();
}
private Builder(Object object) {
super(object);
}
public static final Builder newInstance() {
return new Builder();
}
#Override
public final BuilderInterface cloneInstance() {
return new Builder(this.object);
}
#Override
#SuppressWarnings("unchecked")
protected final <T extends ClassInterface> Class<T> myClass() {
// END OF DUPLICATE REGION
return (Class<T>) ClassToBuild.class;
}
#Override
protected final ClassInterface create() {
return new ClassToBuild(this.object);
}
}
}
IMHO this kind of scenario is a valid, non-repetitive implementation
as there is no real (harmful) code duplication because each Builder class
belongs to a specific class. Please correct me if you smell a design or implementation issue here.
Technical setup:
sonarqube server version 6.2 with Java plugin 4.4
Oracle JDK 1.8u121
Anyways, what can be done to prevent sonarqube marking these regions as duplicate?
Addition:
According to the sonarqube documentation:
"A piece of code is considered as duplicated as soon as there is the same sequence of 10 successive statements whatever the number of tokens and lines."
and the explanation of what a (java) statement is:
"Number of statements as defined in the Java Language Specification but without block definitions. Statements counter gets incremented by one each time a following keyword is encountered: if, else, while, do, for, switch, break, continue, return, throw, synchronized, catch, finally.
Statements counter is not incremented by a class, method, field, annotation definition, package declaration and import declaration."
With this, for me an additional question comes up: Does sonarqube mark these region as duplicate by mistake?
Anyways, what can be done to prevent sonarqube marking these regions as duplicate?
On the code side, perhaps you could add some of this boilerplate to the abstract class?
On the SonarQube side, you could update the project settings to Ignore Duplications on those files.
Does sonarqube mark these region as duplicate by mistake?
No. The two sections of documentation use a slightly different meaning of the word "statement". These (admitted) duplications are reported on purpose.
In this case, a workaround is to add the specific class prefix to each builder class in the methods 'newInstance()' and 'cloneInstance()', for the example this would be ClassToBuild.. The code will do the same and sonarqube does not complain any more.
The updated example looks like this:
public final ClassToBuild extends AbstractClassToBuild {
// ... whatever belongs to the class ClassToBuild
public static final class Builder extends AbstractBuilder {
private Builder() {
super();
}
private Builder(Object object) {
super(object);
}
public static final ClassToBuild.Builder newInstance() {
return new ClassToBuild.Builder();
}
#Override
public final BuilderInterface cloneInstance() {
return new ClassToBuild.Builder(this.object);
}
#Override
#SuppressWarnings("unchecked")
protected final <T extends ClassInterface> Class<T> myClass() {
return (Class<T>) ClassToBuild.class;
}
#Override
protected final ClassInterface create() {
return new ClassToBuild(this.object);
}
}
}

Java class & interface naming trouble [closed]

In my github repo I have hierarchy of classes and of course serialization/deserialization mechanism is present for them.
I serializing them manually via Externalizable and I want to take all of the code that generates values, needed for instance serialization out of this classes to keep all simple and flexible (or just to take out this mess)
So what I basically want to do is to create SerializationHelpers and DeserializationHelpers classes, where the name of particular class will be NameOfClassSerializationHelper.
Names like this are 29 characters in worst case, but I think that this is too much. Yeah of course it provides better understanding of what's going on and the name is less then 50 chars and user will never see this classes.
Here is scatch of interface hierarchy for those helper classes.
So as you can see I reduced Serialization to Ser and Deserialization to Deser but seems like it hurts readabuility.
For example class that implements TrieSerializationHelper will have name LinkedTrieSerializationHelper.
There is one another trouble: I can't place those serialization/deserialization helpers to another package because they use some package-private class (Node, as you can see from restoreRooot method of WordGraphDeserHelper).
So I'm totally confused how to do better and exactly what I have to do. Thanks in advance.
You may also want to create something like Externalizer interface with specific implementations (TrieExternalizer) and move all logic there so your main classes (I think, they are Trie and DAWG) won't be overloaded with serialization/deserialization.
Example:
public interface Externalizer<T> {
void write(T object, ObjectOutput out);
void read(T object, ObjectInput in);
}
class TrieExternalizer implements Externalizer<Trie> {
public void write(Trie object, ObjectOutput out) throws IOException {
out.writeUTF(object.getSomeField());
}
public void read(Trie object, ObjectInput in) throws IOException {
object.setSomeField(in.readUTF());
}
}
class Trie implements Externalizable {
private String someField;
private static final Externalizer<Trie> externalizer = new TrieExternalizer();
public String getSomeField() {
return someField;
}
public void setSomeField(String someField) {
this.someField = someField;
}
public void writeExternal(ObjectOutput out) throws IOException {
externalizer.write(this, out);
}
public void readExternal(ObjectInput in) throws IOException {
externalizer.read(this, in);
}
}

Interface or Abstract class

My Java is a bit rusty, and I am sure I am doing this wrong
I have a whole bunch of different fileformats that I need to export. So I though I would create a class for each format, and have them all implement a standard Interface.
Each document has a name, and default filename, but I am not sure how I should store that data correctly. Initially I thought it should be a static final string in the concrete class, but then how do I enforce it via the interface so that all concrete classes have to supply that info.
Hope this makes sense, this is what I have so far
public interface IExporter {
public void exportToFile(String filename) throws SQLException, IOException;
public String getDocumentName();
public String getDefaultFilename();
}
-
public class LaneDrawCsvExporter implements IExporter {
public void exportToFile(String filename) throws SQLException, IOException {
// code to export document here
}
public String getDocumentName() {
return "Lane Draw";
}
public String getDefaultFilename() {
return "Lane Draw.CSV";
}
}
Your approach looks reasonable. As for how to enforce having to supply doc name and default filename, I think what you've done works -- having methods in the interface that return the doc name and the default filename. All concrete classes implementing the interface will have to implement those methods to even be able to compile. Thus you've enforced the requirement that the concrete classes have to supply those names. I think trying to enforce that concrete classes have a particularly-named static final string is a red herring since you have those methods available.
Separate the information on the files from the Exporters. So you have a bunch of Exporters whose only tasks is to export the file, and some object that links to the file and the right exporter (and maybe some addition constructs to decide which Exporter to use).
I would create an abstract class called BaseIEExporter or something and then provide a couple (or more) instance variables and their getter and setter methods within (like name/filename). Or the common characteristics between all implementing classes.
When you create a new class extending the abstract class, just have the overloaded constructor provide whatever parameters you need supplied.
This way the process of creation of a certain class, would require you to provide the needed information i.e the constructor requires it.
If you need to force to set up the initial state of your class(filename etc) it would be better to use an Abstract class.
The below is just to give you an idea(you need to refactor it)
NOTE: As there is no default (or no-arg) constructor in the parent abstract class the constructor used in subclasses must be specified.
public abstract class Exporter {
string FileName
public Exporter ( string fileName ) {
FileName= fileName
}
public void exportToFile() ....
public String getDocumentName()....
public String getDefaultFilename()....
}
-
public class LaneDrawCsvExporter extends Exporter {
public LaneDrawCsvExporter ( string fileName ) {
super(fileName)
}
public void exportToFile() throws SQLException, IOException {
// code to export document here
}
public String getDocumentName() {
return "Lane Draw";
}
public String getDefaultFilename() {
return "Lane Draw.CSV";
}
}

How can I design my Java / C# library so it stays binary compatible in case of future changes?

Task: I am designing a library which will be used by developers.
Objective: I need to make sure that changes in future versions will not impact existing developers.
Example:
Situation during first release:
There is one class
public class ClassSample
{
String methodSample(String para1,String Para2, int Para3, String Para4);
}
Situation during second release:
Requirements:
Response of methodSample can return multiple values.
More parameters are needed in methodSample method.
Solution: One way could be just add another overloaded method which will have new parameters and return object rather than built-in data type.
But problem with above solution is, it will have too many overloaded methods in future, too many parameters will be overkill.
Modified Solution 1:
void methodSample(Request request, Response response)
In each release(obviously if required), I will modify Request & Response classes to have new additional methods to get/set values. There will be a problem in this case as inside the method, I won't be able to differentiate whether caller is of Version10 or Version20.
Modified Solution 2:
void methodSample(AbsractRequest request, AbstractResponse response)
In each release we can extend derived class like Request200 extends Request100 extends AbstractRequest, similarly for response classes. In this case I can check inside method whether caller is of Version10 or Version20 by checking instance typing.
In summary Modified Solution 2 looks good to me, what about your thoughts ?
I would go for Modified Solution 1, but with the addition of a get/set Version method in the class.
Your library can the use getVersion find out which behaviour the user program is expecting
I realise this might be a bit late but thought might be useful to you or someone else.
I've created an SDK in the past that required versioning and did something very similar to what I posted below and it worked a treat.
The idea being that all messages derive from an abstracted class as you suggested, but there is a static that is set in the calling application right at the start. All requests then simply set a Version property equal to that of the static. This way its only specified once in the whole application.
When you add new versions, just add to the enum. I actually used an integer in mine and incremented it but I think an Enum is always more maintainable.
Enjoy!
namespace SilverlightClassLibrary1
{
public enum SDKVersions
{
NonSpecific = 0,
Version100,
Version200,
}
public abstract class RequestBase
{
public static SDKVersions SystemSDKVersion { get; set; }
public SDKVersions RequestSDKVersion { get; set; }
protected RequestBase()
{
this.RequestSDKVersion = RequestBase.SystemSDKVersion;
}
}
public class SimpleDataRequest : RequestBase
{
public String Data { get; set; }
}
public class SimpleDataResponse
{
public String Response { get; set; }
}
public class SomeSDKFunctionality
{
public static void RandomSDKFunction(SimpleDataRequest request, out SimpleDataResponse response)
{
switch (request.RequestSDKVersion)
{
case SDKVersions.Version100:
//Legacy response
response = new SimpleDataResponse()
{
Response = "Helo " + request.Data,
};
break;
default:
//Fixed / Updated Response
response = new SimpleDataResponse()
{
Response = "Hello " + request.Data + "!",
};
break;
}
}
}
}
namespace MyExternalApplication
{
public class Main
{
public void ApplicationEntryPoint()
{
//Specify a specific version you intend to use
RequestBase.SystemSDKVersion = SDKVersions.Version100;
}
public void ButtonClickExample()
{
SimpleDataResponse response;
SomeSDKFunctionality.RandomSDKFunction(new SimpleDataRequest()
{
Data = "James",
}, out response);
}
}
}

Resources