7 ms·
Language wars aside, I liked this: Returning to Java (and Kotlin) development after a couple of months of Go development, [...] I discovered the value of a cer
by brown 8y ago
Language wars aside, I liked this:
Returning to Java (and Kotlin) development after a couple of months of Go development, [...] I discovered the value of a certain sort of "plain speaking" in code.
This resonates with me. I've spent 1 year+ in each of C, C++, C#, PHP, Java, Python, and JS. There are obvious benefits to taking advantage of a platform's strengths, but the "plain" code has merits too. Easier to reason about, often more maintainable, faster to ramp up new team members, etc.
- guitarbill 8y agoIn my experience, Java suffers from this the most because often CS teaches the tools/techniques, but not how/when to use them. For example, the number of times I've seen an interface with only one implementation is ridiculous. (Yes, I know interfaces have other advantages, no I don't think they're worth the trade-off of making debugging harder until you get to boundaries where that sort of abstraction is a real win.) Simpler code almost always wins. Predicting the future is hard, refactoring simple code that does the minimum it needs to is comparatively easy. Don't write what-if code, YAGNI.
- humbleMouse 8y agoWhy is having only one implementation for an interface bad? It neatly organizes all your code and doesn't make debugging harder at all.
- hocuspocus 8y agoHow does having FooService and FooServiceImpl help with code organization at all? It brings nothing but unnecessary noise.
- humbleMouse 8y agoIn my opinion I like hopping through a codebase where everything goes thru an interface. It just seems cleaner to me. Especially when I'm writing new classes I can think about what the interface does and stub the methods out first. So for me it just splits up the workflow in a really nice way and makes things look clean. I see your point though. Furthermore, when opening a new project you can just read through the interfaces quickly and get a good idea of what the code is doing. You can't just read thru a whole bunch of implementations and get as good of an idea.
- hocuspocus 8y agoUse a better IDE? I've worked on my fair share of Spring projects and I don't miss this one bit. Even though I wade through a lot of open source libraries where the only documentation is the source code.
- Larrikin 8y agoFooService removes all the noise and makes it obvious the point of the class.
- Rexxar 8y agoLike header/code in C or C++ ? I'm not a Java programmer but it seems like an abuse of interface if it's done systematically.
- guitarbill 8y agoIt's also silly. If this was the only use-case, you could just generate "interfaces"/headers from the class for the people who want this in e.g. an IDE. No need to liter the codebase with that.
- _old_dude_ 8y agopublic interfaces help to make dependencies clear and honest. If the implementation doesn't provide more methods than the interface (a transparent class in GoF terminology) you should not name it. In Java, the implementation is usually created inside a static method (a static factory) of the interface as a lambda or an anonymous class.
- hocuspocus 8y ago> public interfaces help to make dependencies clear and honest. Again, moot point if there's only one implementation. > If the implementation doesn't provide more methods than the interface (a transparent class in GoF terminology) you should not name it. > In Java, the implementation is usually created inside a static method (a static factory) of the interface as a lambda or an anonymous class. And how's that not needlessly convoluted and ugly? You're illustrating guitarbill's point about applying design patterns blindly.
- ivan_gammel 8y agoIt's test-friendly. The code may not have explicitly defined second implementation, but a simple "@Mock FooService" declaration in a test.
- guitarbill 8y agoThis is a fair point, however in practice there's solution for that (Mockito, as long as the class isn't final). Which is how it should be. Your code shouldn't be untestable, on the other hand you shouldn't have to go out of your way to make it testable by adding more cruft.
- ivan_gammel 8y agoI don't think the design should be based on the requirement to use Mockito library and it's not the only and not always the most convenient way to provide a test implementation. So, no, it's not how it should be.
- vermasque 8y agoInterfaces can also provide read-only references of a instance. Consider interface Foo with accessors only and a MutableFoo implementation with accessors and mutators. The creator of the MutableFoo instance can make all sorts of changes to the instance but then pass it around as a Foo that can't be modified. Another option is to simply put all the state in the constructor so that a Foo never needs to be mutated; however, that might not be elegant in some cases state is incrementally accrued. I do acknowledge that XImpl is kinda ugly as name.
- hocuspocus 8y ago> The creator of the MutableFoo instance can make all sorts of changes to the instance but then pass it around as a Foo that can't be modified. Until you cast the object... You should use truly immutable data types unless you specifically need otherwise, most modern languages and libraries encourage you to do so.
- jayd16 8y agoWhen you only have one implementation, you often have no concept of what a second implementation will look like and you have no idea what concept or task you're delegating to the interface. They just become header files for the single implementation. Now, you can be good at planning ahead and know what the abstraction should be in many cases. This is still much rarer than all cases. Indiscriminately creating an interface for every class means you're probably not giving the interface much thought.
- davidwtbuxton 8y ago> Simpler code almost always wins. Predicting the future is hard, refactoring simple code that does the minimum it needs to is comparatively easy. Don't write what-if code, YAGNI. I strongly agree with this point. I speculate that some people tend to add unnecessary code because they are thinking of all those well-written libraries they use every day, which have evolved to support multiple uses, including the uses that clearly they don't need but they can see are useful to others. Therefore they conclude good software must add features that are useful for other coders!
- on_and_off 8y ago>Simpler code almost always wins I strongly agree ! At my current company we are ramping up the team and want to go from 4 very senior engineers to 35. The very complex architecture based on functional programming that we are using will probably be a major hindrance here. I don't understand your remark on interfaces though. I tend to have many, even for one click method. If I want to have a callback for a list item tap, I create an interface for that very specific item, that way it is very easy to decouple view and business and it also is extremely easy to debug in Intellij. In one click I get from the interface declaration in the viez to it's implemenentation in the business logic. Why does it hinder debugging in your use case ?
- Sylos 8y agoThis is also the reason why I prefer Java over C#. Most differences that C# introduces, are quality of life features for devs writing the code. But they make reading the code worse and mean that junior devs have to learn more in order to understand their senior colleagues' code. Examples of things that C# has over Java: - Operator overloading: .Add() is really not that much more annoying to write... - Properties: Shorthand for getters and setters, because auto-completion isn't a feature in IDEs since forever. And, like Java, they've introduced lambdas, but have then also changed the automated code generation of Properties in their IDEs to use lambdas, because apparently even an IDE needs to be lazy and give junior devs a harder time. - The out-keyword: Somewhat formalized way of passing along a variable to have it populated via side effects by a method. In Java, you'd refactor your code to not need two return values, or you'd return an object with those values in class variables (or you'd just do this dirty side effect method without telling anyone).
- guitarbill 8y ago`out` is a necessary evil to get any sort of sane interop with the Windows API. Otherwise, using a tuple [0] is almost always better. [0] Bit like Python: https://docs.microsoft.com/en-us/dotnet/api/system.tuple?view=netcore-2.1 https://docs.microsoft.com/en-us/dotnet/api/system.tuple?vie...