Java Developers
nsainsbury.svbtle.com
nsainsbury.svbtle.com
However, I don't think the problem ie necessarily Java Developers - I think they were just early adopters of the larger problem:
Frameworks.
Too much software these days relies on frameworks in order to 'get things done'. The knock on effect is that developers don't have to think as much about how things work (technical debt is at an all time high), and often code following 'best practices' handed down from academia/conferences/books that promote large abstractions which are often un-necessary.
It's similar to how C code would end up having pointers-to-pointers-to-pointers-to-pointers...
A whole generation (generalising/stereotyping, I know) is now coding, who have never grown up and learnt with basic logic gates and low-level code. The framework is the obvious choice because 'why would you want to write it yourself, if it exists' ?
(Ironically, many Javascript developers seem to be intent on re-inventing everything that's gone before, and it's somehow seen as innovation - go figure)
Grumpy old man ? Sure, I am. I'm also gladdened to see a recent upsurge in assembly language and other low-level coding, as this is what the world actually needs - less super-business-entrepreneurial startups, and more people able to actually solve real problems and not just hipster entertainment.
Languages should allow you to focus on creating software that fixes a real world problem, as fast and cleanly as you can. That doesn't include bit flipping, or bit operators or anything like that unless required.
People should be working in super high-level languages like Haskell, OCaml, F#, Clojure, or languages that fit their domain perfectly. The goal is to fix problem the as concisely and quickly as possible.
In the vast majority of cases, it doesn't help your average coder one bit to know about whether or not a particular type of shift on their platform is arithmetic or logical, or how their cache is structured (again, running in a VM, lolzors).
There are cases where it matters--and surprise surprise, most of us don't work in those fields.
It might be nice and it might be cool, but it doesn't matter so much. Or to put it another way, how many people learned how tracing JITs work to do JS form validation? Would it matter if I did/didn't know this? Would it make a better form validator? Eh.
There seems to be some limit to the benefit that knowing such LL details provides. It's icing, but it is most definitely not the cake, and when your time/budget/skills are limited, you want cake, not icing.
It's easy to see why "don't call me, I'll call you" leads to unreadable code. A piece of code is readable if you can understand how it works, not just what it does, and a big part of "how it works" is figuring out the control flow. Inverted control flow makes code less readable, regardless of any other benefits it might have.
Viewed in that light, it's hard to see how moving to better languages like Haskell would solve the problem. Functional programmers pass functions around all the time, so a lot of functional "libraries" are actually frameworks that insist on calling your code in complicated ways, making it conform to very precise types required by the framework. There's certainly no shortage of abstraction in Haskell code. As a result, it seems that most Haskell programmers don't even try to understand the control flow of their programs, because it's almost impossible.
I wonder if we could have a principled approach to programming that discourages the "don't call me, I'll call you" pattern, and encourages code that you can simply read from top to bottom. Do this thing, then do that thing, then do the other thing. It would probably be unlike anything that exists in academia today.
Just call it the Hollywood Principle [1], and ya, it sucks. Databinding frameworks like React go a long way in fixing this (and my own work [2] also).
[1] http://en.wikipedia.org/wiki/Hollywood_principle
[2] http://research.microsoft.com/pubs/211297/managedtime.pdf
My favorite post about libraries and frameworks is this one: http://web.archive.org/web/20130810134741/http://an9.org/dev...
> Frameworks hurt sharing. I'd really like to give you this fork Jimmy, but you're gonna need a knife and plate to use it. The framework checks out all your girlfriends for you, the framework won't let anyone dirty get through, the framework will wait up until you get in, the framework will always find out were you've been, the framework keeps you healthy and clean. Frameworks embrace, extend and hold on to greedily.
For example Simple (http://simple.sourceforge.net) is a great XML serialization framework that does very well what it is supposed to do.
And there are others I haven't used, but you look at the API and think, this is what I want.
I was very impressed with jDBI (http://jdbi.org/) even if we could not use it because of Maven.
Have a look at jOOQ if you haven't seen it yet. There is a pre-compilation stage which generates DAO for you and they can then be used with static type guarantees.
I also don't like code generation. I'm not closed-minded to it, just don't like it if I can avoid it.
It doesn't integrate with the IDE and I am not too fond of it either.
But if you want ORM as a library in Java, I don't think there is any other option possible. Java has no meta-programming support, and annotations are going to be processed at run-time which is even worse than pre-compilation.
Too bad. Once you have code generation built in your development process (e.g. combining things with Flyway: http://blog.jooq.org/2014/06/25/flyway-and-jooq-for-unbeatab...), I'm sure you'll get a hang of how things work with jOOQ, and most importantly, you'll get your errors bright and red when you type (or when you build)
As for functional programming, I only mix bits and pieces here and there. One thing I find quite discouraging about JavaScript, is that (in the code I have been reading) you can define a function within another function, and pass that on to other parts of the program. I have found it really difficult to work out what is going on in the code. In a basic Python script, define the functions at the top then write something to call them at the bottom. Its easy to see where the code starts and ends - well a whole lot easier than looking for function definitions within other function definitions. It just seems unorganized to me. I know that it is supposed to be a benefit of functional programming that you can do so many things with functions, but I find it makes debugging difficult, especially at the start. Is Haskell better at keeping the code organized? I have never used it.
It's called "imperative/procedural programming", and has been around for as long as computers if not longer (in the form of instructions to humans). I think the problem in frameworks is not so much the inverted flow of control as it is the extraneous use thereof --- control flow that bounces around between many functions is difficult to follow in general. It all comes down to the fact that abstractions have a cost and benefit; the important point is when to make the decision to use one in which the benefits outweigh the costs..
The abstractions used in Haskell code almost always use existing and already well understood abstractions such as Monads, Monoids, Functors, and Applicatives. I most certainly have to understand my control flow in Haskell programs and it is not impossible.
> There's certainly no shortage of abstraction in Haskell code.
I've typically found said abstractions to be sound and needed (or at least justified) however.
Low level systems programming is good for low level systems code - code where you have to interact with hardware directly or quasi-directly. If you're doing anything higher-level, like, as I saw here recently, a web framework in assembler, it is certainly a good intellectual exercise. But it stops there. You're going to again and again find that you want a lot of the functionality that a modern, higher-level web framework provides without having to implement it yourself.
Good programmers exist at every level of abstraction. The question isn't whether or not you're using frameworks and a high-level language but whether you're maximizing your language and your toolset and creating the most elegant, bug-free code you can with your time.
I do agree with the author's sentiments about OO, but that's just because I started to use Scala and I've started to really become allergic to state and mutability, recognizing that your code is so much easier to understand and write when you put all your state in one place - like the RDBMS or the filesystem - and your code doesn't need to worry about its own state.
OO works fine for plenty of people as long as you can design your object graph in a way that's not too convoluted, littered with useless or empty classes, and doesn't have too much concurrency.
Having imported those libraries, in the end what I write is going to look a lot like what a framework asks for if it's even remotely well-defined.
Exactly. If you built your own system, choosing a good library for each major recurring task, then you inherently have both an understanding of how the overall system fits together and a degree of isolation between the libraries. If your requirements evolve beyond the scope of a library you’re using, or if a library loses popularity and is no longer maintained, you can probably swap in a replacement to serve an equivalent (or updated/expanded) role relatively easily.
Of course, the price you pay is that you do have to write some glue code to connect up the libraries where perhaps a framework would have provided that for you. This has potentially interesting implications for both the way good library APIs are designed and the scales of libraries that are or aren’t worth the overhead.
This also has huge implications for language design as a whole, and personally I think this is one of the reasons why Java is infamous for its verbosity and boilerplate. I also think it’s one of the reasons why common idioms from functional programming have increasingly been pushing into mainstream languages that aren’t necessarily functional programming specialists: functional idioms offer new forms of glue, and in particular, they are often well suited to writing “slightly customisable” algorithms and adapting more substantial pieces of code so they can be used together.
People hate on OO either because they're being edgy or because they are frustrated with bad implementations of its ideas.
OO is the correct way of thinking about things in the real world, because that is how disjoint systems communicate. Internal to an actor, use all the functional programming you want (and you should, because it's really good for that purpose!).
... I agree Java is not a particularly good example of OOP. It amazes me that so many people complain about Java "forcing OOP on everything". If I read framework source code, I see very little OOP in there. It's mostly procedural-with-classes. Maybe we've redefined OOP to mean "whatever Java is doing". Which is nightmarish, the worst of all worlds.
We kind of have, though it started pre-Java. "Procedural-with-classes" pretty much became "OO" from C++, and Java got it from there.
OO is a good way of approaching many real-world problem domains, but most OO programming languages implement OO in a way which has a significant impedance mismatch with the way in which OO is a good way of approaching real world problems.
I'm increasingly unconvinced that OOP (in terms of language features, even in the Ruby/Smalltalk sense, much less the Java/C++ sense) is actually an important tool in the mapping of OO thinking about systems to actual concrete programming, and that other approaches, like REST-based (not particularly HTTP-based, but the architectural style) SOA where the individual components are functional might be better -- traditional OOP, IMO, promotes tighter coupling than you real want in an OO system, and then requires elaborate patterns to mitigate that into slightly looser coupling than the language structures naturally promote.
I suspect that we've started hitting the issue of "What, actually, is OOP?"
OOP like many Java (and C++) programmers do it is certainly not what Alan Kay was thinking about (in his own words!). But that's merely an appeal to authority. Maybe Alan Kay was mistaken and the Java folks are right. So the other part of my problem is that OOP is not a well-defined concept at all. I cannot begin to agree OOP is the best way of thinking about the real world until we can determine what OOP is; a definition both a Smalltalk dev and a Java dev can agree on.
That claim sums up much of what I dislike about frameworks.
In the marketing brochure, it’s your perfect dream home with everything you could ever need in a single, neatly integrated package. You get someone to do a survey to check for major structural flaws, you spend a couple of hours checking that all the essential utilities are connected up, and before you know it, you’ve made the biggest purchase of your project’s life. A week later, you’re sitting out on the deck, enjoying a cocktail with your glamorous friends on a warm summer evening as your baby sleeps soundly in the room upstairs, just like the models in the photo.
A fortnight after they hand over the keys and you move in, you often realise that what you really bought was a place that had 80% of what you needed. Unfortunately, to reach 100% you would have to knock down a few walls and rewire the whole building, costing at least half as much again as you already paid, so instead you start running extension cables from sockets in one room to appliances in the next, resort to flaky WiFi networking, and install a sofabed in the lounge because you couldn’t quite fit a double in what was supposed to be the spare room.
Over the next few months, you realise that it’s also really inefficient to run the place, because the guys who built it went for all the attention-grabbing features that would push up the price they could get, but what you really needed was energy-efficient appliances and a good HVAC system based on renewables. Also, the soundproofing between downstairs and upstairs sucks, and that baby who was supposed to be asleep during your summer party wakes up every time someone opens a new bottle.
Three years later, when you’re surprised to find you also had twins, there is nowhere to put the extra bedroom you need. A little after that, you have to move to a completely new place, because there’s nowhere to install a lift for your elderly parents, and even if there were you don’t have the three-phase power supply to run it.
Except you can’t, because in the few years since you moved in the area has become run down, the value of your place has sunk like a rock, and there is so little interest in buying it for anything but the land it’s on that you’re in negative equity and can’t afford to move.
This is something that the education system could fix. I believe that we should be teaching kids, starting in elementary school, things like binary and boolean logic, simple circuits with gates, etc. and then move up to memory, instructions, basic CPUs. Everyone should be exposed to some Asm programming. Higher-level langauges, OOP, etc. can be left to those who choose to go into computing as a career, but I think that due to the massive reliance that society has on computers and the influence they have on our lives, everyone should at least have a fundamental understanding of how these machines work.
This should also fix the problem with developers creating monstrosities of abstractions, since they'll have a better understanding of when it's necessary --- this is similar to the difference I've observed between C and Java code, where the former tends to be written far more straightforwardly and with fewer extraneous abstractions than the latter.
> more people able to actually solve real problems
Agreed 100%. It seems far too much time (human and machine) has been spent on creating artificial problems via some sort of abstraction and then trying to solve them (often creating more abstraction in the process), instead of focusing on the fact that computers were invented to solve real problems.
But as things like http://en.wikipedia.org/wiki/Java_4K_Game_Programming_Contes... and the various Java demoscene releases show, the langauge itself is likely not a major source of the bloat, but the culture - it's possible to write simple, efficient Java programs too.
I think this is backwards -- the high level understanding needs to be more universal, and the low-level left for those who seek to make a career out of it (though I think the high-level part that needs to be universal is even higher level than actual programming and is more basic system analysis, though combining it with some programming, including basic DB implementation, would be a good way to make it concrete.)
- Maybe I come from a different kind of academia, but in my CS education they didn't force "large unnecessary abstractions". Mind you, they didn't teach Java, C++ or any particular language. Learning programming languages was something you did in special optional classes or on your own.
- It is fascinating and instructive to learn low-level languages such as assembly, which I enjoyed learning in my spare time, but I don't think that's "what the actually world needs". The world needs reliable, non-bugged software that does what we want and is easy to understand, maintain and extend. Certainly not something that would be helped by coding in assembly...
To clarify: I believe it's immensely instructive to learn about low-level stuff. It should probably be mandatory in a good CS education. But it's not a good idea, in general, to actually build programs by manipulating low-level language. Sometimes it can't be helped, of course, by I assume we're mainly discussing application software here.
I use Java, but I tend to do low level stuff, stick to basic I/O, Guava, etc.
I think the article is right in one important aspect: the way Sun built Java was to pretend as if everything should be a competitive market. So pluggable drivers for everything. Rather than build in say, one XML parser, instead let's build in a whole system to allow you to plug in any XML parser. As a result, it takes 4 lines of code to do what should work in 1 line. On other platforms, Python, Ruby, Go, et al, there is no such assumption that one needs an abstract interface to allow multiple implementation providers. You have an opinionated built-in implementation, or you use third party APIs.
This is why you have stuff like DocumentBuilderFactory/DocumentBuilder/etc.
When really, you want to write: Document doc = XML.parse(...)
Enterprise developers copied the basic design of having provider lookup/locators. This is why we have AbstractFactoryLocatorServiceLocator stuff.
Where I part company with the author is the total trashing of OO and the language. There are certainly lots of warts and things to complain about, but I haven't used a single language where I didn't have a boatload of things to bitch about.
I think you fall in love and there's a honey moon period with most languages, and then the beer goggles wear off after daily use and you see all the flaws.
It reminds me of the opposite take that we've seen in browsers as of late. Eg. innovate with webkit specific extensions then standardize what works. Java meanwhile standardized conceptually useful concepts (Swing, Java Server Faces, etc), but the markets for pluggable Swing or JSF components never took off.
I think it's that under Sun's direction the intent was to create markets, e.g. a market for GUI components or web components, a market for server components (EJBs). At least in the case of server components, Sun made a lot of money by licensing J2EE servers. I suppose that was their motivation all along for forcing DocumentBuilderFactory's on developers.
There is also a lot of Java stuff dealing with dependency management. Not all of the principles are unsound, but they do have more long-term effects and make the code clutterly in the interim.
Once real systems (like UI frameworks) are written with FP, we can compare apples to apples. Until then...wtf? OO actually works well for scaling complexity, much better than toy immutable functions do.
> Even today you’ll still find a strong bias towards OO courses being taught at the university level using Java, and the bias was certainly stronger 5 - 10 years ago.
Because that's what people use to write real programs.
> The engineers at Google working on Android are too busy architecting grand frameworks for solutions and not busy enough solving actual problems.
Because we all know, Google is known for hiring flakes who can't code or design real systems.
Worse is better means getting things done even if your tools kind of suck or your understanding of the problem isn't yet great. It leads to architecting and less than ideal solutions, but at least you ship!
Unsurpisingly, if a given JS UI framework is OO, it is not OO in the traditional sense because JavaScript itself is not OO in the traditional sense. If you make a framework, you use the language of whatever runtime you are targeting.
Functional programming is often used to write server code that must easily parallelize and scale across cores, CPUs and clusters. Mostly because the FP paradigm is more obviously advantageous in that setting, but also because those services have less baggage of trends than UI heavy programs do.
So you are arguing that there is some perceived evidence for OO in UI programming, but I think that could more easily be attributed to historical trends. Note that I'm not necessarily disagreeing with your conclusion, just that your reasoning is flawed.
> Functional programming is often used to write server code that must easily parallelize and scale across cores, CPUs and clusters. Mostly because the FP paradigm is more obviously advantageous in that setting, but also because those services have less baggage of trends than UI heavy programs do.
As someone who works in a distributed systems team, ha! Where are these functional programmers writing high performance parallel code? Microsoft? Google? Facebook? Maybe map reduce and some pipeline descriptions can count as functional but that's about it (even the UDFs are imperative).
The best HPC programmer I know (and probably one of the best in the world) uses C++ and CUDA, neither very functional.
This is because people have been educated in thinking in objects for thirty years now. This is again a result of history, not because of the qualities of OO over FP.
Besides, there's no reason why you couldn't do that using functional programming. FP is not (necessarily) object oriented, but that doesn't mean you cannot reason about 'objects' in a different sense.
> As someone who works in a distributed systems team, ha! Where are these functional programmers writing high performance parallel code? Microsoft? Google? Facebook? Maybe map reduce and some pipeline descriptions can count as functional but that's about it (even the UDFs are imperative).
I'm not talking "distributed" systems that do HPC work; functional programming in general cannot achieve that level of low-level performance (as long as you don't count Rust's ambitions). I'm talking 'scalable' systems that do a lot of messaging processing (like web services and queueing systems). Twitter, Walmart, LinkedIn (Scala), Facebook, Whatsapp, dozens of companies in the telecom industry (Erlang) and Jane Street (Haskell, OCaml, F#) are examples.
Although lambdas are a big improvement to Java, they are not helping enough to make the language more functional. Java is built upon mutable state to its very core, and will never share FP's redeeming qualities.
Lazy by default is a feature of Haskell, and is not a feature of (or necessary for) functional programming. Scala, OCaml, F# and Lisps are not lazy by default.
Not everyone agrees, evidently! In his influential paper, Hughes argues that higher-order functions and laziness are key to functional programming.
If you allow for value identities (via GUIDs or if your language is really impure) in your functional code, you wind up with a style of programming that is very similar to programming with objects (messaging those values to do things with their state). Heck, you wouldn't even need overt mutable state to arrive at a very OO style (see clojure).
Java's lambdas only serve to reduce boilerplate; everything done with Java's lambdas was long possible using anonymous classes. Theoretically, they do nothing to present the advantages discussed by Hughes [1].
Hughes also didn't talk about laziness-by-default: his argument still holds if laziness is available somehow (which it is in many FP languages).
[1]: Of course, lambdas might improve the style and expressivity of idiomatic Java enough to make up some ground.
Now, nothing stops that immutable object containing a mutable object of course, but that's up to you ... Guava has immutable collections if you want them.
Better language support for immutability would not go amiss though.
They just aren't architected the same way. Instead of a monolithic WAR you end up with a series of micro services. FP is actually more suited than OO for micro services since it naturally forces developers down the "do one thing well" approach.
So I would stop with the "OO is what real people use" nonsense if I were you. Because languages like Scala and Clojure are rapidly taking over from Java in the enterprise space and you may find yourself on the wrong side of history.
Let's see how much of the momentum these languages keep after Java 8. Default methods, the new stream API and lamdas provide much what most developers need without introducing baroque features and orthogonal infrastructure.
OOP is too verbose by it's essence compared to closures. I tend to see curried functions as anonymous objects (old lisp koans joke on their duality).
Then CLOS is too verbose?
To be honest, CL shows its age (mapc, mapl, do, dotimes, loop ...), more functional approaches like sml are very tempting, for the small size of their core in which you define all other patterns. I'd love to see a blend of lisp and ml (racket maybe?).
As for verbosity, I'll take ":accessor foo" over methods "getFoo" and "setFoo" with inane, useless autogenerated comments any day of the week.
I couldn't count the number of times I've been writing C or C++ and wished I could express an idea more complex than "Initialize some variables (which may or may not be of the same type (but not of arbitrary different types)); run while this is true; do this thing after every iteration" without just slapping everything into and in the immediate vicinity of a while-true block. I don't have that problem with LOOP.
Could you comment on Smalltalk's blocks?
edit : I should have said closures + curryfication so you can partially augment the creation of a final callable entity that binds many parameters (similar to an object constructor arguments)
Get the facts straight please.
As much as I don't like everything about PHP, PHP means PHP5 and it has been like that for a few years.
The iterative development with a REPL approach deployed with micro services lends itself well to Agile development where big bang architecture simply doesn't work.
While the language is awesome in general, I would not recommend it at work.
Also, while I think Scala is simple at its core concepts and syntax, it gets complex because it has too many features and tries to support all features present in other programming languages. Why do you want structural typing there?.
Also, I hated sbt.
Which things do you have in mind?
> Why do you want structural typing there?
Isn't that a simplification? Instead of saying "here are types which you can use as e. g. parameter types, and here are types which you can't use (like in Java)", it says "all types work the same way".
I don't see the need of it if you already have a class-based system.
Go uses structural typing. But it is the only thing they have. Rust has traits, and it is the only thing they have.
I can't think now of more stuff but I remember you could even write xml in the language.
Like in Java?
new Object() { void foo() {}}.foo(); // Works
Ooops.The point about XML is so stale already that I won't even bother commenting on it.
I care about simple, consistent rules. "X is a type, you can use it wherever you want" is one.
"X is a type, but there is also Y, which you can't really express in position A and B unlike X, but can only use it if you carefully avoid doing things #1 to #4" isn't one.
I don't think it helps for consistency when you have to ask yourself why some functionality is defined in terms of a trait if it could be defined in terms of the structural type and just providing the methods would be sufficient.
Almost every other way of "extending" a type would have worked better in practice eg. Xtend’s Extension Methods.
It's not like Scala developers didn't know extension methods before designing implicits.
Instead, they tried to come up with a more useful, principled way, which also covers a lot of the stuff which is hardcoded and implemented ad-hoc in other languages (like implicit conversions in Java).
In the end, I think they made the right call:
- Implicit parameters are the basis for abstractions which unify the "strategy pattern" of OO languages with FP's typeclasses,
- implicit classes provide extension methods, but are better in pretty much every regard (higher reusability, less error prone) and
- implicit conversions cover the ad-hoc conversions everyone takes for granted, without having to hard-code these hacks into the language (e. g. don't like Java's/C#'s/... implicit convert-everything-to-String conversion? Don't import it in Scala).
Some parts of our codebase really work better with said academic style, so we keep them. In others, the type system was used in ways that did not make any sense, and were rewritten.
Scala's strength is precisely that it can look like anything you want. If you are not interested in said freedom, then sure, avoid Scala at work. But for us, using the style that works better in each part of the system without actually having to change languages is extremely powerful.
The core language is good enough already, and better than most. They way it defines functional purity is the way it will be taught in universities in the future. It also embraces concurrency, and this will only become more important as computers get more processors.
What it lacks is libraries, therefore you are right about point a. The lack of a library like Ogre3D is an issue. The lack of an equivalent to jdbc for D is an issue. That's the reason for me to mention D here, the more exposure it gets, the better.
But about points b and c, no way. You deliberatedly ignore the third compiler GDC, which integrates the open source D front end with GCC and produces faster binaries than DMD.
My point was that serious companies are doing serious work with FP languages.
Clojure is a Lisp, its niche. There will always be some people around who want to program in a Lisp, and many of them are just choosing Clojure today. Nothing new really.
The language could have a Python skin on it and still maintain much of what makes it pleasant to work in. I'd probably even prefer it.
Furthermore, the reaction to Clojure by the lisp community in general seems to be quite negative, like it's some inferior lisp that doesn't even have things like reader macros, and it makes no sense why it's getting traction when CL never did.
Which is all to say, I think the answer to what makes Clojure compelling is actually quite nuanced, and you're painting over it with a broad brush. Maybe with the wrong color.
Interestingly, Scala's combination of OO and FP has given it (besides a lot of mockery and criticism) the title of a "postfunctional language".
Btw: I don't mean to pick on you, but you are talking a lot in absolutes on things I happen to disagree with in this thread.
Many things considered the domain of "functional" languages these days, like typeclasses and higher-kinded types are supported in Scala.
Saying that Scala is 'not really functional' is more or less denying OCaml, F#, SML (in fact, pretty much every language except Haskell, Idris, ...) the status of a functional language.
Would you consider C# to be a functional language? It has lazy streams, generators, and good support for list comprehensions? Or is it just an OO language with functional features?
Just have a look at F#'s higher-order functions for collections to see what I mean.
I consider a language "functional" if it allows me to write good functional code. Scala supports that by enabling me to choose good object-oriented code instead of bad functional code where it makes sense. (There a certainly other approaches to enable good functional code.)
I wouldn't consider C# functional, because it lacks purity, higher-kinded types, useful type inference, first-class functions, good support for immutability, dependent types and typeclasses.
(Note that I'm not saying that functional language need to support all of this. But a language which supports none of those items: I think we can make a clear call in that case.)
> I wouldn't consider C# functional, because it lacks purity, higher-kinded types, useful type inference, first-class functions, good support for immutability, dependent types and typeclasses.
C# has first class functions and has had them for a long time. C# also has real value types via structs, allowing more efficiency with FP styles, better than what Scala can provide on the JVM. Generics in C# are also reified, vs. erasure in Scala, so your run-time and static type system is the same.
Scala has better local type inference than C# (though non-determinstic...), but lacks global type inference like ML, Haskell. Scala also doesn't support general dependent types, settling for a much weaker (must still useful) path dependency. Path dependency is a very OO friendly feature, and in fact really amplifies OOP in general; whereas for FP, path dependency's benefits is limited to records.
So a language is automatically not functional, because other supported paradigms in that language don't suck?
So if OO in OCaml, F# wouldn't suck, they wouldn't be functional either?
> C# has first class functions and has had them for a long time.
I'd say C#'s functions are slightly better than Java's. The distinction between Action and Func is a terrible hack, and both of them are just a thin syntactic layer over delegates. Is that really first-class? They don't even provide function composition in the standard library.
> Generics in C# are also reified, vs. erasure in Scala, so your run-time and static type system is the same.
Bad luck for F#, I guess. Just ask them how much fun it is having to support two different kinds of Generics.
> Scala has [...]
As mentioned, that list wasn't a claim that Scala supports all of them (I think not even Haskell gets all the points).
You can't have one because:
> Generics in C# are also reified, vs. erasure in Scala
The fact that this is true of C# vs. Java -- or perhaps more critically .NET vs. the JVM -- is why you can't have a Scala-like language on .NET (its specifically why you don't have Scala itself on .NET, which was a thing, but foundered on this problem.) Reified generics on a platform are great so long as all your (statically-typed) languages have type system just like the one assumed for the platform, but they ruin the interop story for any other type system, and a Scala-like language without a good interop story with the rest of the ecosystem would be pointless.
Post functional is as vacuous as post modern, ultimately these labels are not meaningful.
http://www.codecommit.com/blog/scala/is-scala-not-functional...
Sure, but the problem is that OO is frequently applied where you don't need scalability, and then OO becomes the complexity that needs to be scaled.
A low-hanging example of this is the singleton pattern, and the Wikipedia section titled "Example of use with the Abstract Factory pattern" saves me from having to bother making the point any further: http://en.wikipedia.org/wiki/Singleton_pattern#Example_of_us...
It is my fervent hope and wish that all programmers someday accept that there is no universal methodology, that FP and imperative and OO all have their place and their faults, and that it is OK to sometimes not use one of them somewhere.
And of course, I mix OOP and FP styles all the time, I'm not a purist by any means (a guy who does F# once commented on how FP my C# code looked).
This is a very important point (hopefully more "when" than "if"). I'm really tired of seeing naive programmers throw the handful of design patterns they know at every problem, not because the abstraction is a fit, but because their toolbox simply doesn't have that many tools.
This is one of the biggest problems with Java — and other “pure OO”, “everything is an object” languages of the same style — particularly from a teaching perspective: when all you have is a class, every problem looks like an object.
If we present a language like Java as being the default, standard, safe option, how are new developers ever going to gain enough knowledge and experience to realise that their elaborate design with seven different classes in Java could have been replaced by a single 10-line function in Python, or a few short lines of Prolog, or a single query in SQL?
You nailed it. And, so did the author, with this:
>so often I find I’m reading code that looks more like a plan for something that solves a problem, rather than something that actually solves a problem.
Java--or perhaps the OO culture that came up with it, or perhaps the enterprise culture in general, or perhaps all three--does encourage a certain overengineering mindset. I am speaking as a recovered victim.
This permeates the entire culture. Remember when the Design Patterns books were first popular? Every Java dev was looking for a way to wedge in as many patterns as possible. There was a real sense that it was required to do development right. I think this (along with reading Java's APIs) is where Java devs began to fancy ourselves Architects Of Everything. You couldn't just solve a problem, no matter how simple. Instead, you had to develop something that could be infinitely extended or modified in the future. And, you'd better be sure that nary a public interface required updating if those future changes were necessary. Nevermind that you layered on extra classes, instantiated everything with a factory, and increased the initial complexity of using the code by orders of magnitude.
So, you were no longer solving a problem. Instead, you were architecting a flexible solution that could support solving the problem, along with every future variation of the problem you could conceive at the time. Then, you implemented your solution for the actual problem within this new, broader mini-framework you just created.
So, when reading this code, it's not uncommon to go through layer after layer trying to figure out where the actual work was being done.
But, the problem is that those future changes seldom came. So we were guaranteeing that our initial solution was overly complex and creating all of this baggage, while relatively infrequently redeeming that heavy cost in terms of avoidance of actual future pain that we imagined.
Many people said the same of GOTO statements a generation ago.
As for the OP, I disagree. There are tons of good Java projects out there and there are tons of crappy Java projects out there ... just like pretty much every language ever invented.
FP wasn't mentioned in the article. Criticism of OO doesn't necessarily mean embracing FP, as far as I know.
So yes, the other options are static procedural and component oriented like CES. Interfaces without inheritance are also gaining popularity, I think this is what Go and Haskell do.
Like Java, Go and Javascript have "objects", but you all know how different they are. So don't make them equal by calling both of them "object-oriented". If structs in C were called "objects", would C be object-oriented as well?
OOP is simply programming with objects. If you have values that contain encapsulated state, and you are instructing them to do things with that state, you have objects and are doing OOP. You can do that in any Turing complete language, but some languages support it better than others.
[1] http://www.drdobbs.com/embedded-systems/object-oriented-prog...
The primary reason Java is the language used for Android is the very same reason that Android is used so much in enterprises: it is easy to learn, and easy to get developers for. But the language's primary redeeming quality has become an economic one, and not that the language itself is so rewarding.
Perhaps the only language more reviled than Java in Google is C++.
The most problematic language at Google was (by far) Python. Mostly because tools that would start out as small Python scripts would evolve to become large Python codebases that ended up being unmaintainable.
There were several examples of unmanageable Python codebases at Google that got rewritten in C++ or Java. I'm struggling to think of examples of code going in the opposite direction.
This does not mean Python is a bad language. It just makes a different set of tradeoffs in its design. C++ and Java were designed with features that are known to increase verbosity but make it easier for large teams to work together. Python wasn't.
Additionally there static analysis was limited to lint and refactoring tools didn't exist, or at least nobody seemed to use them (I never used PyCharm but I heard it can do some cool stuff).
Also for whatever reason these codebases often weren't very well structured and there was a common tendency to define configuration files that were themselves Python, resulting in the codebase spilling out into things that were theoretically just static data, complicating unit testing.
There's also lamdu[0] being made for Haskell which is pretty interesting.
They have some nice scallable backend systems, but a lot of their output is ho-hum, especially when it comes to their Java inspired teams (GTW etc).
As all modern languages, even functional ones, have OOP support.
Java devs are known to over-engineer everything. There are many nicer OOP languages out there, where the devs don't tend to do this.
Because they aren't used in enterprise applications. Just give them time.
When I got software engineering at university, we learned Java. So all those fancy (mostly over engineered) ideas where taught us with it. When we did some web or IA stuff, we did it in PHP, JavaScript and Python and the lecturer went for small concise solutions.
- OO like in Smalltalk
- OO like in SELF
- OO like in BETA
- OO like in CLOS
- OO like in COM
- OO like in Haskell
- OO like in C++
- OO like in Eiffel
- OO like in Ada
- OO like in Sather
A few more models might exist.
In regards to Scala, I would say OCaml has similar capabilities.
Yes, it has a bit of everything anyone thought about in FP in it.
However you can make use of traits like feature by mixing in modules and objects, while taking advantage of first class modules in OCaml.
> JavaScript has many influences beyond Self
Sure, but I am unaware of any that make it such a great language.
JavaScript has been very successful, and got a whole generation of programmers playing around with prototypes without knowing it.
JavaScript's success has less to do with how good the language is, rather sharing the same fate as successful systems programming languages, by being the only gate to the kingdom.
OO in OCaml feels as if the designers thought "we think OO sucks, so let's implement terrible support for OO to get our point across".
Please explain. Are you referring to type classes?
Wikipedia at least seems to agree with me.
For example, OOP with multi-methods, does not imply such encapsulation.
There is a lot of disagreement about which of those is more important. For me polymorphism is the most important, encapsulation is useful sometimes, and inheritance might be a negative attribute. For you encapsulation.
FP is smaller and stricter, it's almost formally defined (you have denotational semantics for FP VM for what it's worth).
So you just get ADTs as introduced by Mesa/Modula-2.
So, polymorphism and object-orientation are orthogonal concerns. OOP is about encapsulation, inheritance, and modules that couple mutable state (attributes) and behavior (methods).
Which is still polymorphism. I purposely did not enumerate all CS forms of polymorphism, but can get more detailed if you will.
ArrayIndexOutOfBoundsException
...
extends IndexOutOfBoundsException
extends RuntimeException
extends Exception
extends Throwable
Not exactly an abomination, but I would not call it thing of beautyI think this is an example of an hierarchy without a purpose.
Pointless OO, what's not to love here..
Up to you man. Peace.
One way of viewing nouns in English is as a hierarchy. At the top of the hierarchy you have "thing", and as you descend the pyramid you get more and more specific. "What is that thing?" -> "What is that animal?" -> "What is that mammal?" -> "What is that ungulate?", etc.
There are times when it is appropriate to use "animal", and times when it is appropriate to use "ungulate". It depends on context. OO allows you to have the same levels of abstraction, and it can be a powerful tool.
NOW, having said that, there are two problems with this:
1) Not everything is a noun. Sometimes you want to deal with verbs.
2) Realistically, these hierarchies (in Java) tend to become overly-complicated over time. That's what OP is talking about.
There are cases, though, like the aforementioned Throwable, where having a deeply (more than 3 layers deep) nested hierarchy is wholly appropriate.
When dealing with OOP, I stick with patterns and keep everything else as flat as possible.
Yes, yes it is. All natural languages are. They are living, breathing, evolving, organic concepts. They don't have the benefit of being designed and prescribed by an individual or group of individuals like programming languages do.
Seems like we are working on very different kinds of systems. Right now I'm working on Hadoop-based data pipeline. While Hadoop itself is mostly written in Java, many recent tools like Spark or Kafka are created in Scala instead. Yes, they still use some kind of OOP where necessary, but it works as a helper tool, not as principal paradigm. At the same time, ideas from FP are used extensively.
Do you consider Hadoop-based systems not "real"?
But ok, let's take something different. Python for example. Python with its main web framework - Django - is really shiny. I would say, it is one of the best web frameworks ever. What about OOP in Django? Controllers are just functions on module level, models are just "poor" records for storing data (no behaviour), ORM is singleton-based. So I would say it's procedural, not object-oriented, at least, not in Java sense. And still sites like Instagram or Washington Post use Django.
Do you consider Instagram not a "real" system?
Ok, maybe it's just web. Java was never good for web, actually. Let's take one another example area, say, scientific computations. Science is something that is really complex, right? Even simple statistical algorithm involves tricky numerical computations, optimization methods, probability models, etc. Matlab is good at these. R is good at these. Python (SciPy) and Julia are good at these. C and Fortran are not very convenient, but fast and thus used extensively. What about Java? Is Parallel Colt best possible choice? Not very impressive. Ok, maybe Matlab, Python, C, etc. are really good only for little experiments and are not really scalable? Hmm, have you ever wondering what software Mars Curiosity is using? It's 2.5 million lines of C code with tests in Python [1]. And nothing about Java or OOP.
So, do you consider Curiosity software not a "real" system?
I'm pretty sure Java is good for some sort of applications. I've heard a lot of good things about using OOP for UIs. But Java is not the only language used for complex systems, and UIs are not the only "real" kind of systems.
[1]: http://programmers.stackexchange.com/questions/159637/what-i...
For small sites, maybe. Once the codebase gets large, it becomes much harder to maintain than a Java webapp of similar complexity written in a sane framework.
So far list of websites written in what I used to think of "sane Java framework" (Spring Web) is not very impressive [1] compared to Instagram, Washington Post or Reddit.
Strongly disagree. The internals of Django are full of inheritance and mixins (a form of multiple inheritance), and so are the class-based views and the forms.
The CBV class hierarchy is complex enough that someone had to make this site to help everyone keep them straight: http://ccbv.co.uk/
If you only write FBVs and implement your own views and forms from scratch you can keep your code fairly procedural, but I would say that Django heavily [ab]uses the OOP features of Python.
It's funny how your comment compromises OOP - even in Django class-based views make things complicated :)
Anyway, I didn't mean that Django doesn't use OOP at all or forbids you to do so, but rather that it provides another approach (mostly procedural) and pretty successfully. Most people outside the OOP dome actually know that this paradigm is good for particular tasks. But what people under the dome don't know is that there are many other approaches that work not worse, and often even better than OOP.
Also note, that performance was not the only point of my comment. In fact, my point was in simplicity of designing complex scientific systems. In Python you have excellent stack: NumPy + SciPy + Scikit-* + Pandas + Numba + Cython + Theano + Pylearn2 +... The list is endless, and all these tools may easily be used together. In R you have CRAN with everything you may ever be wanting. In Matblab you have a number of both - open-source and proprietary libraries. Julia community is also growing quickly. (Note, none of these libraries uses OOP as its primary paradigm.) And what about Java? Java has a little disjoint set of libraries that neither solve large set of problems, nor interoperate with each other well.
No, no, no. Immutable data structures are not actually inefficient, they are just different. They were designed for different tasks and work better in that tasks. Imagine, for example, that you need to traverse list of customers in a large multithreaded application. While traversing, you don't want this list to be updated. So if the list is implemented with a mutable array, you have either to lock it all the time, or create a copy, both of which are pretty inefficient. With immutable list, on other hand, you can freely traverse it because you are guaranteed it will not change during processing.
Multithreading is one of the main sailing points for immutable data structures, but not the only one. IIRC, Java String are immutable to allow creating substrings as views on the same char array, which, on average, increases performance, not decreases it. Another cool thing is that with immutable data structures you can add new cool features like auto generation of `hashCode()` or memoization.
Surely, some algorithms require mutable data structures by design. Change one pixel in 1M image stored as immutable array is definitely bad idea. That's why most functional language tend to, but not limit you to using immutable data structures only.
If you point to substring() as a view of a string, nope, that behaviour has changed for quite some time already. Surprisingly for me as well, back then.
Remarkably many Gang of Four design patterns are unneeded once you can pass functions around. The C# world is now learning this: when C# 1 and 2 were popular, the ecosystem went right after Java in the kinds of boilerplate that the author describes. Now, many years of Func and Action goodness later, there's a large part of the community that codes way more to the point, and this part is growing. People who release C# libraries in 2014 with factories adapters and multiple layer inheritance hierarchies are laughed at.
Since Java 8, Java too has an accessible way to pass functions around. Not really functions, because Java, but in practice it works the same way. This means that there's nothing technologically that's holding the Java community from making these improvements, too.
I hope it happens.
However hopefully now ART is successfully launching they'll go back to upgrading the base foundation and move it beyond Java 6.
Contrast that with Microsoft's WCF: http://www.codeproject.com/Articles/105273/Create-RESTful-WC...
Quartz: http://www.quartz-scheduler.net (hint: it's gigantic)
Contrast with
private void ScheduleRepeated(Action task, TimeSpan interval)
{
Task.Run(async () =>
{
while (true)
{
await Task.Delay(timeSpan);
task();
}
});
}Instead they should learn about design principles, and instead of thinking "which pattern should I apply here", they should be thinking, "what is the best way to create this code so that the basic design principles are upheld". You can start with SOLID principles and go from there.
The same happens with language features; when generics were introduced, everyone wanted a generic class for some reason when it's almost never needed outside of the Collections framework (bit of a sweeping statement but I hope you see what I mean).
In fairness, I don't think it's really Java's fault, only that it's been around long enough for there to be many more examples of this kind of thing. I've been working in Java for 15 years and C# as my day job for the last 3 - you can easily pick out examples in C# where the langauge has been abused: dreadful LINQ expressions where a simple for-loop would suffice (and be quicker), or multiple Events added to a class, ALL of which need to be hooked up by calling classes for it to be usable, so an Observer really would, actually, have been a better solution.
I've played around with functional programming and there are a lot of claims around how it forces programmers to write better code. I'm not sure how it's going to stop programmers abusing language features or the language characteristics, though. I may well be wrong about that and am happy to be put right by a knowledgable FP dude.
I switched to Scala a couple of years back and have never been happier. Only part of the improvement is due to the language the other part is not having to deal with Spring, builder patterns, and madness like AbstractSingletonProxyFactoryBean [1]. My impression has been that the typical Scala developer has had lots of Java exposure and has learned from their experiences.
[1] http://docs.spring.io/spring/docs/2.5.x/api/org/springframew...
1. OO is bad. Every paradigm is bad if you misuse it. If you build deep abstractions then you will hang yourself regardless. Some very elegant and simple designs can emerge from OO code, but only if you think about the problems first. The majority of pain consists of forgetting to do that step. There is no magic bullet - FP has its own pitfalls as well as does simple procedural programming.
2. Everything looks like it's written by an architect. Well that's a broad generalisation and I'm sure some people titled architect would be sick at the association (considering they usually reduce complexity) but the problem here is that people aren't using the frameworks properly. Not joking but the last two or three Java web applications I've put together have virtually no code in them. It's just the domain model, the views and query encapsulations. Nothing else. The abstract factory factory factory factory crap isn't your problem. If you make it your problem, then you're just doing it wrong or not using the tools provided efficiently.
3. Android. Android is abysmal (I've written a couple of things for it so far), but that's not because of Java but the fact that the Android API and versioning mess is a pile of unstable crap. It'd be nice if there were't so many exceptions.
If you're going to pick on Java, at least jump on: Idiotic code on the web, Glassfish being a right pile, view technology being foul, servlet container reloading, Swing/JavaFX or Eclipse...
Play is not Java done right by any means. It's tightly coupled, has really poor documentation, breaking changes galore between major releases, deployment is trouble (compared to tomcat) and rather tied to Scala's API.
Java done right is picking some lego bricks that you stick together to get what you want and telling it how to wire them up.
YYMV but 99.9% of all problems are already solved off the shelf.
Scala can be used instead of Java to build systems, though when a Java developer uses it for the first time to build a system, that system will need heavy refactoring to make use of Scala's functional facilities. Groovy's really intended for use with Java, not instead of it, such as gluing Java apps together, testing Java objects, scripting Grails, and 20-liners for Gradle builds. I don't know how much Clojure's used to build systems in industry, though it's certainly my language for scripting.
form {
input {
name = "bob"
label = "Bob"
}
button {
action = #{bean.submit}
}
}
I've actually wrote a C code generator DSL over the top of Win32 many years ago that did this so the financial app I was working on so we didn't have to write millions of dialogs in win32 loops.That said, I found FXML + IntelliJ to be quite painless. The closing tags are verbose when you have small toy examples but in big files they help orient you by reminding you what the end of a block is. And I mostly use Scene Builder anyway.
I think there also a generational conflict here. Java is a development environment that was born in the big architecture and 'development as enginerring' era of the late 90s. Spring was a reaction to the over engineered J2EE and now even Spring, the early liberator is considered over engineered.
Its our dad's language.
There is still a certain mindset from that era that was conditioned by the GOF and Universities and amaeteurs churning out developers but it is increasingly rare.
In fact I find Java is amongst the most interally introspective and disciplined in terms of coding taste and style.
I can almost guarantee if I look at another Java developers codebase that I can follow their code structure and style without too much effort. I'm not sure that would be the case for the large amount of very individualistic FP code being generated currently.
I've also never found my-self working with a code-base I'd considered clean and highly maintainable. When code-bases becomes big and complex, they tend to get messy. It's hard, if not impossible, to maintain a complete view of the entire application at once - and this leads to different approaches at different times, and places in the code. Having multiple developers come and go, with various levels of skills, does not help either. Having some framework dictate the overall structure of the application limits the potential for to much diversity in the code, it also helps new developers get a grasp of the codebase if they have used the framework, or similar frameworks, in the past.
When I design a simple application, the flow is limited, and I don't need the abstractions - so I don't implement them. But when the system grows in complexity, and the concepts and logic starts to overlap, it becomes reasonable to implement abstractions. To layer the application into DAO, service, persistence layer, etc. To group common logic, and make abstract implementations. I could go on. Abstractions are good, but overuse is also not good - of-course, like everything else it's about finding the right balance.
But give me a gradle error and I'm stuck in their docs all day, you might have a solution this week. And by the way it breaks automatically all the time as Android Studio and the android tools plugins and all the rest version up. I wish we could have just stuck with Ant and Eclipse for Android, which are known evils. Instead every update of Studio and Gradle someone on the team has to draw the short straw and try, then either give everyone else the OK or tell them to stay the hell away from that version.
I say that as a Java developer, btw.
And there's nothing wrong with that, but if you want to build systems that have to be maintained over multiple years, you somehow have to compensate for that. Java is one compensation.
That doesn't say much. So yes, most developers are average, but what is average? Is it necessarily developers who need training wheels, helmets and elbow pads in order to protect themselves and others?
That may be the reality, for all I know. But that isn't necessarily a timeless truth. Take a room of expert programmers; now most of them are mediocre (average), relative to each other (imagine a really big room with a lot of experts, if you must). But that doesn't necessarily mean that they need languages that cramp their style in order to mitigate whatever damage they might do.
"Mediocre" is the same as "average", but with more negative connotations. Hence, when someone says that some people are 'mediocre', the immediate thought might be "bad". Then it becomes obvious that tools need to hinder these bad developers from screwing up too much. But mediocre is just a relative term, and can mean that they are really bad developers who create 100 bugs for every feature they implement, or that they are really competent, reliable developers.
I won't comment on the skill of the average (mediocre) developer. But I think that saying "most are mediocre" can easily hint at "most are bad" (because of connotations, not necessarily because that was the intent).
There certainly are huge variations in baseline skill depending on location and line of business.
I was thinking of the more or less generic enterprise software environment in firms whose main business is not software development, and which reside outside silicon valley or other tech hubs.
Stability -- none, regarding possible law suits from Oracle. Yes, it does matter for a company. Yes, Oracle did that in the past.
Performance -- poor, regarding memory consumption.
Indeed, the sweet spot.
> If you need lots of cheap developers [...]
Shoddy, you mean. For Haskell or Clojure you have at least a guarantee that the guys you found are decent. It's the same hard finding decent Java programmers as it is with Haskell, except that Java scares good devs away and Haskell attracts them.
Do you have actual examples of companies using Java for their run-of-the mill software that have been hit with lawsuits from Sun/Oracle? The only two I can remember are Sun vs Microsoft (because of proprietary extentions) and Oracle vs Google (complex licensing issues). Sounds like FUD to me.
Bollocks. Java code can be over-complex and lack elegance, but it's not the worst offender - sweet spot.
Stability -- none, regarding possible law suits from Oracle. Yes, it does matter for a company. Yes, Oracle did that in the past.
Bollocks. I challenge you to provide an example of a Java developer being sued for using the language.
Performance -- poor, regarding memory consumption.
Bollocks. Uses more memory than C, but no manual management. Sweet spot.
Shoddy, you mean. For Haskell or Clojure you have at least a guarantee that the guys you found are decent.
Bollocks. In my experience, they're likely to be somewhat better skilled and educated. They're also far more likely to spend their time arse-ing around trying to implement an elegant, concise solution to problems which only exist because of not-invented-here syndrome, or because their language lacks as extensive a standard library.
As an example, I once worked on a Mac GUI app for a company - bog-standard, nothing fancy. I took over from a developer who had been trying to build this using Racket; this involved building a Qt-Racket interface, which involved magical automated parsing of C++ header files, which meant… basically, not delivering a product. Meanwhile, the Objective C build was done.
The point is, there's far too much focus and snobbery about what tools developers use. There are loads of languages out there; pick one that has a reasonable amount of support and fits the problem domain, and build simple, maintainable code. You can do that in any language.
> Bollocks. Java code can be over-complex and lack elegance, but it's not the worst offender - sweet spot.
But Java is close. Compare its standard library with virtually anything else on the market. Nobody has dozen ways of reading a file, and in Java they can't be reduced to a one or two (buffered vs. unbuffered), because they're used in many places in the library.
>> Performance -- poor, regarding memory consumption.
> Bollocks. Uses more memory than C, but no manual management. Sweet spot.
Every other runtime has smaller memory requirements. No other runtime requires several hundreds megabytes of RAM to do anything non-trivial. Totally not the sweet spot.
>> Shoddy, you mean. For Haskell or Clojure you have at least a guarantee that the guys you found are decent.
> In my experience, they're likely to be somewhat better skilled and educated. They're also far more likely to spend their time arse-ing around trying to implement an elegant, concise solution [...]
...which is generally a good thing, you just need to remind them they need to ship the product. They need different approach than mediocre programmers. With the latter ones you need to focus on preserving acceptable quality, with the former you need to focus on getting things done.
> [...] solution to problems which only exist because of not-invented-here syndrome, or because their language lacks as extensive a standard library.
Standard library in Java is hardly extensive. It only contains several typical containers, some networking (raw, HTTP, SOAP and Java's dedicated RPC), a little cryptography, XML parser, regexes and GUI toolkit. Oh, and routines for Zip files. It doesn't even have SMTP library built in. It doesn't have HTTP crawler library, like WWW::Mechanize. No XML-RPC or REST library. No built-in support for parsers. No indexed storage, like BerkeleyDB or TokioCabinet.
It's hardly "extensive".
Of memory. Any other resource, you've basically got C with UNWIND-PROTECT and a cheap Schrödingerian knock-off of destructors.
Why using a simple constructor when you can use the factory design pattern? Or why directly instantiating a logger using the "new" statement and the right arguments, when you can also configure it using xml files? Making use of design patterns and frameworks is professional, after all, isn't?
You wouldn't want paths to documents be hardcoded in your office suite, would you? Or target address of VPN gateway in VPN client?
There are many contexts in which the factory pattern is the best choice (although not the majority) and in which configuring logging externally is the best choice (almost always).
Second, it is not like each java program would be inventing its own super complicated xml like logging configuration. It is pretty much always done the same standard way. Pretty much every java app uses one of two standard logging libraries and those libraries share the same API.
You can configure that standard API in xml, through properties file or in code and all three methods are basically the same thing in three different syntaxes. None of them is easier or harder then the other two and everyone is familiar with both xml and properties file one.
No one normally obsess about logging code too much. It is the least obtrusive easiest to do part of anything you can possibly work at.
For example, some changes even though very easy to implement are very difficult to push in production because of requirement of senior management approvals.
Also, best practices depend on the actual environment that you work on. For e.g. In one of the projects, the DBA team had very cool people compared to the server admins who were a pain to deal with even when we had all the approvals. So we decided to keep the configurations in a table and not xml, as changes could be pushed easily!
We use Java in a non-standard environment: products built on a enterprise Linux distribution, and therefore built using the same infrastructure and conventions: everything is built from source as a dependency chain, so that you can patch it and provide support, and ship those patched components back as packages. Everything is built in a repeatable environment, jailed in a VM, no network, that only contains the dependencies you declared.
So there were those nice times where building a Java library meant packaging 2 or 3 dependencies, then packaging the library was as simple as unpacking, apply any patches, set the classpath to the dependencies and run ant. Then install the resulting jar. It played well with the environment.
Java build tools are insane.
To build most libraries I now need Maven. Maven needs like a hundred dependencies to build, plus some plugins that need those dependencies, and those plugins build with Maven, the dependencies too. At the end, to build Maven, you need to have all components which are the reason you are building Maven in the first place.
So this makes me thing Java developers don't think in terms of layers, and they pull dependencies without balancing the costs (writing one function vs depending on 20 more jars).
A build tool should have almost no dependencies outside of the base system (in this case the JDK) and the compiler.
But no, they added even a Dependency Injection container. And now they realized that the one from Google is better, so they switch to it, but without removing the old. So now they may be depend on 150 packages instead of 100. Great. Lets add more stuff.
Imagine if to build make you need to have Gtk, and a library that builds with cmake and another library that builds with scons.
And all the noise with this advanced nuclear engines and frameworks to power something as simple as a build tools is at the end useless. At some point the project still declares technical bankruptcy and dies. Java has a lot of "choice" in terms of libraries, but a good percentage of them are dead projects.
It could give the perspective to programmers requiring from them that they always build their software on a freshly installed machine with no network connection.
Building without network connection was a feature most of these enterprise "build tools" did not get right from the beginning.
Patching a dependency, rebuilding the affected chain and ship it back to the customer is something I still ignore how the Java ecosystem does with their native tools.
Probably they just do "mvn" in their workstations and .zip the output folder.
1) Download and unzip
2) Run it
and that's all that was necessary. Meanwhile on the fly dependency resolution is very nice and a feature of most modern platforms.
However, I don't understand why you mix two things: maven concept and design (which is fine) with what I criticized: a build tool that depends on everything that it intends to build in the first place.
Of course, I am looking at this far from the battle-field, so maybe I am being too non-chalant.
Why package Maven anyway? You aren't likely to add much value by doing that.
But not, it is the obsession to turn everything into agnostic "engines" and meta-somethings, where everything is abstracted to the extreme with little value. At the end, Maven implementation using XML, plugins, dependency injection and having a build dependency chain of 100 packages did not prevent them from being kind of stuck in version 3 and slowly abandoned for another tool (gradle), leaving behind the only important value: conventions and the repository concept.
I can build/bootstrap ant and ivy just fine. And I can build almost every package using it by just telling them, don't go to the network, but use the one I already built myself with little effort.
If you ask why maven had to be packaged, mostly because it had to be patched with ugly hacks.
If anything, Java allowed the so called architects a much easier path to such crazy skyscrapper designs than any enterprise language before it.
So of course they went crazy with Java, and later on C#, because it was so easy to do so, without being caught in core dumps and similar issues.
Anyone complaining about enterprise Java, just needs to go back a few decades to see what was being done in C, C++ with CORBA/DCOM, VB/Delphi, CLIPPER and tons of wannabe 4GL languages.
Any language that wins the hearts of enterprise architects will suffer the same pains that Java is known for.
I can already imagine a "Enterprise Functional Design Patterns" and similar books.
What's scary is that big chunks of heavy industry are all standardised on it via OLE for Process Control (OPC).
At this moment I have an interface open with the following signature:
public interface ClientBenefitOrder extends Internationalizable<ClientBenefitOrderDisplay>, CBMEntity, Enableable<OfferCategories>, Deletable, Comparable<ClientBenefitOrder>, ClientOwned
This is entire application suffers from Enterprise Architechtitus, and like OP I have encountered that far too often for it to be a simple mistake. There is a cultural tendency in Java land towards overengineered solutions. It's pervasive. It also makes for bad code.What did Rich Hickey mean when he said, “All that specificity kills your reuse!”
http://programmers.stackexchange.com/questions/199217/what-d...
Part of the answer given:
"If you have two entities { "name":"John" } of type Person, and { "name": "Rover" } of type Dog, in Java-land they probably cannot interoperate unless they share a common interface or ancestor (like Mammal, which means writing more code). So the interfaces/types here are "killing your reuse": even though Person and Dog look the same, one cannot be used interchangeably with the other, unless you write additional code to support that. Note Hickey also jokes about projects in Java needing lots of classes ("Who here has written a Java application using just 20 classes?"), which seems one consequence of the above."
It's bloated and verbose, because Java isn't very good at it, not because it's a fundamental issue of OO with types.
> in Java-land they probably cannot interoperate [...]
Ditto.
If you have never had the need to introduce factories, I claim that you have not worked with a truly polymorphic system.
I mostly use Haskell and Clojure (with little text utilities in Ruby) now, but I still do find that Java is sometimes the best language for some projects. Off topic, but Java 8 streams and inline functions made the language better.
That said, I no longer use Java in any sort of "standard" way. I stopped using getters/setters years ago in favor of public instance variables. I also write a lot of static methods ("functions"). Basically, I try to make my Java code as concise as possible.
I also have turned my back on large server side frameworks. For web services, embedded Jetty and a JSON library is often all the library support that I need.
If you wrote code that did not abstract enough, such as not using factories, it was jaw-droppingly obvious to your colleagues that you were not good enough. FP and Scala owe the sheer verbosity of Java a lot for their current success :-)
So once we have a common name, shouldn't we use it? If I see a FooFactory, I have a pretty good idea what to expect in that class. So the problem with a FooFactoryFactoryAdaptor isn't that it is following GoF patterns or in it's silly name, it's that you have a solution that has at least 3 levels of abstraction. The patterns didn't cause that.
The problem is not the language itself, rather who uses and whats the culture associated with it.
Java is mostly used in the enterprises, where unfortunately thest "architects" exists. Architects are nothing but people have grown out of the roles and in a way of organization recognizing the peoples talent. Most of the times the Architects are redundant.
Most of the cases use of Java is nothing but writing your business logic into the Java code.
Unfortunately, architect to justify himself would try to engineer a solution, which never needed engineering itself. and down you go in the rabbit-hole of oops and abstraction.
Unfortunately it will be pretty hard for Java to shake up this image.
There are plenty of really tough integration, security, scalability and performance challenges that need someone who is across the entire stack from very top to very bottom. You rarely find developers who can manage it all and still find time to cut code.
Java is swamped in an over-proliferation of verbiage. That is the first impression one has of the language in school: that it requires twice as much code to do anything. And that was, as well, my last impression, as they tried to prepare us for our entry into the world of enterprise computing by steeping us in a rolling, boiling stew of jEverything. Too many cutesy names in a programming language just felt WRONG, and I think my instincts have been borne out. Java is a mess to behold and to work in, and I am fantastically glad that I didn't get that first (Java) job I applied for, but instead got the second (ASP.NET) job.
Irony abounds, I know, but .NET seems streamlined and elegant compared to Java EE. Turns out, sometimes you actually CAN judge a book by its cover. And by the 1496 pages in that Java textbook, which, hysterically, serves as merely an introduction...
I don't know where I'll be in a few years, but I'm fairly certain I'll not be coding in Java.
I haven't done any Android for my job (and just a little Java), but every time I have to design more than a self-contained python script, I'm grateful for the exposure to such complexity.
(and I know that probably many more are attracted because they already know Java but that's not my point)
I would have to write mobile, I would use one of those languages that compile into both Android and iOS as much as possible.
The problem is that it's a poor substitute for currying and composition.
I guess all I am saying is not the throw stones. No one is perfect and to bash a whole community today based a snapshot of what you have seen is narrow-minded, look for the good parts and focus on those at least. Teach someone to code well in Java, if you feel so inclined to say that you know better. I know that there is a lot to learn, personally. I currently do like Javascript and Python as well but I would never look down on Javascript, Python, or Java communities. They are all great in their own way and in many similar ways.
We all enjoy coding at some level, why does anotehr way of doing that have to be so worng?
This line just says - ignorance. Thee is a *tonne of stuff in Java. And just because the majority of developers are low quality(what language does not have that?), does not diminish the interesting stuff that is going on with the whole platform.
Relief washes over me in an awesome wave when I read this line.
No, no, I'm not attempt to mindlessly bash OO. But I've worked over the years with folks that put OO as some sort of holy rules. When arguing X vs. Y the discussion goes well until someone says "Y is wrong, Y violate {this} of OO", shit, when that little statement is made I know I'm lost. Because even if I attempt to show that in this particular case violating such principle is good, I am doomed to be considered a heretic, an outsider, and sometimes automatically a bad programmer.
I've tried to not thought of my self as an 'enlightened', but people kept acting as believers of such religion over and over that I could help myself sometimes. It's pretty much the feeling of being a philosopher teacher in mormon cult of something.
Another big problem with Java to me is that the standard library and available frameworks are so massive, that there are thousands of ways to solve any given problem. This is bad, because only a handful of the solutions perform well, result in readable well-written code, and are efficient (from both a productivity perspective and resource utilization perspective). I'm not sure why, but it seems like many developers are almost trained to pick the bad ones. Perhaps the high level of abstraction enables the programmer to ignore the realities of the implementation?
It is sad to see such strongly-worded blanket statements. The author generalises his experiences with Java to entire OO. He doesn't, unfortunately, seem to realise that non-Java OO does exist.
Also, several lean Java frameworks exist, without deep class hierarchies and factories of factories.
Finally, OO is one of several possible ways to modularise and scale code and teams. FP is another. As languages like Scala have been demonstrating, it is possible to selectively blend features of both in fruitful ways.
Especially when the language in question is getting libraries and native features that pull in the good parts of other languages.
Blog posts like these make stupid generalizations.
I'd also like to say if 5% of the Java Developers are the good developers that would be factors more than 100% of the Clojure developers + 100% of the Haskell developers + 100% more than the F# developers.
Instead, Java has a history of patterns for the sake of interest. Need to inject something in? Use a FactoryFactory. Most of what Java becomes revolves around having to do tedious CRUD apps for the enterprise that constantly change what they want.
You need high quality developers in Java, just as you do in any other language.
It seems like the article's beef is with OO programming, not Java per se.
I disagree that Android has the same problems. To me it looks like Android was actually written in lean-and-mean java. Ok its still Object Oriented. But for UIX interfaces, Object Orientation makes a lot of sense...
There are some areas in the android API that are indeed a bit bloated. And that is indeed inherent to java.
That can be said for ANY language.
Here's a blog post that shows how to make a game out of that madness we have gotten used to thanks to JEE / Spring
These days even the much hatted EJBs are POJO based and lot easier to work with. Not to mention Lambda support in Java 8 and the hybrid approach of Scala, my favorite.
When Google announced an open-source OS for mobile - I was so happy. But ... Java. Broke my heart. Don't Google have any taste. At least Google could bless an alt-Java Swift-ish alternative like Kotlin, Xtend, AnythingButJava.
Google's issue is too many languages and runtimes: Go, JS/ES6/V8, Dart/DartVM, Java/ART, PaNcl, RenderScript.
With the Material/Paper UI Google have given dev's a consistent, elegant unified surface. But Google should also be moving in the direction of an (elegant) unification under the hood. Java and JS are 20 years old - but are at the core of Google's platforms - Android and Chrome/OS. But what - Kotlin, Dart, ES6/7?
At the Google IO Android Fireside Chat, a developer asked the Android team about using an alternative to Java for development - Scala in his case. Pretty much 'no' was the response. But don't Google have any taste. Kotlin or Xtend imo are lighter than Scala and would be good fits for Android.
Moreover, Big Software is generally a bad idea. There are occasions where large programs are a good idea, but the default should be small, composable units. Scripting and batch jobs aren't "baby coding". They should be the default unless you need a long-running server process. Most programs (over 90%) should be doing one thing and doing it well. The problem is that people don't code this way because it's better for enterprise managers' and architects' careers to say they oversaw gigantic, overarching software projects.
I've actually noticed that data scientists, while their line-by-line coding skills aren't as good as a professional software engineer's, are usually much better designers (and far better communicators) than Java engineers. Sure, R is janky and Python has ugly corner cases, but data scientists write programs to do specific tasks and generally are good at keeping code small (because they have a personal responsibility for the code-- if they can't read it, it's basically lost-- not experienced by "architects" who can hire maintenance engineers to clean up their messes). You don't see the enterprise "software for software's sake" problem.
The result of Big Software tends to be Java Shop Politics, as described here: http://michaelochurch.wordpress.com/2012/04/13/java-shop-pol... . It's not the fault of Java. It's just a bad way of writing software.