Java: Real or Not?
java.metagno.me
java.metagno.me
I think the problem is that OOP is automatically considered "virtuous", despite the context. There's nothing wrong with the single responsibility principle and what not, but there is something wrong with thinking that classes and objects are always the best way to approach a problem. Java ends up being the target of jokes because by forcing everything into classes/objects even when it doesn't make sense, it leads to cartooned versions of those ideas.
My solution has been to think of code locality as being valuable. I start off writing something the straightforward way. When I go to implement something similar, I decide whether to abstract the code or not based on how much easier/harder it will be to naively trace the code. If I've done this thing 3 or 4 times, it's a concern and should be separated. If I'm just making something shorter/"nicer"/DRYer I should probably just write stupid code.
DRY, SRP, LSP, OCP are very valuable. There's a reason there's a score of enterprise-grade software being written with exactly those principles in mind. I am not discounting Functional Programming in anyway. But to dismiss OOP and the design patterns is a fool's errand. It has its place, and rightly so.
Look at what the programming Lords (Ken Thompson! Rob Pike! Lars Bak!) at Google came up with when they sat down to design a language-- Go (which is part-OO, part-imperative [1]), or Dart (OO again). OO detractors often point out that "popular opinion isn't always right" and that "people are afraid of change" and there's some level of truth to that, but the fact is, a lot of developers out there are proficient with OO, and see it as a good way to develop massive programs (1 million plus SLOC) unless some radical shift happens in the coming years [2].
[1] https://golang.org/doc/faq#Is_Go_an_object-oriented_language
This is where the mess begins, because it becomes so cryptic to figure out how to use the FactoryFactory to create your own Factory to create some other types you need. It may be trivial to people who've been hacking with the same languages and frameworks for years, but the principle of least surprise is abandonded for new users attempting to use a framework for the first time.
Functional programming suffers from the same overuse of idioms which are unwelcoming to novices, and often throws away some useful ones in favor of ease of use. FP doesn't necessarily dismiss OOP, and it's often used in combination with functions to write practical programs.
Functional programmers don't see OOP as a problem - it's a very practical tool. The problem is that it's the wrong tool for many problems - particularly if you're just computing functions[1]. That a lot of developers are proficient with OOP and see it as a good way to develop programs is part of the cause - they're blind to alternative methodologies and shoehorning something into an object where it doesn't fit is seen as a being skillful. Also, anything that doesn't conform to the language's narrow view of "the right way" is considered an anti-pattern.
[1]:http://www.yegor256.com/2014/05/05/oop-alternative-to-utilit...
That's why TDD is absolutely fundamental. In theory TDD can help fight over-engineering, and keep focus on relevant code. SOLID and design patterns are then here to help refactor code when a spec changes. They are recipes.
Obviously TDD fizzbuzz done correctly would have resulted in a single class implemented. Now imagine requirements changes and booze should be printed if the number can be divided by 20,breeze if the number can be divided by 40,bubble when divisible by 56, the easiest way to refactor that single class would be to introduce a CHAIN OF RESPONSIBILITY. Which again is not necessary at first place, if the number of cases remains small.
In your example we can observe that we still only have one action: print $VARIABLE if $COUNTER mod $VALUE. This doesn't call for anything like a chain of responsibility, since it can be solved by a collection of tuples and a for loop.
My personal guess about the difference between an average programmer and a good one is that the good one knows when to add space for more features (because he can anticipate the customers needs).
In the case of Spring though, they have a tough problem to solve. They are gluing technologies together, so they are always going to have factories of factories, adapter of adapter, and that kind of things. And if in the bunch of tech they glue there is an outlier that behaves unlike the other, or a poorly designed one, they will need to handle it somehow.
Another feature that weights on Spring design is that almost the whole framework is public. Generally you would have a core architecture and well defined key extension points. Not with Spring, and that means more "useless" abstraction and therefore more mess.
Curiously, I'm going to at least partially credit Ruby for introducing the idea of convention over configuration.
I am not really a ruby guy, but I'm very thankful RoR came along and shook things up.
My favorite example is the single responsibility principle, which, while a useful guideline, is 100% qualitative. All classes and functions do more than one thing.
Is making a sandwich one thing? Is putting mustard on the bread one thing? Is opening the mustard jar one thing?
The exception might be if you had a function call bitFliper that turned 0s to 1s and vice versa. But that's probably as close as you could get in most programming languages.
Usually though, if you try to make the code clean and as small as possible while still allowing unit tests to be written, you normally hit a decent spot. YAGNI applies very heavily here too and it's often better to make the code less generic and refactor it later when required.
It's the knee jerk reflex of decoupling everything, to the point that you have 80% configuration/wiring/setup vs 20% of code that actually does something useful.
Each extension point in the framework is represented by a couple of these classes to handle the layer of indirection. Maybe Spring should run a study and see which of their extension points is actually used, at all, or by more than x % of users, and then cut down all the useless ones. I'm not too familiar with Spring these days, but I'd expect that the vast majority of indirections isn't actually useful for anybody.
The other problem is that our mechanisms to introduce and handle these abstractions are too verbose. Each extension point spawns multiple classes where it's really just one little method that needs to be called instead of another block of code. That makes software systems extremely hard to understand and use, and the overall bloat does actually slow things down - if not in production, then in deployment, startup, and build.
That last part seems key: I'd be shocked if you didn't find someone, somewhere for every one of those features – and, based on some of the enterprise apps I've seen, doing so because it allowed a quick hack rather than solving a problem more correctly and expensively. The question really should be “Is the value from having this work the non-trivial obscurity and maintenance cost?” to emphasize that features and extensibility aren't free.
Or making fun of medical jargon. (ha ha, you said subdermal hematoma not bruise)
Once you know what the individual words mean, you can use them in different places, and know right away what the class does. Do you need to use 80% of these? No, but they're there, like parts in a car, in case you need to tinker.
I think core java libraries are amazingly designed and a good part of why the language became popular. You won't find many FactoryFactories there, The land of c,c++ libraries that came before is incredibly fragmented, inconsistent and difficult to use by comparison, not to mention the documentation. Good lord the docs ;x.
What's surprising is that one third of the names it's showing me are actually real. I mean, "MetaMetaContextHierarchyConfig" actually exists?
Apparently.
https://github.com/spring-projects/spring-framework/blob/mas...
"Custom context hierarchy configuration annotation that is itself meta-annotated with MetaContextHierarchyConfig"
Sadly, it's true. What the hell, Spring Framework?
And of course, what about testing the custom overrides of that config?
Well just use the ConfigClassesAndProfileResolverWithCustomDefaultsMetaConfigWithOverridesTests!
Seriously.
- HttpServlet
- AbstractXmlWebMvcResultProcessingInterceptorAdapter
- MockJtaTransaction
While there is HttpServlet class, it is considered wrong, and 3rd option is considered correct :(
On Firefox DevEdition nothing past "Pick the one that's not made up!" appears. On latest IE it's every time "ComplexPortletApplicationContext.EditController" vs "ModelMapBasedHandlerMethodProcessor" vs "AbstractPlatformTransactionAttributeSource". 16 times the same question. Well, this could be just bad luck if questions are random. With randomness you never know.
The key thing to keep in mind with generative models based on real data is that just because results were based on random generation doesn't mean they can't match something real.
org.aspectj.weaver.patterns .HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor
Java is triumph of the "packers mindset".
http://the-programmers-stone.com/the-original-talks/day-1-th...
I really don't think people with that mindset could put together the sort of shit we do on the enterprise mindset side of things. The tools are carefully picked to be entirely the opposite to the contrarian mindset.
So we have a system that has about 500 HTTP endpoints, 600 service endpoints, 4MLoC, several TiB of data, several TiB of documents, handles 5000 concurrent users 24/7 ramping up to 2 million euro consumers (not concurrent) and 10 full 42U racks of kit in two facilities. Oh and strict security isolation through several layers.
Java+c# is the only answer.
But 50 times a day someone says, hey rewrite it all in Ruby and Monogo. That's a joke.
We're breaking it down into tiny subsystems at the moment i.e. moving to a microservices architecture. I'm describing the "monolith" that we're starting from.
In time it'll have 1/2 the code, 2-5x the throughput and significantly less cost.
I'd rather be using Erlang or Common Lisp myself.
BTW, how many languages do you speak well enough to hold an intelligent conversation?