Hacker News new | past | comments | ask | show | jobs | submit login
Java Developers (nsainsbury.svbtle.com)
256 points by nsainsbury on July 22, 2014 | hide | past | favorite | 315 comments



I agree with much of the article (also as being a java developer for the last 17 years).

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.


Interesting! The most important difference between frameworks and libraries seems to be the "don't call me, I'll call you" pattern. Frameworks call your code, while libraries get called by your code.

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.


Strange, since I started using Django a while ago, I would say it encourages me to keep my own code a lot more organized. Are Java frameworks so much different?

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.


You can define functions within the scope of another function in Python as well. It's up to the developer to keep it organized.


Yes, Python seems to encourage this sort of organization, while (from what I have seen) JavaScript does not.


> "don't call me, I'll call you" pattern

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


I really like your work, but not sure that it lies on the right side of the framework/library divide. For example, to realize the full benefits of your approach, you define a new programming language with "no escape hatches". That's the most extreme kind of framework thinking!

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.


We are not so much defining frameworks as we are new ways of computing. In that sense, it's not really something that will be ready tomorrow (or ever). I do use glitch as a library in C# for UI and compiler programming (hard to program very interactive UI and compilers otherwise), but that is with lots of escape hatches :)


Fair enough :-) Thanks for the pointers!


The point about defining a new language is that the abstraction doesn't leak, whereas frameworks generally leak left right and centre.


According to Joel Spolsky all abstractions leak: http://www.joelonsoftware.com/articles/LeakyAbstractions.htm...


Does assembly language leak compared to machine code? That is, does mnemonic names for machine code instructions leak?


Yes: for example the x86 MOV instruction is actually a family of instructions. You can see the leakage in the restrictions on which combinations of addressing modes you can use.


What? React is a framework as well. componentWillUpdate much?


code that you can simply read from top to bottom. Do this thing, then do that thing, then do the other thing.

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..


+1 for the last sentence. I get this nice "do this, then do that" understandability feeling when I work with python scripting of cloud services (e.g. AWS with boto). You get all the powerful apis and OOP mechanics boiling down to readable procedural code with helper functions.


There are several examples of simple libraries in Java that makes you realize it is possible to provide solutions to problems without the "culture" that predominates the ecosystem.

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.


Just had a look at jDBI and it doesn't exactly look like a simple library to me. There's a lot of run-time annotation processing.

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.


That pre-compilation step, though... How does that play with the IDE? I'm looking into various (more) modern ORM/DB-talky-to-things, and checked out jOOQ but was turned off by that pre-compilation step. I like having my errors bright and red when I type.

I also don't like code generation. I'm not closed-minded to it, just don't like it if I can avoid it.


> but was turned off by that pre-compilation step. I like having my errors bright and red when I type.

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)


> That pre-compilation step, though... How does that play with the IDE?

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.


I don't see any reason it shouldn't be possible to support pre-compilation steps as part of the IDE. Unless you are actively editing the bits that are compiled, it seems like this should work, but I am not an expert on what goes on behind the curtains of IDEs.


I mentioned I haven't used it, I only got the impression from the API, but you are criticizing the implementation right, not the API?


The main advantage is when doing something like this is Haskell the code you pass around can't have arbitrary side effects, so you don't actually need to worry so much about where it is called.


Yeah, I agree that having no side effects helps quite a bit. But you still need to understand control flow to reason about time and space complexity, which are a sort of "unavoidable effects".


If "it is almost impossible to understand control flow in Haskell" as you posit, then how are so many people making time and space efficient Haskell libraries?


> 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.

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.


Agreed. I'd say that most Java framework abstractions are ad-hoc and poorly thought out. Java frameworks usually do "reinvent the wheel".


Unless you're writing something very simple, you're going to end up re-inventing portions of a framework in order to do what you need to do anyway. In which case you're going to be wasting time. If you're trying to write a complex web application it isn't a good use of your time to implement templating/declarative views/JSON serializers/etc in a low-level language. It's not laziness - it's efficiency.

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.


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.

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.


Or, you know, use languages that take OO to its logical conclusion, like Ruby, Smalltalk, or the right answer in a concurrent environment, Erlang.

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 disagree OOP is the correct way of thinking about the real world, and I think the software industry is starting to realize it was an overblown fad too (and moving on to the next fad, of course), BUT...

... 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.


> 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".

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.


If you disagree, would you mind explaining your reasoning?

I suspect that we've started hitting the issue of "What, actually, is OOP?"


Well, part of the problem is that we've all accepted that OOP is the best way of modelling the real world, but there is no convincing proof. Maybe experience? I don't know. We do know modularity is valuable. We know OOP is a way of achieving modularity, but is it the best way? And is OOP-like-in-Java the best way of doing 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.


