Java Doesn't Need to Be So Bad
twitch.nervestaple.com
twitch.nervestaple.com
Never try to abstract something until I'm on my third implementation of something like it. The first time I lack context for what is likely to change. The second time you have to watch out for second system effect, adding all of the things you wanted in the first version. But the third time you tend to have the experience and knowledge to do it right.
This is a rule of thumb that should be drilled into the heads of anyone who is even thinking of drinking the patterns kool-aid.
This really isn't the case. Until you really understand the commonality of the problem, attempting to abstractly define the solution will make your future work all the more difficult when it turns out you didn't really understand all the edge cases and exceptions.
Three use cases are a good number -- by that time you're much more likely to understand the problem, and by avoiding premature abstraction, you'll have an easier time doing the work.
Abstract classes on the other hand are very useful but most Java programmers think... "well what if in the future I need...".
If Java just had traits/mixins, closures, literals, and some syntax brevity it would be a pretty damn descent language... oh wait that's Scala.
Also you don't have to name property accessors getX() and setX() if you don't want to.
which changes the contract from "this component will accept and work with anything implementing this interface" to "this component will accept and work with anything of this class or inheriting from this class". And without multiple inheritance ... Do you feel the difference?
Coding to an interface is a good thing - but it's the concept "interface", not necessarily the language feature named "Interface" that's important. If/when you have multiple concrete objects which share the same interface, it's trivial there to switch references from the concrete type to that of the Interface (you were coding to a conceptual interface representing a consistent abstraction of a single responsibility in the beginning so your Interface is interchangeable, correct?)
you're a lucky person that it has been trivial for you, your teammates and all the known and unknown clients of your code and components. I can only envy your experience.
However, as you point out, if you are presenting a Java API to your known and unknown clients you had better think carefully about which abstractions you are going to expose and interfaces are probably going to be very helpful.
I think that all Java IDEs make it trivial to introduce an interface when it is required, so unless you are producing an API for consumption by a third party you should only introduce an interface when you have multiple implementations, or a third party can legitimately produce their own implementation, and not because you think you may have multiple implementations at sometime in the future.
Also if you have a single implementation naming it InterfaceImpl is just lazy, you almost always have more information that you can use to name it, it might be a InterfaceUsingJdbc or an InterfaceFileBased for example.
I can understand that you don't like candidates not going into detail but I have worked on projects where using interfaces, even if there is not more than one implementation is still best practice as otherwise you are just hard-coupling your dependencies.
You should check out Gosu[1], which is a language that does exactly what you say without adding complexity or being as different from Java as Scala.
[1]: http://gosu-lang.org
Like recommendations against premature optimization, it's just a good rule of thumb.
The first time you write it, just make it work. It works or it doesn't work. Chances are, yes, there's only going to be one of it. So making it "as right as you can" I assume means "it works". "Its reusable" however, is not necessary.
As soon as a "ball of mud" is being created, that is your moment to refactor. If you aren't doing that, then that is your choice. It is not possible to argue that taking an action which causes "development pace to slow way down" is a situation where refactoring would cause a deadline to be missed. Not refactoring will cause the deadline, and many more, to be missed.
I'm in agreement with OP and nupark on the rule of 3.
Oh, and by the way: death to injection frameworks. I want my java code to be readable, tangible java code.
My preference has always been have a constructor which takes in the interfaces required. Its very explicit, makes testing a breeze and with no magic is much easier to read.
The less magic the better.
When you have a strong idea about the direction of the project then you start creating less branches that lead no where.
e.g.: Integration with Twitter. If you don't mocked Twitter client API, you won't be able to write unit-test (or someone will make a lot of excuses of how hard to write unit-tests).
You can work-around DI with having a factory/template method that you'd override or whatnot but that situation won't work 100% in all situations. You may end up writing more code.
YMMV. Use it when you absolutely need it.
I personally have to live with the shame of a very clear and vivid memory
wherein I circled objects that covered nearly four sheets of this paper
and wrote, in my own hand and with a clear-head: "A good candidate for an
abstract factory! :)"
Eventually I realized that the emoticon was mocking me. Laughing at my
presumptuousness, laughing at my premature optimization.
10-12 years ago, I was that guy trying to spot "patterns". Ugh. Hopefully my Clojure hacking will tip my karmic balance back to neutral.It's not that I don't see value in Reflection, it's just that I'm sick of debugging it.
Abstractfactories are not that bad, actually if you're in the habit (like me) to always step in and write an interface before you start any abstract, you pretty soon understand why it's a good or bad idea - interfaces of factories are so damn trivial that even an abstractfreak will see this as redundant work and will want to write an interface of this factory interface and then a factory interface factory through code injection, preferrably through annotations, but it could be from other means such as a properties file or xml configuration, so they think about a factory interface abstract factory (and of course its interface). By then, even the craziest persons give up and just do their job.
Non-reified generics with their ridiculously verbose syntax are the first thing that came to my mind. God forbid you should try to write your own class which uses them.
Not to mention that since spending almost decade of my career working with Java I have since worked with languages that do not have generics, and have not suffered thereby. Generics are, IMO, largely unnecessary.
Yes, this is a small subset of Java, but it is one that continually annoyed me.
This needs to be drilled into the heads of all the people complaining that Go has no generics before they have even tried to use it. (Also Go's interfaces overlap with many common uses of generics, and Go's useful builtin containers take care of most of the rest).
This typically occurs when 1) I am doing enterprise application development, and there are many different instantiations of a particular application, or 2) I am doing enterprise integration, and I have many different libraries and services to work with, sometimes legacy, and often with complex business logic that selects some over others.
Granted, I've seen this pattern used all too often and seen over-abstraction, in general. But, I need to be brave and defend this, given that no one else seems to want to. It does have some legs.
I use this when working with a lot of different teams / companies and coordinating them all and agreeing to how things will work in production. That's especially true when some of those teams / companies may be interchanged with others. This type of solution makes a lot of sense.
However, I would much prefer a dynamic typed solution to avoid the unnecessary boilerplate. And, even better, I would prefer to work only with self-contained software companies that have complete control over their code-base and restrained domain logic. That would be awesome! (but wishful thinking).
Do I want or must use Java? Does not matter to me. The libraries (and their quality) help me write less code and make me feel comfortable (it is psychology, but it matters).