Have you seen FizzBuzz: Enterprise Edition ?
https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris...
One can write a Java application and never touch XML, use AbstractFactoryWhateverTheFuck, and write sane, clean code. I've done so for years, worked on green and brown-field projects. I've also written, maintained, and modified monstrosities in Java... as well as C#, Javascript (front and back-end), PHP, Python, and plenty more.
Java is not the Hot New Thing™ and never will be. It's also not always the answer, but for a run of the mill application running on a web-server you're going to have a hard time finding a better language and ecosystem that will keep on trucking and be reasonable to work with.
case class Person(name: String, age: Int, likes: List[CustomObject]) //simple data object
implicit val personFormat: Format[Person] = format[Person] //this creates a "Format[Person]" with serialize/deserialize methods
The code to generate a serializer/deserializer is completely independent from the definition of the data, no annotations or XML needed. It is also efficient in that it doesn't use reflection. This is only possible because of how expressive Scala is - macros and strong type system means a lot of powerful code introspection can be done at compile time.Because of implicits, most of the time I write that one line above, and an HTTP handler as a simple function from (Person => HttpResponse) and dont even think about the serialization/deserialization. And that one line is not an opaque abstraction, it is very customizable if you need it to be, and all via code not config.
Using Jackson in Java can get much more complex because annotations and XML files creep across the whole code if you want compile time generation. I think this is directly because Java's inspect/generate code at compile-time is not as powerful as macros.
What, in your mind, is a good language that needs no framework?
If you find yourself doing this, it is a clear indication that the software design is failing to abstract properly or at all.
(I'd argue that the industry in general has a terrible ratio of "coders" to people who can design programs, thus you're much more likey to come across poor designs than good ones. Beware of this when judging programming languages.)
I believe, it is an indication that people tried to fix all the leaks in the abstractions, which turns the abstraction into an ugly twin of the stuff it tried to simplify.
ORMs are a good example. They start easy and simple, but lack various features of full SQL. If you start a new project, the ORM is fine. At some point, you are forced to use plain SQL, which clashes horribly with the ORM concepts. Thus the desire to extend the ORM. Over time more and more features are bolted on and the complexity grows.
There's a really bad trend in the industry of choosing libraries or tools based on trying to improve your resume, rather than trying to find the best solution to a problem.
I've yet to see a good one.
Often ORMs fail to implement JOINs efficiently.
Every ORM fails to give you a powerful query language: if they had a powerful query language, someone would write an ORM for the ORM, because the reason ORMs exist is that "SQL is hard", as the doll says, and any powerful query language will get the same treatment. But SQL is not really hard, and not having SQL eventually means you pay a huge price.
And then there's things like LDAP, which are absolutely awful. LDAP's object naming scheme has no canonical text representation. Let that sink in. And that's not even the main problem -- forcing your database to be hierarchical and a collection of objects, with no standard relation/pointer type, is. (Yes, Active Directory has an Object DN type, I'm aware.)
Just say NO to ORMs.
It's not true that people who know SQL always prefer using it to using an ORM. In one of my prior jobs we had strict controls on the queries that ran in production for performance reasons. We screened all of the query plans the planner generated, but we also used an ORM. Sometimes we needed to work around or even reimplement the queries that used to be in SQL due to niche features like index hinting or the HAVING clause. And yet usually we used the ORM because it was more concise and reduced manual mapping of columns to fields.
[1]: https://en.wikipedia.org/wiki/Object-relational_impedance_mi...
Java 8 and the current ecosystem can be incredibly lean and devoid of high levels of abstraction. Like today how I took the lovely Sinatra inspired http://sparkjava.com/ out for a spin. I think if Java can shed the memory of it's horrible past (and the enterprise space was truly bad) then it has a lot to offer developers these days.
Also, i think new grads tend to only know how to make things dry via abstraction (not considering the trade offs) and b/c of javas popularity and oop as a buzzword, always did it via inheritance.
It has been my experience and observation that something like a JMS library in Java are complex because of a different interpretation of "do one thing and do it well." In the Java world, possibly because of enterprise adoption, that means pluggable transport for the queue, pluggable aaa, pluggable security and encryption, pluggable durability storage, configurable delivery protocols and guarantees, aspect based hooks to support different ha patterns, pluggable dispatch on delivery and probably some other things I can't think of this early in the morning. Each JMS implementation is "the best damn message queue ever made" with tons and tons of features. That's not an expressiveness issue, unless it's too expressive. Java makes it easy to add a layer of abstraction at each of those decision points. The typical user here wants to get a message from one piece of software to another, maybe with ordering; JMS will do that more ways than you can imagine or care about and can use pieces of machinery you didn't even want to know about. Where does expressiveness play in to that?
Why do these reasons have to be mutually exclusive?
Furthermore, your second point relies on every single cumbersome/complex java library also being a perpetrator of trying to do too much. Surely a lot of people here can probably think of smaller libraries that explicitly don't try to do everything, and are still "complex" and cumbersome to use. The best examples I can think of were of internal libraries at previous jobs, and that happened across many languages not just java. These sorts of annoyances pop up repeatedly in a wide variety of languages, despite not necessarily having the same culture as java.
Not to play evangelist here, but I just haven't had as many of these kinds of issues with libraries since switching to more modular typed functional languages (i.e. ML/Haskell), and it has really played a role in helping me see the forest instead of the trees. Noticing how language complexity and inexpressiveness leads to those kinds of problems isn't supposed to be obvious or intuitive, because it's effectively a Butterfly Effect that causes most of its severe repercussions much further down the line. We can play whack-a-mole with smaller sources of complexity (such as java having kitchen-sink libraries) as long as we like, but shouldn't the goal be to hunt down where all those "complexity moles" are even coming from in the first place? Because if that is the goal, and even smaller more focused libraries still produce annoying amounts of incidental complexity, then there's not much room to blame anything other than the constraints of the language at that point.
I have written Java code and rewritten code large parts done by others. The issue I have noticed is architecture and framework mindset of people who just do not think solving problem at hand is important and good enough task. It would be ok if they wrote elegant library/framework but it was still junk and solved only very narrow problem. At each instance it was the problem of culture and people using Java because I was perfectly able to write productive and simple code with just standard plus very few extra libraries.
> Another language in this category is Go. It's still young enough that people haven't used it much outside the niche it was created
Huh, may be you should be able to give example of highly expressive and popular languages which are a hit with developers in very different domains. Because it is easy to pile on popular Java and increasingly popular Go without talking about alternatives.
Let me give an example of how Java limits ones thinking.
Look at these Stack overflow answers: http://stackoverflow.com/questions/28459498/why-are-java-str...
They are great examples of Java/C# users being unable to explain succinctly what the APIs are doing, because they lack the necessary common language. They have to answer with great essays describing various scenarios and use cases.
A Haskell user just needs to compare the type signatures, showing where the IO is happening. She will then understand the differences and the implications.
I would wait till Scala does something great natively without standing on shoulders of JVM/JRE etc.
Monkeypatching is everything you need in terms of power. The problem is that it is too powerful, and Python lack intermediately powerful constructs. So if you have a problem that could be perfectly solved by passing around anonymous functions, creating a DSL, or writing some macro, you will either write everything by hand, Java style, or use monkeypatching and get a mess of mutable code.
Still, monkeypatching will solve the problem. It is more powerful than any of those other features. It's just that killing your fly can be best done with some small tool, and cannons leave a mess wherever they are used.
Overall, it's a more useful response than the Ruby's community one. Ruby seems to have inherited the Lisp propensity of meta-programing everything so many of its basic libraries are incredibly hard to follow. Even with Ruby's metaprograming features being easier.
Still, providing safe metaprograming features sidesteps everything. I do love Haskell.
What happened to OS packaging was mostly a result of the arcane tools around .debs and .rpms, which led to sysadmins reinventing the wheel (poorly) using symlinks, tarballs, and shell scripts.
FPM helped to a great degree, but even then, what if you want two different versions of the same application on the same machine? And if you hack your way around that, how will you manage which instance of the application gets which port?
When Docker came out, that kind of ended the idea of using OS packages for deploying in-house applications. Why bother with a packaging infrastructure that will only tie you to a certain OS?
I still think OS packages have a place, especially for system level software. Nobody ever complains about how SSH failed to install or upgrade...
But even when using containers for internal software, Dockerfiles can still be a pain to deal with for the simple reason that most languages have horrible build-chains that produce unusable outputs, which as you said Golang addresses beautifully.
However I think you're off the mark when you say "mostly devops" are excited about it. It's entire companies that are excited about it, and for one simple reason: Languages with these bad build chains and bad outputs have led to the creation of an entire teams of people to deal with it.
The realization of this is spreading, and it's going to be an interesting time.
such things are less en vogue these days.
There are real benefits to picking the mainstream / popular option, which includes tons of documentation, forum discussions, books and developers available immediately for it. So when you go against the mainstream, those alternative tools have to be worth it.
I think Scala got over the worthiness threshold, by exposing one of the best OOP implementations exposed in a static language, sane generics, higher kinded types and implicits which make it possible to encode type-classes, which led to a community emphasizing on functional programming.
I think Kotlin isn't over that threshold. Some people view its thin layer approach to be an advantage. But it either has to evolve in being more than that, or to divorce itself from the JVM, because it is in direct competition with Java 8 otherwise. Evolving to be more than a Java++ goes against its own philosophy. Divorcing itself from the JVM is a work in progress, they also have a Javascript compiler, but the results aren't convincing enough for now.
It's a nice language, but personally I like those with a strong community of functional programmers and libraries. If I'll see http://typelevel.org for Kotlin, I might reconsider.
Short of implicits and higher kinded types what has Kotlin not yet copied from Scala? FP in the pure sense is still very much niche, nobody cares about Scalaz and Cats in Java land.
Providing a less powerful Scala as an alternative to Java might very well prove to be a great strategic move. Scala's certainly not going mainstream anytime soon, probably in part due to its being too powerful.
Going on 6 years in Scala, staying put for now, but will jump ship if/when something better comes along (for me Kotlin is not it).
Subtyping makes a lot of things that are easy in purely functional languages hard. I think that is also the main reason why you don't get global type inference.
As I like saying, the status quo in Java land is Spring and Hibernate and people bemoaning Scala's implicit parameters never wonder why such monstrosities like Spring or Hibernate happened. Sure, blame the culture, but that's only half the story.
The same thing happens with other inexpressive languages. One of them is Python. And here we disagree again, as I think Python is chock full of ugly parts.
It started with refusing powerful and multi-purpose language features, like multi-line anonymous functions. As a result Python has been patched repeatedly with multiple non-orthogonal features to supplant the need for multi-line anonymous functions and/or to make up for its statement oriented nature. Oh, now Python 3 got await/async as well, but somehow I don't think this will stop people from monkey patching the socket module. I'm going to make the claim that in fact Python is not a TOOWTDI platform, in spite of its much touted "spirit" and anybody making that claim never tried working with Gevent or Eventlet, trying to make it work with MySQL's client and being forced to use the native client because Django wasn't compatible with the pure one. Or with an N-th iteration of Ruby inspired libraries that hack into its meta programming features to make it smell like the DSLs in Ruby, but with limitations and leaks. I don't even want to talk about the build and dependency management tools in Python's land, because it should be self-evident how broken the Python ecosystem has been.
Another language in this category is Go. It's still young enough that people haven't used it much outside the niche it was created for and doesn't have much reuse going on in libraries. Give it time, you'll see the same pattern, same mistakes repeated again and again. Java was also a pioneer in dealing with concurrency, Java introduced generics really late and it was also built by famous engineers working for a sexy company, designed to appeal to beginners and managers.