I think our scientific reductionist worldview is a better fit to simple datastructures plus functions that work on them than OO.


You can use libraries instead of frameworks to avoid reimplementing/reinventing functionality.


Ok - so in a web application I need routing/binding of controller functions to URLs/HTTP methods, the ability to interact with an RDBMS and parse a result-set into an intermediate abstraction, the ability to take in the results of a POST or PUT and parse it/validate it/sanitize it, the ability to emit JSON....and yet all of this functionality is baked into my web framework. I can either use a library for each one of those functions or I can just use a light-weight web framework and get all of them automatically. Most likely the framework is just a collection of libraries anyway - Scala Play Framework uses, for example, Anorm for database querying, Slick for higher-level ORM, Jerkson for JSON serializing/deserializing, Twirl for templating, etc, etc.

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.


I think the advantage of using each of those libraries instead of a single unifying framework is that you put them there and understand why they are there, instead of relying on defaults. Also, there is less risk of framework-induced coupling -- sure, many frameworks are configurable, but try to move away from their recommended components and you are asking for trouble...


Also, there is less risk of framework-induced coupling -- sure, many frameworks are configurable, but try to move away from their recommended components and you are asking for trouble...

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.


But good frameworks are essentially collections of commonly needed libraries (to solve whatever problem the framework is concerned with) wrapped in (hopefully thin) unifying API.


The distinction made in the context of this discussion was that frameworks call your code, whereas you call libraries.


Assembly, and Low Level Coding is the exact opposite of solving 'real' problems. Your going low level to create problems that didn't exist, as opposed to working on the core issue(often business related) your software is trying to solve.

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.


There are many goals and many problems. "People" should use the right tool for the job. I don't want to try to write performance critical code or low-level code (OS level, drivers, critical libraries) in a language that seems almost designed to resist my efforts. Similarly, most people don't want to write business critical processing in C.


Writing low-level code is important for writing the underlying libraries for those high-level languages, e.g. the run-time systems or the big integer routines.


It's also important due to it helping one understand everything that's going on under the hood in whatever high level language one's using


While it is important to know low level details if you are going to understand how the high level language is built, it is not necessarily important to know how the high level language works if such details don't readily aid you in your task.

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.


Who gives a shit? Computers are cheap, programmers are expensive. You're probably deploying onto Amazon anyways, so don't kid yourself.

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.


I more or less agree with your post, but take issue with a few things:

- 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.


> 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.

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.


> 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.

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.)


I think most of the problems are caused by enterprise, enterprise frameworks, and the sheer age of Java. There's a lot of technical debt built up and a lot of enterprisey frameworks that are way over engineered.

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.


You are bang on.

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.


+1 for the DocumentBuilderFactory. I was trying to figure out why such an idea was implemented. I saw it sort of like having multiple implementations of DEFLATE on the same system. Seems like you really only need one...

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.


Java is not designed to solve programming problems, it's designed to solve organizational problems. And it does a pretty good job. That's why you see lean startups shunning it then slowly migrating when their company gets too big.


> The OO craze has a part to play in this madness as well. More and more developers are stepping back and realising that as a programming paradigm, OO is actually pretty shit.

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!


> OO actually works well for scaling complexity, much better than toy immutable functions do.

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.


>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.

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.


If you get good at programming, you actually know when to apply these patterns (and many others not in the GoF bible).

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).


> If you get good at programming...

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.


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?


Actually there are "real systems" being written in FP e.g. Clojure @ SoundCloud.

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.


> Because languages like Scala and Clojure are rapidly taking over from Java in the enterprise space

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.


Doesn't change the point. It's called JAVA but with lazy streams and closures, everything Java culture built prior that will be moot and that's what the article is pointing at. Same thing happened in PHP land, people say PHP is great now, but what is PHP ? PHP5, which is a perlish javaesque thing ? or the regex craze html implicit template system that was PHP4 ? ...

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).


> Same thing happened in PHP land, people say PHP is great now, but what is PHP ? PHP5, which is a perlish javaesque thing ? or the regex craze html implicit template system that was PHP4 ? ...

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.


I'm talking about languages evolution. PHP5 got a Javaesque Object System, closures, generators. The idioms that will emerge will be close to other language with similar features, and what made php php is becoming less and less so.


PHP is actually the perfect example to disprove my point (pig with new lipstick). I'll reflect on that.


PHP is a funny thing, started very very low (https://twitter.com/agumonkey/status/488432654577303554), and nowadays it's got a lot of very positive improvements (linguistic features, faster interpreter, principled community). Who knows how long it will survive ...


> OOP is too verbose by it's essence compared to closures.

Could you comment on Smalltalk's blocks?


I never used ST, I thought a block == closures, but according to http://c2.com/cgi/wiki?SmalltalkBlocksAndClosures there were differences until they wanted to make blocks real closures.

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)


