I have a big class, which is used on the user interface of an application. It serves around 20 modules. For only one Module for the time being I need a different formation of number on a Label. The applying of formation is programatically only a line of source code. The separation of the cases can be done either by the use of a boolean flag variable, or by applying inheritance:
By boolean flag variable:
class MyClass{
private boolean isYear;
...
public setValue(){
...
if(!isYear)
doFormat();
...
}
}
The variable isYear is set of course externally, when a module serves for year valus is needed.
By applying inheritance I have to create a new class which derives from MyClass, i.e. MyYearClass and merely override the method setValue(). I think in the OO-programming the second approach is recommended, but I have heard also the opinion that in this case it makes the code complicated, more nebulous, less neat and it seems generally an overkill when only one line of code is to be changed. What approach do you consider recommendable?
As always, it depends. It can be one line now but maybe a lot more later. I agree that overengineering your code is bad but if you feel that the current design will change (and it usually does) you can use a simple design pattern here and there. For your problem (described shortly) I believe you can create a simple Factory and have that factory return for you one of the subclasses of MyClass you need when you need it.
Good design practices will favour the second method (inheritance) as it is easier to manage in the long run. When you start adding specific code to a common class, you are opening a can of worms. Maybe not you, but a developer working after you will add another feature, and another feature to the same class and then support becomes a nightmare.
What worries me more is your "I have a big class" quote. Good design principles will tell you to break it apart.
If your class has more than, say, 1000 lines, it's a good candidate for refactoring into specific functionalities.
The second approach is really better generally. But in your case you have a small class with simple logic. If you know that you are going to change this class a lot and it will become bigger and more complicated, then split it now. Otherwise you might leave it as it is, and postpone the refactoring for a future moment if you feel the class becomes too complicated. Instead, focus on other part of your application.
I think the second approach is the best practice. It might seem a bit superfluous but it is always best to keep your programming as modular as possible. Just imagine if someone else was using your code or you were using it later on and couldn't exactly remember how the MyClass worked but all you wanted to do was use the functionality of MyYearClass.
Related
there are two questions with microstream database and its class StorageConfiguration:
1) What ist the difference of the methods New() and Builder() and the DEFAULT construct?
2) Why the methods are writting uppercased? That does not seem to be Java naming convention.
Thanks for any answers!
I am the MicroStream lead developer and I can gladly answer those questions.
To 1)
"New" is a "static factory method" for the type itself.
"Builder" is a static factory method for a "builder" instance of the type.
Both terms can be perfectly googled for more information about them.
A quick service as a starting point:
"static factory method":
https://www.baeldung.com/java-constructors-vs-static-factory-methods
"builder pattern":
https://en.wikipedia.org/wiki/Builder_pattern
--
To your actually second question, about the "DEFAULT" construct:
If I may, there is no "DEFAULT" construct, but "Default".
(Conventions are important ... mostly. See below.)
"Default" is simply the default implementation (= class) of the interface StorageConfiguration.
Building a software architecture directly in classes quickly turns out to be too rigid and thus bad design. Referencing and instantiating classes directly creates a lot of hardcoded dependencies to one single implementation that can't be changed or made more flexible later on. Inheritance is actually only very rarely flexible enough to be a solution for arising architecture flexibility problems. Interfaces, on the other hand, only define a type and the actual class implementing it hardly matters and can even be easily interchangeable. For example, by only designing via interfaces, every instance can easily be "wrapped" by any desired logic via using the decorator pattern. E.g. adding a logging aspect to a type.
There is a good article with an anecdote about James Gosling (the inventor of Java) named "Why extends is evil" that describes this:
https://www.javaworld.com/article/2073649/why-extends-is-evil.html
So:
"Default" is just the default class implementing the interface it is nested in. It makes sense to name such a class "Default", doesn't it? There can be other classes next to it, like "Wrapper" or "LazyInitializing" or "Dummy" or "Randomizing" or whatever.
This design pattern is used in the entire code of MicroStream, giving it an incredibly flexible and powerful architecture. For example:
With a single line of code, every part of MicroStream (every single "gear" in the machine) can be replaced by a custom implementation. One that does things differently (maybe better?) or fixes a bug without even needing a new MicroStream version. Or one that adds logging or customized exception handling or that introduces object communication where there normally is none. Maybe directly with the application logic (but at your own risk!). Anything is possible, at least inside the boundaries of the interfaces.
Thinking in interfaces might be confusing in the beginning (which is why a lot of developers "burn mark" interfaces with a counterproductive "I" prefix. It hurts me every time I see that), but THEY are the actual design types in Java. Classes are only their implementation vehicles and next to irrelevant on the design level.
--
To 2)
I think a more fitting term for "static factory method" is "pseudo constructor". It is a method that acts as a public API constructor for that type, but it isn't an actual constructor. Following the argumentation about the design advantages of such constructor-encapsulating static methods, the question about the best, consistent naming pattern arose to me. The JDK gives some horribly bad examples that should not be copied. Like "of" or "get". Those names hardly carry the meaning of the method's purpose.
It should be as short but still as descriptive as possible. "create" or "build" would be okay, but are they really the best option? "new" would be best, but ironically, that is a keyword associated with the constructors that should be hidden from public API. "neW" or "nEw" would look extremely ugly and would be cumbersome to type. But what about "New"? Yes, it's not strictly Java naming conventions. But there already is one type of methods that does is an exception to the general naming rule. Which one? Constructors! It's not "new person(...") but "new Person(...)". A method beginning with a capital letter. Since the beginning of Java. So if the static method should take the place of a constructor, wouldn't it be quite logical and a very good signal to apply that same exception ... or ... "extension" of the naming convention to that, too? So ... "New" it is. Perfectly short, perfectly clear. Also not longer and VERY similar to the original constructors. "Person.New" instead of "new Person".
The "naming convention extension" that fits BOTH naming exceptions alike is: "every static method that starts with a capital letter is guaranteed to return a new instance of that type." Not a cached one. Always a new one. (this can be sometime crucial to guarantee the correctness of algorithms.)
This also has some neat side effects. For example:
The pseudo-constructor method for creating a new instance of
"StorageConfigurationBuilder" can be "StorageConfiguration.Builder()".
It is self-explaining, simple, clear.
Or if there is a method "public static Vector Normalized(Vector v)", it implicitely
tells that the passed instance will not be changed, but a new instance will
be returned for the normalized vector value. It's like having the
option to give constructors proper names all of a sudden. Instead of
a sea of different "Vector(...)" methods and having to rely on the
JavaDoc to indirectly explain their meaning, the explanation is right
there in the name. "New(...)", "Normalized(...)", "Copy(...)" etc.
AND it also plays along very nicely with the nested-Default-class
pattern: No need to write "new StorageConfiguration.Default()" (which
would be bad because too hardcoded, anyway), but just
"StorageConfiguration.New" suffices. It will internally create and
return a new "StorageConfiguration.Default" instance. And should that
internal logic ever change, it won't even be noticable by the API
user.
Why do I do that if no one else does?
If one thinks about it, that cannot be a valid argument. I stick VERY closely to standards and conventions as far as they make sense. They do about 99% of the time, but if they contain a problem (like forbidding a static method to be called "new") or lacking a perfectly reasonable feature (like PersonBuilder b = Person.Builder()" or choosing properly speaking names for constructors), then, after careful thought, I br... extend them as needed. This is called innovation. If no one else had that insight so far, bad for them, not for me. The question is not why an inventor creates an improvment, but why no one else has done it so far. If there is an obvious possibility for improvement, it can't be a valid reason not to do it just because no one else did it. Such a thinking causes stagnation and death of progress. Like locking oneself in a 1970ies data storing technology for over 40 years instead of just doing the obviously easier, faster, direct, better way.
I suggest to see the capital letter method naming extension as a testimony to innovation: If a new idea objectively brings considerably more advantages than disadvantages, it should - or almost MUST - be done.
I hereby invite everyone to adopt it.
At the company I work for there's a document describing good practices that we should adhere to in Java. One of them is to avoid methods that return this, like for example in:
class Properties {
public Properties add(String k, String v) {
//store (k,v) somewhere
return this;
}
}
I would have such a class so that I'm able to write:
properties.add("name", "john").add("role","swd"). ...
I've seen such idiom many times, like in StringBuilder and don't find anything wrong with it.
Their argumentation is :
... can be the source of synchronization problems or failed expectations about the states of target objects.
I can't think of a situation where this could be true, can any of you give me an example?
EDIT The document doesn't specify anything about mutability, so I don't see the diference between chaining the calls and doing:
properties.add("name", "john");
properties.add("role", "swd");
I'll try to get in touch with the originators, but I wanted to do it with my guns loaded, thats' why I posted the question.
SOLVED: I got to talk with one of the authors, his original intention was apparently to avoid releasing objects that are not yet ready, like in a Builder pattern, and explained that if a context switch happens between calls, the object could be in an invalid state. I argued that this had nothing to do with returning this since you could make the same mistake buy calling the methods one by one and had more to do with synchronizing the building process properly. He admitted the document could be more explicit and will revise it soon. Victory is mine/ours!
My guess is that they are against mutable state (and often are rightly so). If you are not designing fluent interfaces returning this but rather return a new immutable instance of the object with the changed state, you can avoid synchronization problems or have no "failed expectations about the states of target objects". This might explain their requirement.
The only serious basis for the practice is avoiding mutable objects; the criticism that it is "confusing" and leads to "failed expectations" is quite weak. One should never use an object without first getting familiar with its semantics, and enforcing constraints on the API just to cater for those who opt out of reading Javadoc is not a good practice at all— especially because, as you note, returning this to achieve a fluent API design is one of the standard approaches in Java, and indeed a very welcome one.
I think sometimes this approach can be really useful, for example in 'builder' pattern.
I can say that in my organization this kind of things is controlled by Sonar rules, and we don't have such a rule.
Another guess is that maybe the project was built on top of existing codebase and this is kind of legacy restriction.
So the only thing I can suggest here is to talk to the people who wrote this doc :)
Hope this helps
I think it's perfectly acceptable to use that pattern in some situations.
For example, as a Swing developer, I use GridBagLayout fairly frequently for its strengths and flexibility, but anyone who's ever used it (with it's partener in crime GridBagConstraints) knows that it can be quite verbose and not very readable.
A common workaround that I've seen online (and one that I use) is to subclass GridBagConstraints (GBConstraints) that has a setter for each different property, and each setter returns this. This allows for the developer to chain the different properties on an as-needed basis.
The resultant code is about 1/4 the size, and far more readable/maintainable, even to the casual developer who might not be familiar with using GridBagConstaints.
I have a project (related to graph algorithms). It is written by someone else.
The code is horrible:
public fields, no getters/setters
huge methods, all public
some classes have over 20 fields
some classes have over 5 constructors (which are also huge)
some of those constructors just leave many fields null
(so I can't make some fields final, because then every second constructor signals errors)
methods and classes rely on each other in both directions
I have to rewrite this into a clean and understandable API.
Problem is: I myself don't understand anything in this code.
Please give me hints on analyzing and understanding such code.
I was thinking, perhaps, there are tools which perform static code analysis
and give me call graphs and things like this.
Oh dear :-) I envy you and not at the same time..ok let's take one thing at a time. Some of these things you can tackle yourself before you set a code analyzing tool loose at it. This way you will gain a better understanding and be able to proceed much further than with a simple tool
public fields, no getters/setters
make everything private. Your rule should be to limit access as much as possible
huge methods, all public
split and make private where it makes sense to do so
some classes have over 20 fields
ugh..the Builder pattern in Effective Java 2nd Ed is a prime candidate for this.
some classes have over 5 constructors (which are also huge)
Sounds like telescoping constructors, same pattern as above will help
some of those constructors just left many fields null
yep it is telescoping constructors :)
methods and classes rely on each other in both directions
This will be the least fun. Try to remove inheritance unless you're perfectly clear
it is required and use composition instead via interfaces where applicable
Best of luck we are here to help
WOW!
I would recommend: write unittests and then start refactoring
* public fields, no getters/setters
start by making them private and 'feel' the resistance on compiler errors as metric.
* huge methods, all public
understand their semantics, try to introdue interfaces
* some classes have over 20 fields
very common in complex appilcations, nothing to worrie
* some classes have over 5 constructors (which are also huge)
replace them by by buider/creator pattern
* some of those constructors just left many fields null
see above answer
* methods and classes rely on each other in both directions
decide whether to to rewrite everything (honestly I faced cased where only 10% of the code was needed)
Well, the clean-up wizard in eclipse will scrape off a noticable percentage of the sludge.
Then you could point Sonar at it and fix everything it complains about, if you live long enough.
For static analysis and call graphs (no graphics, but graph structures), you can use Dependency Finder.
Use an IDE that knows something about refactoring, like IntelliJ. You won't have situations where you move one method and five other classes complain, because IntelliJ is smart enough to make all the required changes.
Unit tests are a must. Someone refactoring without unit tests is like a high-wire performer without a safety net. Get one before you start the long, hard climb.
The answer may be: patience & coffee.
This is the way I would do it:
Start using the code , e.g. from within a main method, as if it were used by the other classes - same arguments, same invocation orders. Do that inside a debugger, as you see each step that this class makes.
Start writing unit tests for that functionality. Once you have reached a reasonable coverage, you will start to notice that this class probably has too many responsibilities.
while ( responsibilities != 1 ) {
Extract an interface which expresses one responsibility of that class.
Make all callers use that interface instead of the concrete type;
Extract the implementation to a separate class;
Pass the new class to all callers using the new interface.
}
Not saying tools like Sonar, FindBugs etc. that some have already mentiones don't help, but there are no magic tricks. Start from something you do understand, create a unit test for it and once it runs green start refactoring piece by piece. Remember to mock dependencies as you go along.
Sometimes it is easier to rewrite something from scratch. Is this 'horrible code' working as intended or full of bugs? It is documented?
In my current project, deleting my predessor's work nearly in its entirety, and rewriting it from scratch, was the most efficient approach. Granted, this was an extreme case of code obfuscation, utter lack of meaningful comments, and utter incompetence, so your mileage may vary.
Though some legacy code might be barely comprehensible, still it can be refactored and improved to legibility in a stepwise fashion. Have you seen Joshua Kerievsky's Refactoring To Patterns book? -- it's good on this.
We recently had a code review . One of my classes was used so that I could return/pass more than one type of data from/to methods . The only methods that the class had were getters/setters . One of the team's members ( whose opinion I respect ) said that having a class like that is bad practice ( and not very OOP ) . Why is that ?
There's an argument that classes should either be "data structures" (i.e., focus on storing data with no functionality) or "functionality oriented" (i.e., focus on performing certain actions while storing minimal state). If you follow that argument (which makes sense but isn't always easy to do) then there is nothing necessarily wrong with that.
In fact, one would argue that beans and entity beans are essentially that - data containers with getters and setters.
I have seen certain sources (e.g., the book "clean code") arguing that one should avoid methods with multiple parameters and instead pass them as a single object with getters and setters. This is also closer to the "smalltalk model" of named parameters where order does not matter.
So I think that when used appropriately, your design makes sense.
Note that there are two separate issues here.
Is a "struct-like" class sensible?
Is creating a class to return multiple values from a method sensible?
Struct-like classes
An object class should -- for the most part -- represent a class of real-world objects. A passive, struct-like java bean (all getters and setters) may represent a real-world thing.
However, most real-world things have rules, constraints, behaviors, and basic verbs in which they engage. A struct-like class is rarely a good match for a real-world thing, it's usually some technical thing. That makes it less than ideal OO design.
Multiple returns from a method
While Python has this, Java doesn't. Multiple return values isn't an OO question, per se. It's a question of working through the language limitations.
Multiple return values may mean that an object has changed state. Perhaps one method changes the state and some group of getters return the values stemming from this state change.
To be honest, it sounds fine to me. What alternative did the reviewer suggest?
Following OOP "best practices" and all is fine, but you've got to be pragmatic and actually get the job done.
Using Value Objects like this (OO speak for 'struct') is a perfectly legitimate approach in some cases.
In general, you'll want to isolate the knowledge needed to operate upon a class into the class itself. If you have a class like this, either it is used in multiple places, and thus can take on some of the functionality in both of those places, or it is in a single place, and should be an inner class. If it is used in multiple ways, but in completely different ways, such that there is no shared functionality, having it be a single class is misleading, indicating a shared functionality where there is none.
However, there are often specific reasons for where these general rules may or may not apply, so it depends on what your class was supposed to represent.
I think he might be confusing "not very OOP" for bad practice. I think he expected you to provide several methods that would each return 1 value that was needed (as you will have to use them in your new class anyway that isn't too bad).
Note that in this case you probably shouldn't use getters/setters, just make the data public. No this is "not very OOP" but is the right way to do it.
Maybe Josh Bloch offers some insight into this here.
I just found myself creating a class called "InstructionBuilderFactoryMapFactory". That's 4 "pattern suffixes" on one class. It immediately reminded me of this:
http://www.jroller.com/landers/entry/the_design_pattern_facade_pattern
Is this a design smell? Should I impose a limit on this number?
I know some programmers have similar rules for other things (e.g. no more than N levels of pointer indirection in C.)
All the classes seem necessary to me. I have a (fixed) map from strings to factories - something I do all the time. The list is getting long and I want to move it out of the constructor of the class that uses the builders (that are created by the factories that are obtained from the map...) And as usual I'm avoiding Singletons.
A good tip is: Your class public API (and that includes it's name) should reveal intention, not implementation. I (as a client) don't care whether you implemented the builder pattern or the factory pattern.
Not only the class name looks bad, it also tells nothing about what it does. It's name is based on its implementation and internal structure.
I rarely use a pattern name in a class, with the exception of (sometimes) Factories.
Edit:
Found an interesting article about naming on Coding Horror, please check it out!
I see it as a design smell - it will make me think if all those levels of abstraction are pulling enough weight.
I can't see why you wanted to name a class 'InstructionBuilderFactoryMapFactory'? Are there other kinds of factories - something that doesn't create an InstructionBuilderFactoryMap? Or are there any other kinds of InstructionBuildersFactories that it needs to be mapped?
These are the questions that you should be thinking about when you start creating classes like these. It is possible to just aggregate all those different factory factories to just a single one and then provide separate methods for creating factories. It is also possible to just put those factory-factory in a different package and give them a more succinct name. Think of alternative ways of doing this.
Lots of patterns in a class name is most definitely a smell, but a smell isn't a definite indicator. It's a signal to "stop for a minute and rethink the design". A lot of times when you sit back and think a clearer solution becomes apparent. Sometimes due to the constraints at hand (technical/time/man power/etc) means that the smell should be ignored for now.
As for the specific example, I don't think suggestions from the peanut gallery are a good idea without more context.
I've been thinking the same thing. In my case, the abundance of factories is caused by "build for testability". For example, I have a constructor like this:
ParserBuilderFactoryImpl(ParserFactory psF) {
...
}
Here I have a parser - the ultimate class that I need.
The parser is built by calling methods on a builder.
The builders (new one for each parser that needs to be built) are obtained from builder factory.
Now, what the h..l is ParserFactory? Ah, I am glad you asked! In order to test the parser builder implementation, I need to call its method and then see what sort of parser got created. The only way to do it w/o breaking the incapsulation of the particular parser class that the builder is creating is to put an interception point right before the parser is created, to see what goes into its constructor. Hence ParserFactory. It's just a way for me to observe in a unit test what gets passed to the constructor of a parser.
I am not quite sure how to solve this, but I have a feeling that we'd be better off passing around classes rather than factories, and Java would do better if it could have proper class methods rather than static members.