> OOP is too verbose by it's essence compared to closures.

Then CLOS is too verbose?


CLOS is a layer on top of CL, it's optional. Also, LISPs are as verbose as you want them too. If you identify boilerplate you macro it away. It's part of the culture. Some systems (php/symfony2, eclipse/emf) go out of their way to generate unnecessary temporary files, templates and such but it's still cumbersome.

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?).


I find it very strange that you've thrown LOOP in there. It may not be as sexy as canned functional algorithms or simple recursion, but for complex algorithms, it's an absolute joy to use.

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.


Talk about workarounds.


Lisp macros ? (first-class and generic, not bad for a workaround)


No, faced with the fact that CLOS is also verbose, although in a language that is all about closures, you started to present workarounds how to simplify its verbosity.


CLOS is verbose if all you're doing is encapsulating some state. If, on the other hand, you plan on doing anything remotely interesting, it's very succinct and expressive. Trying to emulate the functionality of CLOS' multiple dispatch and mixins in Java or C++ is hell beyond hell.

As for verbosity, I'll take ":accessor foo" over methods "getFoo" and "setFoo" with inane, useless autogenerated comments any day of the week.


I don't find CLOS verbose. Private slots by default, accessors as option ... I find LISPs quite succint in general, sure lots of parens, but usually the bare minimum of information is required. This contrasts with the large amount of useless code you can see in Java class definition that amount to nothing (setting fields, toString, manual get/set).


If you think those features change anything then you must have a poor understanding of FP or why people are moving to Scala/Clojure. It is a fundamentally different way of developing code that is starting to look really appealing to the enterprise.

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.


I did the two FP courses from Mr. Odersky using Scala as the main language and then continued playing with the language for small experiments.

While the language is awesome in general, I would not recommend it at work.


The secret of Scala is that it can be used in a wide variety of ways by a wide variety of teams. Yes, you can end up hiring people that would rather work in Haskell, or those that hate the type system and would rather code in Clojure. I've seen people that attempted to make Scala look like Java, or even Javascript. My current team, working in Scala, has had plenty of people like that. But the fact that you can get too academic with Scala does not mean you have to.

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.


I will steal that argument for D.


I think D has a completely different of issues starting by a) small community b) reference compiler is not fully free software c) free compiler (ldc) is not finished d) very few people work on both compilers, etc.


IMHO, D is a better teaching language than Python and a better systems language than Java. I wish Android was written in D. I can't enjoy using a language with significant whitespace or extremely forced OOP.

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.


GCD is still maintained basically by a single person, who replaced another person that basically stopped contributing and resulted the project stagnant for some years.


Any particular reason you wouldn't recommend it at work?


As the author of this post mentioned the culture of the Java developers, the "architect" thing and the frameworks, Scala has its own similar problems: it attracts a group of academics on type systems and creates over-engineering in a completely different direction.

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.


> it gets complex because it has too many features and tries to support all features present in other programming languages

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 understand what it is.

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.


> I don't see the need of it if you already have a class-based system.

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.


You seem to be stuck in the topic of how useful structural typing is. Which I agree with.


Eh what? No. I couldn't care less about structural types.

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 agree with partly with you.

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.


Oh, I also disliked implicit conversions a lot. I considered them a wart at some point. Made everything hard to read and reason about.

Almost every other way of "extending" a type would have worked better in practice eg. Xtend’s Extension Methods.


Extension methods have mostly the same drawbacks as implicits, but none of the advantages.

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).


I worked on Scala for two years seven or so years ago (2005-2007), and I'm not really worried about it (Scala is a great OOP language, and a soso FP language). Compared to Scala, Clojure has a minuscule user base (as one would expect for a Lisp).


Well there is an overwhelming trend towards Scala/Clojure both in the enterprise and for large internet sites. When companies like Twitter, LinkedIn, Foursquare, Netflix, eBay etc start embracing FP languages you can be sure the rest of the world takes notice.

My point was that serious companies are doing serious work with FP languages.


Scala isn't really functional, its more like a better Java that happens to include some FP abstractions (like C# does with Linq). Its actually a good OOP language, better than Java and even C#.

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.


I'm a Clojure fan, and the syntax has nothing to do with it. The pervasive immutability, persistent data structures, ease of threading and STM mechanics are the good bits as far as I'm concerned.

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.


It's unfair to call Scala 'not really functional'. Although I agree it allows for very rich OO programming, dismissing it as merely adopting "some FP abstractions" and comparing it to LINQ is bordering on FUD. To substantiate these claims, you have to at least give an example in which Scala falls short in being a functional programming language.

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.


Compared to the real functional languages (Haskell), the only reason I can think of that scala is called a functional language is because the community would be insecure in their smugness otherwise. You can totally use scala as a better java dipping into FP occasionally as you would in C#. It's not like say F#, which really forces you into a functional mindset.

Post functional is as vacuous as post modern, ultimately these labels are not meaningful.




I agree on that.

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.


F# at least pushes you into a functional style; its support for classes is just interop; this is as opposed to Scala, which really innovates on Java OO. OCaml is specifically OO (hence the O in the name), though with lots of functional features. SML and Scheme...are SML and Scheme. They don't fit nicely into OO or FP buckets.

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?


If you consider a language to be more functional, because it forces you to use functional approaches even where it produces an inferior solution, then F# will certainly win this comparison.

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.)


The point is that I can use Scala as an OOPL without ever dabbling very much in functional programming (beyond as much as I do in C#). I can't, however, do that with F#, and believe me...I really want a Scala-like language for .NET so I can move on from C#.

> 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.


> I really want a Scala-like language for .NET so I can move on from C#.

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.


> The point is that I can use Scala as an OOPL without ever dabbling very much in functional programming (beyond as much as I do in C#).

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).



>Because that's what people use to write real programs.

Many people said the same of GOTO statements a generation ago.


I don't believe the parent of your post meant to say that nothing ever changes ;) Personally I think Java is a good, first language to learn. It's quite simple and easy to get started with. I'm not saying Java exclusively mind you, but that it is one decent language to start with.

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.


>Because we all know, Google is known for hiring flakes who can't code or design real systems

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).


> Because we all know, Google is known for hiring flakes who can't code or design real systems.

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.


Most of the Googlers I know writing Java code would rather not be writing Java code. They would prefer Python or even Javascript (and a lot of FP enthusiasts also), but Java is what Android needs so Java it is. I would be very surprised if Google was hiring many people who only knew Java or were even very enthusiastic about it.

Perhaps the only language more reviled than Java in Google is C++.


I worked at Google for a long time.

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.


That's a really useful insight. What particular problems did you run across in Python that Java/C++ handled better?


It's hard for someone who was not the author to dive in to the middle of the code and understand it, debug it or upgrade it, due to the lack of explicit types.

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.


PyCharm is pretty neat, but coming form IntelliJ it's baby stuff. The tooling around Java can simply not be matched by a dynamic interpreted langauge. Probably ever.


And the more expressive your type system is, the more that becomes true. It will be interesting to see what is done for Idris tooling if it gets some popularity.

There's also lamdu[0] being made for Haskell which is pretty interesting.

0: https://peaker.github.io/lamdu/


What part of Python would you blame that on? Dynamic typing? Multiple inheritance?


That was not my point. Android is a developer platform; it uses Java because that is an accessible language for app developers, not because it is liked internally.


+1 for the "toy immutable functions". Immutability everywhere is the current hype, but like mutability it has its advantages/disadvantages. The main consideration is the tradeof between performance(best for mutability) vs ease of use of development (best for immutability). However on HN, the war is dogmatic whereas reality is not that black and white. As a Java developer, I find immutable String and primitives very convenient. For the rest, the liberty left to the developer is sufficient for high performance applications.


> The main consideration is the tradeof between performance(best for mutability) vs ease of use of development (best for immutability)

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.


> IIRC, Java String are immutable to allow creating substrings as views on the same char array, ...

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.


Ah, yeah, I remember discussion about this, but didn't know about its result (I'm not active Java developer for some time now). Anyway, I think you've got an idea - immutability assumption may be pretty useful and improve performance in some cases, not decrease it (if you use it correctly, of course).


What I find quite amusing is that all these posters bashing OOP, end up using languages that actually do offer some form of OOP, as they seem to lack the understanding that Java OOP is not the only way of doing OOP.

As all modern languages, even functional ones, have OOP support.


Also I thought the point was Java and not OOP.

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.


> 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.


I don't think "enterprise" is the problem here.

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.


I never found a way to sense the differences between OOP flavours (NPI). Are you thinking of ST/Ruby where it's object and method all the way down ?


There are many models:

- 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.


> OO like in Haskell

Please explain. Are you referring to type classes?


Yes. Type classes is a way of doing polymorphism in Haskell, the central point of OO.


OO is more general than that, it's just a general paradigm for code reuse. Polymorphism is one of many forms of code reuse (allowing functions to accept multiple type signatures). I wouldn't call it the "central point" because polymorphism can be done without OOP, and OOP can be done without polymorphism.


What you're saying is that traditional OO conflates polymorphism with encapsulation and inheritance, creating one big complexity murder-death-ball; whereas Haskell lets you have these things a-la carte, so you can deploy them as needed.


It is central. Without polymorphism you don't have a way to abstract algorithms over types.

So you just get ADTs as introduced by Mesa/Modula-2.


You can do OOP with only ad-hoc polymorphism, which is just method overloading, which is what Java and C++ do. Actual parametric polymorphism isn't necessary for OOP, and there are non-OOP languages that have it (e.g. SML has polymorphism but does not have objects).

So, polymorphism and object-orientation are orthogonal concerns. OOP is about encapsulation, inheritance, and modules that couple mutable state (attributes) and behavior (methods).


For the curious, Ocaml mixes both, its object model is parametric (see: http://caml.inria.fr/pub/docs/u3-ocaml/ocaml-objects.html)


> You can do OOP with only ad-hoc polymorphism...

Which is still polymorphism. I purposely did not enumerate all CS forms of polymorphism, but can get more detailed if you will.


I thought the central point of OOP was to encapsulate functions ("methods") and the data ("objects") they operate on, thereby providing a way to structure code? That's why it's called "Object Oriented Programming" and not "Polymorphism X Y".

Wikipedia at least seems to agree with me.


I think one problem that people have when they are talking about object oriented (or FP for that matter), is that there isn't a clear definition around what it means. Most developers agree that it is some mix of encapsulation, polymorphism and inheritance.

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.


I had that revelation at my college Lab, teacher discussing why OOP was such a beautiful thing, none of them could agree on definition of OOP nor the qualities.

FP is smaller and stricter, it's almost formally defined (you have denotational semantics for FP VM for what it's worth).


That is only in the case of OOP as introduced by Smalltalk.

For example, OOP with multi-methods, does not imply such encapsulation.


HyperCard and AppleScript. And JavaScript is pretty unique at this point. Scala's OO is also pretty unique with traits and type members.


How unique is JavaScript from SELF?

In regards to Scala, I would say OCaml has similar capabilities.


Scala's capabilities are not really comparable to OCaml, which doesn't even have traits. JavaScript has many influences beyond Self, and is enough of a mishmash even in its original form to have its own point in the list (at best, a not very similar descendant of self).


> Scala's capabilities are not really comparable to OCaml, which doesn't even have traits.

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.


Scala's OO features are more like Java's done better. OCaml is this weird object system that is structural most of the time sometimes nominative, and then there is that weird ML module system. Ah...I totally forgot about Moby. [1]

JavaScript has been very successful, and got a whole generation of programmers playing around with prototypes without knowing it.

[1] http://moby.cs.uchicago.edu


Thanks for pointing out to Moby.

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.


I think the biggest difference between Scala and OCaml is that Scala users don't (have to) tell beginners to avoid the OO part at all costs.

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".


OCaml's object/class system is actually pretty good. It isn't used very often in OCaml because most of what OO gives you can be more naturally expressed in other parts of the language, but that doesn't mean that it's bad. In particular, classes are still the best mechanism for open recursion in OCaml, and should be used when that is what is required.


> 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.

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...


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.

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.


> The CBV class hierarchy is complex enough that someone had to make this site to help everyone keep them straight: http://ccbv.co.uk/

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.


For scientific computation, libraries such as JAMA or la4j performs much faster than scipy on matrix operations or common linear algebra operations : http://martin-thoma.com/matrix-multiplication-python-java-cp... https://code.google.com/p/java-matrix-benchmark/wiki/Runtime...


Sorry, but both of these benchmarks are terrible. First link compares run time of the whole programs, including start-up time, time for parsing file and printing out resulting matrix. I'm pretty sure matrix multiplication was the fastest of all these operations. I haven't read details of second benchmark (in fact, I've got lost in all these XXXFactories and couldn't find where things are actually happening), but I see no Python sources to compare with. So it's quite useless in this discussion too.

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.


> Python with its main web framework - Django - is really shiny. I would say, it is one of the best web frameworks ever

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.


Intagram's website is small? Ok, so show me the large one written in Java. But let's agree: this should really be web site/web interface, not some back-end service in large distributed system like Twitter or LinkedIn, because in such systems there's a great mixture of the whole bunch of different languages.

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.

[1]: http://spring.poweredsites.org/top


Really? I heard the same claims about Perl, but didn't see much evidence of it when I worked on a large Perl app.


   ArrayIndexOutOfBoundsException
   ...
   extends IndexOutOfBoundsException
   extends RuntimeException
   extends Exception
   extends Throwable
Not exactly an abomination, but I would not call it thing of beauty


Most words exist in fairly deep ontologies also, is English an abomination?


> is English an abomination?

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.


Sidestepping much? We are, obviously, not speaking about a natural language here.

I think this is an example of an hierarchy without a purpose.

Pointless OO, what's not to love here..


There is a clear ontology in the above classes, and it's nice to formalize that in the language rather than just keep it informal in a naming convention. I mean, why not have subtypes if you have subtypes?


It seems that you argue for subtyping for the sake of subtyping.

Up to you man. Peace.


I don't read it that way.

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.


This kind of metaphor is why object systems go so epically wrong. You just want the minimum set of objects that you need to express the problem. In my experience, any attempt to map that to natural language taxonomies leads to a large number of object subtypes that just exist to name things, not DO things.

When dealing with OOP, I stick with patterns and keep everything else as flat as possible.


There seems to be an implication in your comment that people aren't using FP to write "big serious programs". Is that really what you are implying?


In that domain, yes! How many UI frameworks are functional (beyond I think...Om?)?


It's unfair to focus on "UI frameworks" when UI frameworks are specifically aimed at supporting client OSes where they have to deal with "preferred frameworks", all of which were developed when OO was all the craze. Functional programming has only been discovered as a practical paradigm quite recently! Besides, implying that "big serious programs" necessarily implies that they are UI programs is completely wrong.

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.


OOP is well suited to UI programming because it is built around metaphor. FP doesn't quite work because UI programmers like to think in terms of buttons and windows rather than f and g.

> 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.


> FP doesn't quite work because UI programmers like to think in terms of buttons and windows rather than f and g.

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.


These scalable messaging systems...we have those also. Also C++ mostly. I would be surprised if Google was very different.


Functional programming has been known and researched for decades. Mostly what happens is the obviously good features filter down into more mainstream languages, hence the new stream extension in Java 8, and the rest (lazy by default?) gets left behind.


The key selling point of functional languages is not lambdas, but immutable state and referential transparency. People read "advantages of functional programming" and think "anonymous functions" and "they're talking about scary Haskell" which is wrong.

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.


> The key selling point of functional languages is not lambdas, but immutable state and referential transparency.

Not everyone agrees, evidently! In his influential paper, Hughes argues that higher-order functions and laziness are key to functional programming.


I'm going to agree with parent. OO programming is mostly about objects...they have names and identity, with that identity they can have mutable state (would be difficult to have state without identity and aliasing). In pure functional programming land, all values are anonymous, there is no way to tell if you seen something for unless you setup a GUID in the value (which would also require state, but whatever). Those values have no identity, so mutable state is impossible, leading to a very different style of 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).


Hughes didn't disagree with what I said; I would contend that higher-order functions and laziness only improve modularity iff the language was referentially transparent in the first place. The assumption that the theoretical FP language he discusses is referentially transparent is found on page 2 of Hughes' paper.

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.


You can make immutable objects in Java. The result is quite, quite unpleasant IMHO, but so are many other things in Java. You just create an object that has final fields and a constructor (or a builder if you have a more complex object).

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.


Let's wait and see if Om inspire others. You know that ideas take time to diffuse, OOP/MVC has been a somehow natural fit for IHM, but like many other ideas (closures?) now that people can see it, maybe they'll change their mind.


> 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.

FP wasn't mentioned in the article. Criticism of OO doesn't necessarily mean embracing FP, as far as I know.


What other choice is there? Old fashioned procedural? Logic rule driven? Some "other flavor of OO but lets not call it OO" (e.g. component entities)? From a paradigm perspective, there are really only two in active contention.


CES is definitely not a flavor of OO. It can be mixed with OO and it can easily be implemented in OO languages, but it's far from being OO. You can't say 'entities are objects so CES is object oriented' because entities are not objects in the OO sense.

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.


I guess it really depends on your definition of "objects." If it quacks like a duck, its probably a duck. Inheritance is not necessary at all for objects (since at least the Treaty of Orlando).


It's true that there's no definition of "object oriented" that fits every language that has "objects". But that also means that the term "OOP", without the context of a language, is useless in discussions, because it doesn't mean anything.

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?


Go is fairly OO in its own 1970s style. JavaScript is definitely OO and not many would argue otherwise. C is not: struts don't support encapsulation directly. However, many have invented or reinvented OOP in C (including me) with void* and hand rolled virtual dispatch tables (you can even find that in Linux). Heck, how do you think the first C++ compiler was written? And you could of course do objects in assembly...it's even easy given a few macros. [1]

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...


It is possible to use OOP without taking the AbstractFactoryInjectorBean train all the way to the last stop.


A lot of these bloated patterns that got popular in the Java world have shorter, simpler alternatives when programming in a functional style. You often don't need multiple child classes to implement a template method if you can just pass a function to the constructor. You don't need a BananaFactory if you can just inject a createBanana function.

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.


I don't think Android supports Java 8, though.


I don't think Android supports even Java 7. Sure, maybe source level but AFAIK invokedynamic and method handles are still missing.


There's a thing called RetroLambda which purports to be a backport of lambdas to older versions of the runtime/platform.

However hopefully now ART is successfully launching they'll go back to upgrading the base foundation and move it beyond Java 6.


I thought there was some work to support Lambdas in ART?


There is a retro-lambda library that allows to write lambda expressions. It is compiled to jdk 6 compatible bytecode though.


I like your comment. Do you have any examples of C# libraries that use the ideas you're talking about? Or even better - do you know of a tutorial or something where I can clearly see the two approaches compared and contrasted?


Nancy: http://nancyfx.org

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();
                }
            });
        }


I've always found that the people who write the AbstractFactoryFactorySomethingVisitor patterns are the people who read about design patterns and want to use them for the sake of using them, because they think it makes them better developers.

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've been using Java for about 15 years and largely agree with the article. The verbosity of the Java language is definitely part of the problem, although that aspect is downplayed in his blog post. I agree with the author about the culture. Java programmers in general seem to be on some sort of design pattern frenzy, especially in the better known frameworks. It doesn't matter if you're writing a fancy framework or writing a trivial app to process a file, chances are you're going to see layer upon layer of over-engineering.

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...


I disagree with this, as a part time Java developer (I do C# most of the time). The points I disagree with:

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...


Some of the complaints about the over-formal language is a matter of taste, perhaps, but it does grate and is not a new complaint (see also: the Kingdom of Nouns rant). However Java developers are learning (or migrating to Scala/Groovy/Clojure). And there is hope -- the Play framework, for example, is an example of Java done right (imho). Spring 4 is moving in the right direction.


I don't think it's a matter of taste. TBH I write very little of the code that is checked in to the source control. The IDE does all the boilerplate. I literally design the method signatures, define the access policy for the methods and fill in a few gaps here and there.

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.


I agree a bit with the Play framework comments. It has some interesting things borrowed from Rails but it borrowed to much of the magic for my tasted. I'm using Wicket right now. which is very nice and flexible and well documented. The source code is easy to understand it is not lasagna.


Ninja Framework is rather nice, I've found. I looked around for Java web frameworks lately and it seemed to be the one that balanced good documentation, features, simple configuration and so on to my liking.


Thanks - I will investigate this one.


Deployment of Play is as simple as copying a JAR file onto a server and starting it.


> Java developers are learning (or migrating to Scala/Groovy/Clojure)

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.


The Java variety of the Play Framework is indeed pretty decent. Last time I worked with it however, it had to some really hacky stuff to work around deficiencies in Java (7).


What's your beef with JavaFX? I've been using it recently and it's a surprisingly well designed and nice UI framework. Parts of it are kind of immature and there are occasional surprising holes in its functionality, but that's because the current generation (after dropping the scripting language) is only a couple of versions old.


Mainly FXML (I hate XAML as well) but it's better than Swing.


How would you prefer to define UI layouts? Some other DSL? A binary format?


Another DSL. Structural DSL like this:

   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.


KotlinFX defines something a bit like this.

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.


You might already be familiar with it, but this looks a lot like QML.


I wasn't actually - never used Qt (been stuck in win32 and Wx). Thanks for pointing it out :)


As the author said its not the languages fault. And if you know what you are doing then Java is clean, mature, performant, dare I say it enjoyable platform to use.

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 been a java developer for over 10 years (8 professionally). I've worked as a consultant on large government projects, using legacy frameworks like Struts/Tiles and being forced to use older versions of Java. I've worked for tech-startups being able to use new and hot tech. like Cassandra, jdk8, and the play-framework. And in between I've hacked on a ton of personal projects, including tech like gwt, mongodb, android, etc. I've used lots of frameworks like Spring and Hibernate. Although such frameworks often provides abstractions and encourages usage of design patterns, I've never really found my-self getting lost in their layers of abstraction, and I've can't really say I've come across any "AbstractAdapterFactoryProviderBean"-either.

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.


I can say the same re your experience, but I kind of experience the same thing he links to with Gradle and really despise it. Handling the constant Groovy errors and Gradle errors, and spending my life digging through their docs for a language and a build system I couldn't care less about really depresses me when I'm a Java expert. Give me a stack trace and I'll have the problem fixed in five minutes with unit tests and UI automation tests done later that day.

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.


Java hits a sweet spot of simplicity, platform stability, safety and performance. Also, its popularity in the enterprise is partly because interchangeable, cog-in-the-machine low quality developers can be productive in it and not cause too many meltdowns. Thats an economic advantage! If you need lots of cheap developers for your IT department, good luck finding 15 Clojure and Haskell gurus.

I say that as a Java developer, btw.


Isn't it just a little sad that the biggest selling point of a language is that mediocre developers won't cause too many problems with it?


It's not sad, because most developers are mediocre. It may not apply to you, but if you work in the industry long enough you realize that very few of your colleagues are good/great.

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.


Exactly. By definition, most developers are mediocre, and thats okay. Platform stability and limiting complexity is really important in the long run, so (luckily, imho) C++ and Scala are non-starters.


> Exactly. By definition, most developers are mediocre, and thats okay.

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).


True, there is a negative connotation there - maybe using that term was a mistake.

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.


Simplicity -- none, if talking about the resulting code.

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.


Simplicity -- none, if talking about the resulting code.

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.


>> Simplicity -- none, if talking about the resulting code.

> 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".


>no manual management

Of memory. Any other resource, you've basically got C with UNWIND-PROTECT and a cheap Schrödingerian knock-off of destructors.


> I challenge you to provide an example of a Java developer being sued for using the language.

Google ? https://en.wikipedia.org/wiki/Oracle_v._Google


Google is not a software developer, rather a corporation that tried to work around paying for J2ME licenses.


> Stability -- none, regarding possible law suits from Oracle. Yes, it does matter for a company. Yes, Oracle did that in the past.

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.


There is a lot of Cargo Cult programming going on among Java developers.

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?


Your statement sounds like a reverse cargo cult. The problem is not that people use these constructs that you mention. The problem is that people use the wrong constructs at the wrong time, don't seem particularly good at judging which to use when and just use the most convoluted one by default.

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).


Actually, configuring logger with values stored in a separate file instead of hardcoded ones is a good thing. Logging configuration is configuration, after all.

You wouldn't want paths to documents be hardcoded in your office suite, would you? Or target address of VPN gateway in VPN client?


Hard coded logger instantiation in a library is anti-pattern. Whoever is using your library usually has his own opinions on how much of your stuff he wants in logs.


Why are you assuming that he is writing a library? I have seen people bloat up simple java applications with provision for future requirements which will never happen in the real world.


Logging is still weird example to pick up for it. First, it make sense to have it configurable in production (and yes we ask clients to raise logging level in production we have no access to in case of troubleshooting).

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.


Sorry the logging thing and the configuration thing wasn't my point. What I was trying to say was all the best practices and standard way of doing things are not set in stone and should be evaluated at every instance. Beginners write very inflexible code. When intermediate, they learn best practices and about making it flexible and keeping room for the future. But only after seeing enough projects in production, one will know which flexibilities make sense to the project at hand and which don't.

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!


over the years, I developped a fiery hatred of XML configuration files.


and I'm starting to develop a fiery hatred for JSON configuration files. At least XML had standard support for schemas and querying.


Over the years I've developed a deep understanding for why XML configuration is great. Java's move to annotation, upon annotation. As a result there is no single, canonical place I can go to see what the general configuration is. I have to track through classes, that may or may not have a good structure to find a specific instance of a route. Spring 3.x configurations, with inheritance are wonderful. The only work is to follow the imports.


While I have seen what you describe, I am not sure if it is only specific to Java, and I have to admit that I enjoy working with the Java platform. There are things in the ecosystem that annoy me more.

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.


Are you really generalising to an entire industry from the build procedure for a build tool? Why are you even building Maven in the first place? My experience with Maven has been:

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.


I think I already mentioned why Linux distros build the entire chain from source: they provide support for it, they need to be able to patch it and they can't take responsibility for binaries built in an unknown environment.

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.


Bootstrapping any tool is going to look that way. To compile gcc you need a C compiler don't you?


Yes, but gcc requires gcc and THAT is. gcc does not require KDE and apache to build (which is like Maven dependency chain looks like).


You probably are angry at the "length" of the dependency chain, but I see no conceptual difference between the two bootstrapped tools.

Of course, I am looking at this far from the battle-field, so maybe I am being too non-chalant.


So Maven is at fault because they prioritise their own development productivity over ..... Linux distributors?

Why package Maven anyway? You aren't likely to add much value by doing that.


I think what you call "development productivity" shows exactly the cancer that makes the Java ecosystem a spaguetti of jars (whith some of them being dead projects) instead of a lasagna where you see libraries use only other libraries from the layer "below".

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.


Well, there's exactly the reason I try and avoid distributor packaging as much as possible and prefer to use Maven from upstream. Not only is it much simpler but it means it's not being patched with "ugly hacks" by people who dislike the project. Sorry, Debian proved multiple times that this whole arrangement is a recipe for disaster. Maven is convenient and fast, I think I'll stick with it for now.


So what do you do if you realize one of your dependencies has a very bad security issue that will not be fixed upstream for a while and you need to fix it and ship an update to the customer? (or the same example with a crash bug in one jar, and you can't workaround it)


Programmers rarely see how their software is built and shipped. Those who have this opportunity rarely have their taste developed to see that external dependencies have cost associated. And it's not something specific to Java: I see the same in Ruby and Python.

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.


That is why I don't understand the "enterprise" sticker they try to put on some Java stuff.

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.


Applications are open for YC Winter 2021

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: