There's the language and there's the ecosystem. A lot of negative feelings that still linger are, IMHO, directed more at some of the painful historical aspects of the ecosystem: J2EE XML configuration hell, EJBs, bloated application servers, XML for everything, JAX-WS, SOAP, ant, classloader problems, maven dependency hell, 10 different logging libraries, etc... A lot of this stuff truly sucked.
But I feel things have improved over time. Dropwizard, gradle, embedded jetty, jersey, guava, Spring boot, etc... The trend is towards minimizing configuration and overall, the ecosystem has become somewhat more manageable. I wouldn't necessarily call it pleasant, but it's better.
An as for the language itself, Java8's lambdas + streams provide significant improvements.
(Example is contrived, since you could use the built in Collections.reverse() to achieve the same result. My main point is that we have eliminated ~4 lines (counting braces) of ceremony.)
Keep in mind that JAX-WS with JAX-B beats other rival libraries in other languages. If your requirement is to be a client that consumes SOAP web service given wsdl, I'd take Java any given day. The wsimport and wsdl tool that JDK provides beat any libraries.
Also, JAX-B annotation can serialize and deserialize to JSON given the right provider. That's JSON, XML with POJO with the price of one. Good example of Java ecosystem: build on top of existing one / backward compatible / play nice with others.
False. If you use a language that's homoiconic (any Lisp), you don't need to serialize anything. The source code of the language is already in its serialzed form. You can't beat the speed of not having to do something in the first place. As an aside, no sane person would write a SOAP webservice today.
I wrote a SOAP webservice -- not because I'm insane, but because our business relies on data sent to us.
We could certainly tell everyone that they'll need to write code to send us the data we need to be of use to them. Or we could look at the installed systems that hold their data, and see what built-in support those systems have for external integrations. And so: we quickly added a simple SOAP endpoint.
About serializing -- I'm potentially missing your point, but "The source code of the language is already in its serialzed form" doesn't seem to make sense. Who serializes source code? Values in data structures need to be transmitted, normally (sometimes in the form of source code -- e.g., JSON) -- homoiconic languages are interesting for other reasons, but not serialization.
So you're consuming data of an existing (legacy) SOAP service? Or complying with exisiting clients of a (legacy) SOAP service? That's not the same as writing a new SOAP service.
If the language you're using is already expressed in a form that does not need serialization, then you don't have to serialize it. This is the very essence of languages that are homoiconic. Perhaps you should familiarize yourself with that before down-voting what I have to say about it.
> So you're consuming data of an existing (legacy) SOAP service? Or complying with existing clients of a (legacy) SOAP service? That's not the same as writing a new SOAP service.
Neither; we're accommodating large, complex systems that only have a few options for "send selected data elsewhere". "Web services" (meaning SOAP) tends to be on that list, plus often other options that are completely unacceptable like "FTP".
> If the language you're using is already expressed in a form that does not need serialization, then you don't have to serialize it. This is the very essence of languages that are homoiconic. Perhaps you should familiarize yourself with that before down-voting what I have to say about it.
I'm someone who responded to you; I didn't downvote anything. I can try again: I use serialization all the time, to convert in-memory data structures into something I can send over a connection (or to disk, etc.), then to reconstitute them back into in-memory data structures on the other end. So I don't yet see how homoiconic languages play into serialization.
>If the language you're using is already expressed in a form that does not need serialization, then you don't have to serialize it.
Yeah. If only that language and "not needing serialization" code format didn't have 200 other problems, like NONE of the major services accepting it, lack of tooling, a sorry state of an ecosystem, difficulty of finding programmers and/or jobs, etc...
And the simple fact that taking code provided by a remote service and just using it as is just handing the keys of your server over.
LISP homoicity is nice but its a bad, bad idea to accept LISP code over the network from any client. Documented dataformats that are not executable are enough of a security risk that sending an executable around is not a great idea.
(Should have been attached to grandparent, as I agree with parent)
You really don't get it do you. An s-expression doesn't have to be evaled to be read. I just keep getting downvoted here. It's like offering a machine gun to a caveman and getting clubbed to death with it.
>An s-expression doesn't have to be evaled to be read.
Yeah, so you get a serialization format that's the same as your code. Big deal. And you have to live with your code having the same look as a serialization format. Even McCarthy wanted to give Lisp a proper syntax.
>It's like offering a machine gun to a caveman and getting clubbed to death with it.
More like it's coming to Paul Graham's house to tell him all about this new wonderful Lisp thing thing you've discovered. I mean, this is HN, what makes you think those that answered you don't already know and/or use Lisp and its homoiconicity properties?
Being used as a serialization format is perhaps the least interesting and useful property of Lisp code.
Okay, this suggests I'm not confused; there's just no argument given.
> Yeah, so you get a serialization format that's the same as your code. Big deal.
There's no reason this would be automatically a "good thing" -- a serialization format that is also valid source code -- it's just a thing. It's good to have a clean path from data structure to serialized data and back again; but if the obvious way to re-create the data structure (exec the code) has a huge security flaw built into it, that's no longer a clean path.
Human-readable serialized formats are nice; but guidelines on "readable" for a data structure vs. "readable" for full-power source code are not the same -- and "compact" is also strongly good for serialization formats, but not nearly so important for source code.
> Yeah, so you get a serialization format that's the same as your code. Big deal.
Oh, but it is! Making a massive compute grid can be done with just a few lines of code if your language is homoiconic. If you have to come up with a protocol and a data transfer format, well you have some work to do then.
SOAP certainly sucks, but regarding your comment on using lisp as the transfer protocol is a bad idea. Data transfer protocols must be verifiable - you should basically be able to write a piece of code that parses the data input and verifies that it will not do something bad if deserialized. Given that as far as I know, Lisp is turing-complete, this task is impossible. Therefore, Lisp, while being a nice programming language, is a very bad wire protocol.
Reading an sexp isn't the same as evaling it. Just read it and manipulate the resulting tree. Lisps have templating, marshalling, and unmarshalling built-in.
You've clearly never tried to implement a REST API using any flavor of Lisp before. Guess what: most clients of web services understand JSON and XML, not S-expressions.
I think we need something that could be called "The good parts of the Java/Ruby/C#/Javascript/... ecosystem".
Showing what tools and libraries are recommended at the moment and how some of them work together. In Javascript the ecosystem is growing almost exponentially which makes it impossible to keep up with everything. In Java and C# there is many old classes still in the libraries and around that most experienced developers avoid. And some trimmings of the ecosystem would probably be useful every 3-5 years or so.
I suspect readability isn't a big priority for you.
Here's how I'd write this, lambdas or not:
public static List<Integer> sortDescending(List<Integer> ints) {
ints.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
if (o1.equals(o2)) {
return 0;
} else if (o1 < o2) {
return 1;
} else {
return -1;
}
}
});
return ints;
}
My personal perspective is that your use is a typical abuse which turns simple code into something unreadable and overly complex. This makes code hard to maintain and buggy. Not to mention, it's nigh impossible to step through in a debugger..
shrug. This seems like a pretty standard use of the ternary operator to me. I mean, just google examples of Comparator, and you'll find tons of examples like this:
@Override
public int compareTo(Object arg0) {
Country country=(Country) arg0;
return (this.countryId < country.countryId ) ? -1:
(this.countryId > country.countryId ) ? 1:0 ;
}
But that's orthogonal to my point, which is that lambdas offer significant improvements to readability because they remove the irrelevant cruft and simplify the code.
And lambdas (or similar) has existed in C#, Python, Scala, Javascript and other languages for years. I still thinks this means that those languages has had large benefits compared to Java (7 and older). Now that Java 8 has lambdas even Java developers can learn to write better and more readable code. I also thinks that Java 8 is good enough for most projects now but Java 7 wasn't. Just my thinking.
That would probably never matter in practice, though—I've rarely seen compareTo() return anything other than -1, 0, or 1; certainly never anything approaching MAX/MIN_VALUE. Still, bravo for considering all of the edge cases.
I've used Ant, Maven, and Gradle, and Ant is the only one that's never given me a minute's trouble. But it's true that it has a bad reputation. It feels harder to use when everything is working right.
Ant's one of those "seldom skills". You set it up in the beginning and then tweak a little bit. Yes it works, it's fine. I just find it funny that it hasn't changed or evolved in a long time. I just keep taking my old examples and tweaking them. It's weird.
>>Java8's lambdas + streams provide significant improvements.
It will take more than a decade before we see any decent adoption of Java 8 in the industry.
You are still going to see piles and piles of getters/setters, Enums, your design patterns taken to far extreme. Writing such pointless ceremonial code is the bloodline of Java community.
Merely introducing a new version hardly changes anything.
The community that takes design patterns to far just happens to use Java (1.4 ;( ) if they used a different language they would do the same to that :(
Anecdote: I once saw a Perl shop that could have been the worst of Enterprise Java. They where the same because they where ENTERPRISE, they suffered in Perl in the same way the common office programmer suffers in Java.
Verbosity matters for reading and maintenance far more than it does for writing. IDEs can make the writing faster, but they can't make the code as easy to comprehend as it would be in a more expressive language. And remember that lines of code is the only proven risk factor for bugs.
Most sites are not Twitter. They're not Stack Overflow. They're not even Nanowrimo. I've watched a company spend two years, dozens of developers, and over a million in ESB license fees failing to write a site that was expected to have, at peak, 100 users/day. Their competitor had four guys writing Ruby, and was profitable after the first month. Nor are the performance advantages "permanent"; even if you use Java, you will probably have to rewrite if you reach Twitter scale, because your initial app won't be clusterable (or if it is, it's massively overengineered and your business will fail). So do it the way twitter succeeded - write the first version in Ruby, and then worry about performance when you need to.
The advantage of using the same language on both sides of a boundary are real but overstated. If you have a system with multiple components, you probably need to evolve the interfaces between them, and you need to be able to upgrade without downtime. Which means you need well-defined interfaces for which you understand the compatibility implications - in other words, you need something like Thrift. I've used Thrift even for Java-Java interfaces, but once you're using something like that it doesn't matter which language is on the other side.
Still, the library point is valid, as is the point about spending time with a language. Better to have one language that you know very well than ten in which you dabble. But by the same token it's worth taking the time to make sure that language is the very best available. I use Scala for everything, and there's plenty to learn - maybe even twice as much as a "normal" language. But if I'm focusing on that one language, I can afford to take the time to learn it really well. And Scala combines the expressiveness, clarity and scripting-suitability of Python (yes, it can be unclear if you use silly method names or libraries that use silly method names - don't do that then) with the strong type-safety and performance of Java. It's a great language in any case, but especially if you want a single language for everything, I don't think anything else comes close.
> I've watched a company spend two years, dozens of developers, and over a million in ESB license fees failing to write a site that was expected to have, at peak, 100 users/day.
I'm sorry to hear that. But you understand that this had nothing to do with Java, right? Java didn't make those people do that. That was just good old fashioned human stupidity. It's entirely possible to write simple things in Java, without ESBs and a person-century of effort.
> Nor are the performance advantages "permanent"; even if you use Java, you will probably have to rewrite if you reach Twitter scale, because your initial app won't be clusterable (or if it is, it's massively overengineered and your business will fail).
I don't think this is true either. The normal approach to writing scalable apps these days is the twelve factor approach:
And that works just as well for tiny deployments as huge ones. It doesn't involve doing anything arcane and expensive up front. It's mostly common sense. Scaling out will involve a lot of changes, but incremental ones.
It's entirely possible to write simple things in Java, without ESBs and a person-century of effort.
That I don't disagree with (see Java4K and various other demoscene-like competitions), but when the mainstream culture of Java is oriented towards architecture-astronautism and "enterprisey" bureaucratic excesses of complexity, that's what the majority of Java developers you find are going to do. Ask them why a simpler (and less time-consuming) solution wouldn't suffice and they'll respond with things like "robustness", "extensibility", "modularity", "encapsulation", "abstraction", etc. even when none of these properties are truly applicable to the situation at hand. If I were to guess why, they're just so accustomed to writing code with such indirectness that a simple solution feels "wrong" to them. I worked very briefly for a Java shop and on one occasion my code was rejected, and was told to "refactor" a fairly trivial 20-line method in one class into 8 separate classes each containing 1-line methods on account of the fact that my original code was not "extensible" nor "modular" enough. I was suggested to introduce a design pattern to do this. Any advantage of that extra flexibility was never realised since the application was eventually completely scrapped in a rewrite. (I left shortly after that.)
"was told to "refactor" a fairly trivial 20-line method in one class into 8 separate classes each containing 1-line methods"
How typical is this level of non-value adding misguided pedantism? I understand that big software consultancies would want to milk their clients for all the work they can for implementing function points. But what profitability models drive developers to this level of weirdness? Is it just a cultural pathology?
It's plain and simple pedantry, and it's not confined to Java. This mindset has a healthy representation in the Ruby community, which actually makes programming in Java much less distasteful to me -- if I'm going to be writing AbstractSingletonFactoryAdapters, then at least let my AbstractSingletonFactoryAdapters be fast.
This is excessive but I've seen numerous similar cases. Premature code future-proofing has always struck me as similar to premature code optimisation. Generally something that newer/weaker devs tend to do until they learn better.
No it is not. Just because you have a one bad experience, doesn't mean that is how the enterprise works. There are hundreds of thousands of enterprise shops out there. We don't do anything like the craziness you guys are talking about. We make it work with the easiest code possible. If necessary we refactor when we need to make a solution more generic.
Java at Amazon, Google, Twitter etc. is generally less pedantic and more focused. I have been a Java developer since 1997 and the only time I've seen the type of pedantry you are talking about is at non-technology companies where the most important metric is how cheap a developer is, not how much value they can add.
> I'm sorry to hear that. But you understand that this had nothing to do with Java, right? Java didn't make those people do that. That was just good old fashioned human stupidity. It's entirely possible to write simple things in Java, without ESBs and a person-century of effort.
It's an extreme example of the same mistake this blog post is making. I mean, from a certain point of view they were right - if the site had reached twitter scale, it would have needed those things. The market genuinely is growing, and the problems the system solves exist in almost every industry. I expect those four guys won't keep their system in Rails forever.
Maybe using PHP really will make your system slower by a factor of 15. So what? A trivial saving in development time - say a week over your first year, a 2% factor - is well worth that 15x performance penalty for most businesses.
((Don't use PHP, kids. But not because of the performance))
> The normal approach to writing scalable apps these days is the twelve factor approach
Hmm, I wonder how many people have heard of this, and you say it's "the normal approach".
Debugging distributed systems is and always will be harder than debugging monolithic systems. Even the simple engineering good practices from that page, like explicitly declaring dependencies, have a cost. My Google friends tell me their explicit policy is to design a service for one order of magnitude more than the current traffic, and expect to rewrite it after that.
And once you're doing the things you need to scale - explicitly defined interfaces, all calls going via the network or something equivalent to it, service discovery - then changing the language used in parts of the system really isn't that big a deal. You can do it incrementally. (I have experience of doing just that, at last.fm)
> I expect those four guys won't keep their system in Rails forever.
For people who didn't know this, I would like to add that Twitter was written in Rails as well. They switched later on for a couple of reasons[stackoverflow].
My bad. I suppose i live in a bubble just like anyone else. I do think this is a well-known approach within the bits of software culture that talk about scalability. If you're a regular reader of highscalability.com, or a developer at Netflix, or one of the sad nerds who wish they were (eg me), or you've read the Heroku documentation, you've heard of 12-factor. But no, not everyone has, and in particular not every working stiff who shovels Java for a living.
The book is mostly about the use of the Java EE APIs. As such, it's not all that affected by the evolution of the core language from 6 to 7 to 8.
However, it probably will be affected by the evolution of the Java EE API. EE 6 was a huge, massively simplifying, change from EE 5, which is why it needed a book like this. EE 7 was a fairly incremental change from EE 6, and EE 8 is set to also be a modest step forward.
The biggest change in EE 8 - and i don't know whether to laugh or cry about this - is that Java will be getting a standard web MVC layer. Fifteen years after such things first appeared on the scene, and five years after they became passé. Maybe there'll be an API for controlling dialup modems or AIM clients next.
> they can't make the code as easy to comprehend as it would be in a more expressive language.
It's a little hard to make a general statement using an vague term like "expressiveness".
Static typing can actually make things clearer. That's a kind of expressiveness. You can know with complete certainty what type of data the code works with, just by looking at it. No need to rely on a certain set of unit tests living somewhere else to confirm your assumptions. And if you say "well just read the function docs", how is that any less verbose in the end? It's the same verbosity, minus the compiler guarantees.
On the other hand, there are situations where DSLs can greatly cut down on route programming. Like Apache Pig vs. calling Java APIs. But that's a more extreme example, an actual speciality "domain" to make a specific language for.
I might help to use a more precise term like verbosity. Then we can ask, is this verbosity really helpful (like explicitly declaring types), or can we compact it without losing significant information. Fortunately Java 8 has made some progress with adopting features that cut down on unnecessary verbosity.
Static typing can make things clearer, indeed, however Java has really shitty static typing. Also this is a common misconception:
> You can know with complete certainty what type of data the code works with, just by looking at it.
First of all, the type is only a limited view of the shape of the underlying data, written from the perspective of the business logic using it. In a micro-services architecture it happens often to see the same data exposed with types that are often very different, depending on what you're trying to accomplish. And too often developers that work with Java are complecting the business logic with the actual data, which is often pure data that's being messed up with short term business logic rules.
And furthermore, Java developers don't work with static type safety. Tell me, what does a String tell you? What does a Double tell you? How often have you seen explicit type-safe numeric types in Java (e.g. lets say values that are in kilowatts, or meters, or other units of measure)? You don't see that, because Java is awful at expressing such types, from the lack of operating overloading, to the completely retarded generics system and the lack of type-classes.
Second of all, the type IS NOT sufficient documentation when dealing with non-determinism and if side-effects happen in your system, then that's non-determinism. And when non-determinism happens, you need to document the protocol of communication and static types in mainstream languages cannot capture that, which is a PITA because that would be far more useful than seeing that this Person has an email address.
> In a micro-services architecture it happens often to see the same data exposed with types that are often very different
You mean micro-services that use dynamic instead of strongly typed APIs? That's really more a critique of such architectures than the facility of static typing.
> Tell me, what does a String tell you? What does a Double tell you?
It tells you you can't use a String where a Double is needed, without unit tests, from the very moment you type the reference in your IDE.
You're correct that it doesn't eliminate all possible problems such as validating the unit of measurement, and that it's not sufficient documentation in and of itself. But that's not the goal of static typing. It's there to eliminate a very large swath of problems through simple declarations in code.
Type safety is valuable, but you can have equivalent or better type safety in a much less verbose language than Java. e.g. I use Scala - it's not quite as concise as Python, but it's pretty close, and the language is powerful enough that I can express more possible effects directly in the type system (Does this method make an async call? Does it access the database? Does it log audit events?) without the code becoming unreadably verbose.
Care to share more details of these companies including how the Ruby ones become profitable after a month with 4 guys on payroll? No offense but I've got to check the facts these days.. :).
Also, don't forget Fred Brooks article about the Second System. I betcha smart engineers on tight budget can hack in Java just as quick as those 4 guys and achieve the same result. My apology, Java today is as productive as Ruby on Rails.
The difference between rewriting a Rails site to Java and an already written system un Java to a more modern architecture is huge. One can slowly move from old Java architecture to the newer one but it'll be trickier from Rails to something else... don't forget the accumulated Ops experience managing jvm based app server, the devil in details for those experienced engineers who have been there and done that...
> Care to share more details of these companies including how the Ruby ones become profitable after a month with 4 guys on payroll? No offense but I've got to check the facts these days.. :).
It was small industry, those were basically the only two companies in it, I don't feel I can. (I've already changed some small details e.g. it wasn't actually Ruby). In any case it's just one person's anecdote - but I bet it's happened a lot.
> My apology, Java today is as productive as Ruby on Rails.
Citation needed. In the programming language shootout Ruby still comes out much shorter than Java, and like I said, the only proven risk factor for bugs is number of lines of code.
> One can slowly move from old Java architecture to the newer one but it'll be trickier from Rails to something else...
When I worked at last.fm this was literally my entire job (well, from PHP). You're rearchitecting anyway, creating stable interfaces and putting load balancers in there because those are also things you need to do as you're scaling up. Changing languages is no harder.
> don't forget the accumulated Ops experience managing jvm based app server, the devil in details for those experienced engineers who have been there and done that...
You can hire the experience - Java is literally the easiest language to hire for (I mean, hiring is still hard, and there are a lot of crap java programmers around, but there is a bigger pool of experienced programmers out there than any other language). And you're going to need to hire anyway; your ops team will have to grow, your engineering team will have to grow more, and you absolutely cannot rely on the engineers who bought the first version still being around when the time comes to rewrite; the half-life of an engineer in a startup is not large.
Twitter was the article's choice of example, not mine - and from a business point of view Rails worked really well there.
>the only proven risk factor for bugs is number of lines of code.
I'm sure you can cite that, but it feels wrong in this context.
That is, given the same language, or equally verbose languages, it may be true and applicable. But, if comparing a more verbose language to one that is less so, then the former will naturally yield a higher LOC count. But, does this mean it's more bug prone? There aren't any more logical constructs, flow control mechanisms, etc. The language simply requires more lines to express the same intentionality.
In fact, I wonder how a more verbose language would compare with a less verbose one if we normalized for some verbosity factor. So, let's say language A is twice as verbose as language B, such that when the LOC count of A is twice that of B, we consider them equal (call it the same "Effective LOC").
I actually wonder if, in this case, language B would have a higher bug count per effective LOC, owed to its terseness and/or reduced readability.
This behaviour - downvoting without explanation irritates me too when there is very lucid and concisely structured argument you can oppose.
As such, I do not find your argument for verbosity normalizing convincing :)
I fail to see how normalizing some risk metric against a verbosity of language will provide any valid data in the general context. For numerical algorithms, where a multiplication is just as verbose in any language then there is no difference.
But when manipulating collections, for example in C I need to write
int i;
for(i = 0; i < someSize; i++){...}
This has several places where the verbosity of language can make it easier to write bugs that slow down the progress a bit. If we add these tiny slowdowns throughout the lifecycle of the entire application the cost is not neglible if compared to a situation where these bugs would not appear at all. Some other language:
for i in collection do:...
Which does really have no place to shoot oneself in the foot unless the iteration logic itself does something funny.
Well, I can appreciate the reply versus a downvote, but "I do not find your argument [against] verbosity normalizing convincing." :)
>I fail to see how normalizing some risk metric against a verbosity of language will provide any valid data in the general context.
OK, then let's look at the corollary: that is, not normalizing against verbosity would mean, roughly, that you're claiming that a language that is twice as verbose would yield twice the bugs over the same app. I don't think that's the case nor what you intend to say.
I think you're also confusing complexity with verbosity. An extremely terse language can be very complex, and may even suffer from readability issues.
Overall, the notion of LOC alone being a risk-metric absent any additional context seems an oversimplification.
"Overall, the notion of LOC alone being a risk-metric absent any additional context seems an oversimplification."
Yeah, I agree completely. Didn't think too long before answering there, I'm afraid. I confused the fact that in my experience increase of LOC correlates with increased risk of bugs with there actually being a causality between the said observables.
For me personally languages with higher LOC are harder to read, but this is just about the languages I like and not a generalization that can be applied to any language in general (i.e. Ocaml is nicer than C in this sense but APL or J would get me just terribly confused).
Basically, of the languages I consider readable, and when dealing with container operations, it's easier for me to parse especially those that either have basic containers as fundamental data types in the language (e.g. Python, F#) or have a uniform syntax over typical algorithms and containers (Clojure) rather than verbose languages like C or Java.
In these instances, it's not about the overall LOC count of the languages but the fact that they make common operations more legible and easier to reason with than C. I.e. they have less non-value adding burden typically. Why they are nicer, is not because of their LOC, though, but their LOC is a side-effect of their features that make them nice, I think.
What you argue is not that LOC in itself causes bugs, but that certain programming syntaxes are both complex (thus induces bugs) and takes up more LOC.
>You're rearchitecting anyway, creating stable interfaces and putting load balancers in there because those are also things you need to do as you're scaling up. Changing languages is no harder
I have to disagree here. With just a little forethought, a good bit of the code can be reusable. For instance, your data access layer.
And, the more forethought you put into it, the larger the potential reusability. This doesn't have to be premature optimization. It's just a balance between getting it done as quickly/efficiently as possible while still making some sensible, fairly low-cost coding decisions for scalability. For instance, everything I write now is load-balancer ready. This was achieved largely through a simple library that understands its environment via a simple config directive, and proxies relevant calls (e.g. when pulling the client IP or checking whether the request is secure, it determines when to pull from the request headers stamped on by the load balancer versus invoking request.getRemoteAddr() or request.isSecure()). Of course, there are other coding decisions you make, but it's really not as much extra work as how you implement.
In any case, unless you're purposely writing completely nasty throwaway code, there is always some reusability, which typically makes starting from scratch in a new language a much weightier prospect than making some scalability enhancements to the existing base.
> In any case, unless you're purposely writing completely nasty throwaway code, there is always some reusability, which typically makes starting from scratch in a new language a much weightier prospect than making some scalability enhancements to the existing base.
It's not really from scratch. If you've figured out the correct structure and interfaces to solve your problem you can reuse all that when porting to a different language, and that's the hard part of development.
>If you've figured out the correct structure and interfaces to solve your problem you can reuse all that when porting to a different language
Well, I think you're underestimating the sheer brute force work needed to port an app with a large-ish LOC base.
But, beyond that, if you've gone through the care of structuring it correctly such that the structure and interfaces are preservable once scalability needs arise, then all the more reason not to port it. Presumably, at that point you'd have, not only the structure, but working code.
So, if it can be so readily adapted to a new language and you're preserving so much code, then why bother porting it? Kind of makes may original argument. Just apply the scalability tweaks on the existing code base and you're done.
> Well, I think you're underestimating the sheer brute force work needed to port an app with a large-ish LOC base.
I have done this professionally. You don't port everything, you just port services as they become bottlenecks. By the time you need to scale like this, you already need to have multiple engineering teams and you need well-defined interfaces between components, so having parts of your system in different languages doesn't impose an additional cost.
> So, if it can be so readily adapted to a new language and you're preserving so much code, then why bother porting it? Kind of makes may original argument. Just apply the scalability tweaks on the existing code base and you're done.
Sure, which is probably why Digg was happy to carry on using PHP. For the vast majority of systems you never get to the scale where using Java is worthwhile (at least in performance terms).
When do you want to port? When your server costs get high enough that a 15x performance factor is worth the constant cost in dev time that using a lower-level language would cost[1]. It might take more effort than writing in Java from day 1 - but it might not, if you go through several iterations of prototyping/refactoring in PHP and then only port once you've found the correct design. And more importantly, you get to pay the Java price much further down the line, when you're bigger and more profitable. As PG says, an early-stage startup should do things that don't scale.
[1] I'm not convinced you can't have your cake and eat it, with e.g. Scala or Haskell. But assuming for the sake of the argument that the only languages were Java and PHP and PHP really was more productive than Java but less performant.
>I have done this professionally. You don't port everything, you just port services as they become bottlenecks.
Yep, been there too. Except, in the case I'm thinking of, it wasn't for performance. We went with a multi-language approach for different reasons, and we ended up with a hybrid that no-one liked. Then, we finally decided to port everything to one language.
All of this to say that a multi-language approach can have its own drawbacks, which is not to say that it's never appropriate. There should just be a really good reason for it. Generally, I'm not sure that starting with a plan to half-port a non-performant app is a good reason. But, I'd never say never.
I'd also add (again) that if you've really taken the time to structure the app so well that you have clean interfaces and modularized, easily-portable services, then it begs the question: did you really save so much time by then implementing that design in PHP vs Java? As you said, the design is the hard part, and I'm just not seeing the notion of a quick non-scaling app, somewhat hastily implemented in PHP, being compatible with the idea of a tight, service-oriented, modular design. I think you kind of have to choose one.
I don't suppose any approach is necessarily the absolute right approach per se. But, given that the article is about picking one approach/language (Java) and sticking with it, I'd have to say that I'm still convinced that it may indeed be optimal, even after reviewing your points.
> I'm just not seeing the notion of a quick non-scaling app, somewhat hastily implemented in PHP, being compatible with the idea of a tight, service-oriented, modular design. I think you kind of have to choose one.
Oh sure, the initial code was pretty terrible. But by the time we were moving parts to Java it had all gone through a lesser or greater amount of refactoring; the best design is iterative and emergent, and we had the http://c2.com/cgi/wiki?WhatIsAnAdvancer experience several times over. In the early stages you really can iterate faster in not-java; as the correct design emerges and the codebase gets larger the interfaces tend to firm up, and at that point it becomes more reasonable to port pieces for performance.
> like I said, the only proven risk factor for bugs is number of lines of code.
There's never been a proof that writing code in Ruby WILL give you LESS bugs than in Java just because you'll end up with LESS LOC. I think this is a generic statement that needs to be clarified.
I agree and I will not argue that LESS lines of code "might" give you LESS bugs given that you're writing it using the SAME language (version 1 in Java has more lines than version 2 in Java, maybe because in version 2, the developer gained more experience and can write idiomatic Java and use libraries instead of rolling his/her own). But Ruby yielded less bugs because of less line of code is a marketing speak to sell the religion of Ruby.
Sometimes I wonder why developers aren't forced to just use LISP since everybody in the whole world knows that LISP is super expressive that it MUST resulted in far less code right? Right?
> When I worked at last.fm this was literally my entire job (well, from PHP). You're rearchitecting anyway, creating stable interfaces and putting load balancers in there because those are also things you need to do as you're scaling up. Changing languages is no harder.
I work for a company that has been using Java since probably 2002/2003 (I joined in 2012). Server-side in Java with Client-side in Swing, slowly evolving the Server-side POJO (probably no Application Server), to EJB 2.x (shudder) to EJB 3.x and goes to the cloud we go (AWS). Recently we refactor a certain part of our code and added Microservice written in JAX-RS because we have to integrate with another product suite internally. That's what I called re-use and evolution of code-base: 10 years of Java where some of the code from the past were/are reused and still in production today. (.... but boy those old code aren't pretty, hehehehe).
Oh, I almost forgot the part where we used shell script to build, moved to Ant, moved to Ant + Ivy, and slowly moving to Maven (if we need to write a new microservice, maven by default, the rest have to move slowly).
Oh, here's the best part: last year we moved away from homegrown migration tool to use Flyway, 4-6 lines of Java code to initialize and execute the migration workflow dropped in our old Java code.
So yes, if we had to re-write and re-write and re-write to different languages every time, it is definitely will be harder.
> You can hire the experience - Java is literally the easiest language to hire for (I mean, hiring is still hard, and there are a lot of crap java programmers around, but there is a bigger pool of experienced programmers out there than any other language).
Ops, not devs.
> and you absolutely cannot rely on the engineers who bought the first version still being around when the time comes to rewrite; the half-life of an engineer in a startup is not large.
Thank God it's Java, not PHP, not Perl, not Ruby (I give Python a pass because I'm being nice). IDE helps a lot. This reminds me of Zed Shaw blog about charging a lot of money fixing Rails mess as a consulting service.
> Twitter was the article's choice of example, not mine - and from a business point of view Rails worked really well there
I'm not suggesting that they made a bad move or whatnot I'm just merely debunking the common stories of how small team beat big team (that may have big expectation/big scale yet not focused on solving customer needs) because of the technology/languages. Talent is something else. Tech/Languages/Scaling? sounds like ego problem there.
> Sometimes I wonder why developers aren't forced to just use LISP since everybody in the whole world knows that LISP is super expressive that it MUST resulted in far less code right? Right?
You've fallen for Lisp propaganda :P. If you look at the shootout, Python and Ruby are comfortably ahead of Lisp in the expressiveness stakes.
Really not. This was one of the leanest places I've ever worked; everything we did there was absolutely necessary for the scale we were operating at. I've seen second-system effect in action; last.fm wasn't it. Writing Java will not save you from having to scale horizontally; maybe it's 2x, 5x, 10x faster than a dynamic language, but if you're growing then these kinds of constant factors only buy you a small amount of development time.
> Recently we refactor a certain part of our code and added Microservice written in JAX-RS because we have to integrate with another product suite internally. That's what I called re-use and evolution of code-base: 10 years of Java where some of the code from the past were/are reused and still in production today. (.... but boy those old code aren't pretty, hehehehe).
If you're using microservices multiple languages really shouldn't be a problem. It's not like we rewrote everything; services that were fine in PHP stayed in PHP. We moved things to Java as and when we needed to. If everything's a service (Thrift in our case) then it really doesn't matter what language is on the other end.
And it's not exactly "from scratch". Physically typing out the code is never the bottleneck; most of the hard part of programming is design, getting the correct decomposition of the problem. Porting well-written code from one language to another language that supports the same paradigms is really not that hard, and certainly doesn't mean throwing away all the lessons of the first codebase.
> Verbosity matters for reading and maintenance far more than it does for writing.
I would argue that on average verbosity improves readability. Yes it may take you slightly longer to read the code, but verbosity often results in the code conveying more information or expressing it clearer (or both).
I would rewrite that as "_explicitness_ improves readability". When I read Java code, I rarely have trouble to know what the code is doing (at least at a local scale).
Not all static-typed languages are readable because they're not all explicit. In C++ for example, even the most trivial snippet of code can be obfuscated by all sorts of abuse: operator overloading, implicit calls to copy constructors, preprocessor macros, etc. Scala suffers the same problem, perhaps even worse, doing tons of stuff automatically i.e. in a way that's not obvious by just staring at a code fragment such as an individual method. Organizations that have success writing large-scale code in such languages [I can speak for Google here], typically have careful style guides that ban the bad stuff and are strongly enforced by code review process; but in that case you're not using language X anymore, you're using some "safe subset" of X.
Of course you can't have any high-level abstraction without some tradeoff of maximum explicitness; virtual calls for example make hard to know which exact code is invoked by "just staring" at an invocation. The trick is striking a healthy balance between power and readability. Java is not perfect in this criteria (it errs a bit in the side of caution), but it's certainly much better than any dynamic-typed language.
Just repeating the same thing twice doesn't help with anything. The standard examples of Java verbosity - repeating variable types, getters and setters, anonymous classes instead of lambdas, using the visitor pattern to emulate pattern matching - don't make anything more readable or clearer (indeed many people find the Java version more confusing to read).
What features does Java have that you're saying help code convey more information or lead it to be expressed more clearly? I find that my more concise Scala code usually both is clearer (there's just less irrelevant clutter e.g. braces) and conveys more information (because e.g. error handling with Either and for/yield makes it clear which parts of a function could have errors, whereas with try/catch all you know is "there's a function somewhere in this block which throws").
> Just repeating the same thing twice doesn't help with anything.
I completely agree - but not all (or even most) of Java's verbosity is from repetition. The traditional example of `Foo foo = new Foo();` as repetition ignores the fact that `Foo` will not always be repeated as the first will often be an interface (or superclass) and the second will be an implementation, e.g. `Set<String> set = new HashSet<>();`
> What features does Java have that you're saying help code convey more information or lead it to be expressed more clearly?
My comment regarding verbosity wasn't in comparison to Scala, I was thinking of Ruby, Python, Lua, et al (I'm a huge fan of Scala btw, but the post was on the benefits of Java versus dynamic languages). Anyway to answer your question with a few examples:
* Java's method signature gives me a lot of information, looking at `public int doStuff(String foo)` tells me the visibility, what it will return, and exactly what I can pass it - even to someone completely unfamiliar with the language. Looking at `def doStuff foo` tells me nothing other than how many arguments it takes (if you're familiar with Ruby you'll also know the visibility).
* Similarly when you see `return foo` you know (even knowing nothing about Java) that it's returning `foo` and that `foo` is the intended return value.
* Someone who's never read a line of Java in their life can look at `Map<String, Integer> foo = new HashMap<>();` and know that `foo` is a map (and will most likely conclude it has Strings for keys and integers for values). If you've never coded in Lua and you see `foo = {}` you have no idea what that is (if you've seen similar in other languages you can make a good guess, but you don't know).
A significant amount of the article is arguing that Java for everything is better because the author and his coworkers already knows it. I can make the same argument for Python _for me_. And for my company too; we have a ton of Python developers already, so it makes sense to write things in Python if possible in case someone needs to change or improve anything.
The author also talks about how Java's verbosity is a trivial issue, and in terms of "stuff you have to type", I agree. The point isn't to save a few characters to type. To me, the problem with Java's verbosity is that it _impedes understanding_. The excessive notation required by type declarations and generics and so on are visual noise that distract from what the code is doing.
There are some valid points raised too, such as concerns about Python's scalability, but that's an argument for _choosing the right tool for the right job_, which, while mocked at the beginning of the post as a way to avoid an interview question, is still good advice. For a lot of projects, Python is fast enough to handle the expected processing, has an ecosystem with libraries that handle all of the things the project might need to do, and is portable enough to run on the platforms necessary. For some projects, it fails one of these, and another language may be a better choice. That's okay!
I think the best takeaway here is that it is sometimes useful to see if you can leverage your existing knowledge in one programming language by applying it to a task you don't normally use it for. By all means, write shell scripts in Java, maybe that's really useful! Or maybe write a GUI in Haskell! Transpile BASIC to frontend code!
(For context, I use Python for web development (both small and large sites), scripting, and a few personal projects like a music player or emulator. I did a bunch of Java in college and some internships.)
> A significant amount of the article is arguing that Java for everything is better because the author and his coworkers already knows it.
Far more of the article is spent on arguments that are valid for any compiled statically-typed language. So much so that he feels the need to point out why Java [as opposed to C#, C++, D, Go] in the penultimate paragraph.
Though the lack of noise could also translate to parsing things in my head trying to understand what is happening in this super short code....hence it takes longer to read the code!
Maybe, but what are the examples? "Foo f = new Foo()" takes longer to read than "f = new Foo()". An anonymous class is longer than a lambda and also less readable, as Java folk have thankfully finally realized. "public static void main" does not clarify anything. Getters and setters are the bane of my Java-reading life, because 99.9% of them are the exact same autogenerated four lines, but you still have to read them all in case one of them is different.
Also, there's a huge jump in readability at the point where a method or class fits on a single screen. So if 4 lines of Java = 1 line of Brand X, but it takes me the same amount of time to read 4 lines of Java or 1 line of Brand X - that's still a win for Brand X, because it's much easier to write classes that fit on a single screen.
True! It requires some skill to write concise code that can be understood easily. I think that the required verboseness of Java makes things worse than the potential for excessively-short code does in Python, though.
> There are some valid points raised too, such as concerns about Python's scalability
But if you think about the two python scalability problems :
1) speed
2) programs become unmaintainable as they grow way quicker than they do in java and the like
Nobody's arguing to write shell-scripts in Java. Why are people arguing writing websites that will include more than a trivial amount of functionality in anything but Java ?
(1) isn't really something that's terribly arguable one way or another (In my experience Python is plenty fast for most tasks, but my tasks differ from your tasks).
I question (2) though. Why do you think that a Python program will become unmaintainable faster than a Java program? Is it type errors? Or maybe you think it's difficult to figure out what values are expected in a given variable? Or is it something else?
The problem with verbosity and repetition is not that it takes longer to type the code, at all. The problem is that it creates dependencies which you have to manage by hand.
Changing `Foo a = new Foo()` to `Bar a = new Bar()` doesn't seem that bad... except when you have to propagate that change through the code base. Half of Java's tooling is dedicated to solving a problem that doesn't exist in good duck-typed languages or those with type inference.
Verbosity is also a warning sign for lack of expressive power. If you have a pattern like `if (cmd == "run") run();` in multiple places in your codebase, you want to make it so that changing one changes them all. Java won't let you factor this out easily, but worse, it won't catch you when you make a mistake (better languages will either do first-class functions or pattern matching and exhaustiveness checks).
Note that this has nothing to do with static vs. dynamic; verbosity is a problem that can be solved in many ways, but it is a problem. The author also spends a lot of time equating statically typed with fast; well, there are plenty of very fast dynamic languages.
There certainly are reasons to like Java, but these aren't them.
> Changing `Foo a = new Foo()` to `Bar a = new Bar()` doesn't seem that bad... except when you have to propagate that change through the code base. Half of Java's tooling is dedicated to solving a problem that doesn't exist in good duck-typed languages or those with type inference.
A sweeping change like that is hard in Java, but it's nearly impossible in Python. That is, unless you're willing throw up your hands and assume your new duck looks enough like the old one, and cross your fingers that you don't find out in production one day. With a modern IDE like Eclipse, it's a fairly trivial matter to find all references to the class, navigate call hierarchies and make the necessary changes to adapt to the change in type. In a sizable Python program, good luck. You're pretty much forced to rely on string searches - hope you picked a distinctive function name - or interactive debugging. Ease of refactoring is a huge win for static types IMHO.
I'll be the first to agree that Java-style class hierarchies and duck typing don't mix well, but not every dynamic language is Python. Clojure, for example, is very easy to refactor when it's (very rarely) necessary.
Not saying static typing doesn't have it's advantages – tooling is probably Java's greatest strength – but there are other, equally valid, solutions to the problem.
DISCLAIMER: I write mostly java, at home and at work.
Refactoring goes a lot further than just renaming types. A refactor script _WILL_ rename both sides of 'Foo x = new Foo();' to 'Bar x = new Bar();', so given the right utilities (and if you use java for everything, it's _MUCH_ easier to become an expert at the tools!) this is not any more effort at all.
However, there are refactors for things that are much more difficult in a duck typed language. For example, if I have a bunch of methods named 'execute()' in my code, and I decide that this is a sad state of affairs and ripe for a refactor, I can refactor one of them to a different name and the tools will 'get it right', renaming the right calls (calls into this type) and not renaming the wrong ones (calls to another type's execute() method which has no relation to this type's execute() call). In python, you just can't do that. You'd have to rename all of them, defeating the point.
Similar concerns crop up for 'find callers', or 'add argument to method'.
There are also refactor scripts that are equally possible in both python and java, but which nevertheless require either a lot of manual editing, or an intelligent tool that can automate it, such as 'extract method' (taking the selected code and turning it into a (helper) method, figuring out which variable(s) would have to be passed along to make it all work as needed.
The point is: Duck typing does not obviate the need for refactors. It does make certain refactors impossible to 'safely' automate ('safely' in the sense of ensuring that, post-refactor, the code does the same thing as it did pre-refactor).
As far as 'dynamic == slow, static == fast' being a bit of an oversimplification, yup, that's true. Java _IS_ a heck of a lot faster than python, but that's mostly an implementation detail; you could make a pretty quick python. dynamic definitely does not help, but it can be worked around. Javascript JIT engines are seeing a lot of serious improvements right now, and a large part of it is guesstimating type info. They're getting pretty fast.
In the spirit of the article, though, static typing isn't just a boon for speed reasons (based on the practical upshot that java IS fast, and most dynamic solutions simply aren't, even if they could be with more engineering efforts): It becomes quite useful when you start having to read the additions to your code written by someone else, or rereading your own code half a year down the line when updates are required. explicit static typing also helps with refactoring, which is useful especially when you have to fix or extend your project.
Refactoring goes a lot further than just renaming types. A refactor script _WILL_ rename both sides of 'Foo x = new Foo();' to 'Bar x = new Bar();', so given the right utilities (and if you use java for everything, it's _MUCH_ easier to become an expert at the tools!) this is not any more effort at all.
Ctrl-Shift-R B A R
No, not much effort at all. Just twice as many keystrokes.
I wouldn't even mind the verbosity if it actually gave me some speed improvements, but it doesn't. There are plenty of statically typed languages where you just write x = new Foo() and the compiler will figure out the types for you.
Great, I suppose, but you didn't answer his execute() example at all. I don't care if you do it in vim, emacs, or an IDE, the problem is that in a dynamic language, you can't do it safely at any speed or with any number of keystrokes. Counting keystrokes is therefore completely beside the point.
Counting keystrokes in programming is like counting letters in a novel - the amount of time put to think of something, to discuss it, takes the vast majority of time. Keystrokes used to write something is irrelevant (especially if you type with more than 2 fingers)
And if the whole arguments boils down to Java not having a var/val keyword - yes, that would be handy; but you would then still need tools to figure out what is the type of val foo = calculateSomething();
To parse Foo x = new Foo();, javac has to perform type inference on the right hand side to figure out its type, and then check whether that type is a subtype of the left hand side. Telling the compiler: "hey, trust me, variable x is of type Foo" doesn't make the compiler's job any easier at all.
In that case specifically, no, but in general doing type inference means running a constraint solver over the entire program, which will definitely add some overhead to the compilation time.
One hand position still over the keys and uses common fingers, and is easy for emacs users (Ctrl + Shift + R), versus leaving the typing keys entirely to climb to a command key that's used sufficiently infrequently that you have to look at where it is.
At least that's my experience.
Oh, and more fun. If you're on a modern keyboard, you have to type the function key since apparently volume up and down and expose are more important than function keys.
Long story short: what's faster and 'less' for some, is more for others. And this is why we have options! :D
I don't understand the point. Are you claiming that search and replace functionality provides the same ease of use as an actual rename refactor ?
Foo x = new Foo();
int Fool = 5;
I'm sure you see the problem.
Dynamic languages are great, until the program grows. Then you hate yourself for having picked a duck/dynamic typed language (including Go, btw : programs become unmaintanable if they grow, not as bad as python and the like, but ...).
Still don't understand. Let's take the changes you need to make :
Foo.java
...
class Foo {
...
}
SomeOtherFile.java
...
Foo x = new Foo();
...
Equivalent in Python:
some_file_in_a_library.py
class Foo:
...
some_other_part_of_the_program.py:
x = Foo()
Keystrokes to change the name "Foo", in Java :
1) Position cursor on Foo.
2) Alt-shift-R "Bar" (+ enter)
Keystrokes to change this name, in Python :
1) position cursor on Foo
2) Change to bar (5 or 6 keystrokes)
3) Open some_file_in_a_library.py (couple dozen keystrokes, most people I see do this have to switch to mouse and use that)
4) Change the classname
5) Go through all the unit tests that you should have that test the class (you need 5x more unit tests in Python compared to Java as well, to have equivalent tests), and do the same. Yes, all of them.
Java wins out, by a factor of 3, maybe even 5. Even if the class definition and the usage were in the same file, it would still win by a lot.
Refactoring simply doesn't work reliably in Python. Heroic efforts by Jetbrains notwithstanding, it just doesn't compare.
So I don't see what you're complaining about. Making changes is only faster in Python in tiny programs, where you don't have the problem of interdependencies. As soon as you have some of them, Python starts losing out, bigtime.
If you are prone to having the "if (cmd == 'run') run();" pattern in multiple places, no language is going to fix your copy pasta and the maintenance issues it has. Java absolutely has mechanisms to fix that and factor it out, it just bs to say otherwise.
It's a pain when you are first learning and typing every keystroke, but with a modern IDE (IntelliJ) you don't really need to worry about things like this.
That's why I like Limbo and later Go's implicit typing:
a := Foo():
a now has whatever type Foo() returns. If you change the definition of Foo then you don't have to cascade your type change through all of your source code.
I agree with the author on some level. All of HBase and Hadoop (except for a little bit of native stuff) is implemented in Java.
I found that to be + and a -.
Java is easy to understand and to follow, lends itself very well to large-team development, and performs well in most situations. The alleged verbosity I do not mind. I have tools, and well structured code is easy to follow.
Java (or the JVM really) does have limits, though. What I miss by far the most are simple pointers and access to the RAM outside of the Java heap. Then again I am working on a low-latency database. Yes there are DirectByteBuffers but they are annoying to use, just gimme a struct (some IBM folks are working on a proposal for that for Java).
Everybody in this space who is using Java invents their own off-heap code to avoid heap allocations and the inevitable garbage collections. G1 will make it better, but not eliminate this.
I still user other tools: Python, Ruby, Bash (yes), JavaScript, C/C++, etc, and I disagree with the author's premise. It depends very much on what I attempt to do which language/ecosystem I will use for that.
Edit I: In the end I prefer to versatility of Java over the limits I face with it. Would I write a Kernel in Java: No. At least not with the current JVM.
Edit II: We should not conflate Java with the JVM.
You have to appreciate bombastic statements like this for forcing you to confront your assumptions. "Everything in Java? Even a kernel? That's absurd." you think, and then wonder what makes it absurd, and realize that it could perhaps be done with some modifications, and remember Singularity, etc.
But on the other hand, this is well trod ground. Everything WAS going to be Java. Remember picoJava, the bytecode-native processor? Remember Cocoa Java, for OS X desktop apps? Remember HotJava, the pure Java web browser? These things were tried, and they failed. Performance issues, especially around startup and memory usage. The weightiness of the JVM, what Jobs called a "big ball and chain." The weird foreignness of Swing apps. The generalized misery of applets. Etc.
Great perspective! I don't think 're-implement the world in java' was the point of the blog post. I do follow you're line of thought however. Vala is a Java like language (in the same way C# has a subset that is Java like) that is AOT compiled by translating to C.
Interestingly, it has a few departures that make it very un Java like. For example, Vala uses reference counting for memory management and provides a 'weak' keyword, passing reference cycle management off to the programmer. And voila, no gc (edit: or rather no centuries level of effort garbage collector implementation, with associated performance indeterminism). Another departure is no dynamic class loading.
Point: I use Vala as a proof by example there's a language out there that's statically typed, highly productive, GC'd, and AOT friendly, for which some formulation of "X Everywhere" is not far fetched.
I am more convinced by the part "write everything in one language", and less convinced that Java is a great choice for that language.
On the other hand, if you're going to write everything in one language, you do need a language that is capable of doing nearly everything, and doing it well. And I see how Java is a reasonable choice.
But yeah, I think "pick the right language for the job" (and the corresponding "when all you have is a hammer...") under-estimates the extent that the right language for the job is the one you know best, because you'll be able be most effective in it.
The biggest thing for me is that the tooling around Java makes maintaining large projects extremely easy. Being able to refactor hundreds of files in a few keystrokes without worry lets me sleep well at night. It's certainly a lot faster to get up and running with a dynamic language, but the initial build out is a small percentage of the overall time you are going to spend with a codebase.
I've also built just about everything in Java from HFT algos, to an exchange, to a web server, to thick clients so I have an idea in my mind about how to solve any new problem that comes up.
I think this is the key point in the debate - weighing initial development time against ongoing development and maintenance. It's something that's hard to grasp until you've been around for a while working on real-world large-scale projects. And it's a hard thing to get the sense of when you're in school, writing throwaway code that doesn't last past the end of the semester.
When you understand this, then you can make an honest assessment - is it really important to get the first build out that much quicker? Sometimes it is. But I think it's overemphasized. The first one to market doesn't always win. And the shift from new development to maintenance happens quicker than you might think.
First to market has never ever been about using a dynamically typed language. Getting the ideas from talk to concepts, testing, bugfixing and marketing takes vastly more time than actually developing the code. So while Python might enable me to show my prototype on Monday, while that Java version wouldn't be seen until Friday, there still is quite a lot of time before you can say it's properly released.
Where these "fast" to develop languages shines are throwaway prototypes. For some people their ideas flow out much faster with dynamically typed language. But it is all too well known that even though the manager said you could throw it away, they change their mind because "it's basically finished, right?".
That said, you are spot on. Initial development is likely not where you want to focus at all, for any kind of project that needs to be maintained for more than a few months.
If you're actually using good tools (Something like IntelliJ or Eclipse, and something like Maven or Gradle), and you use sane variable and function names (business oriented instead of tech oriented) verbosity is one of the worst arguments against Java.
The verbosity, static typing, etc, of Java contributes information to the "next guy" about developer intent and is incredibly valuable.
I completely buy the idea "write everything in one language", even if I do it with a different language for completely different reasons.
In general I think "use the best tool/language for the job" and anyway any tool/language will have pros and cons, nothing is perfect.
My context is I was a big ECMAScript fan, then I moved to use something called ActionScript 3.0 and there I just found the "right balance" between verbosity, correctness, speed, etc.
That's the work part, I use AS3 and AIR to build mobile app for iOS/Android.
Then there is the hobby part, in 2006 Adobe open sourced their ActionScript Virtual Machine (AVM2), I started to work on it (OSS project RedTamarin) in 2008 because I had this silly idea "it would be fun to run AS3 on the command line".
So, few months ago, with a not too bad release of this RedTamarin project, in the spirit of "use your own dog food" and trying to push the limit of what can be done with this open source project, I kind of decided to use only AS3 for all development, either work or home.
I don't do that because I think it is better or faster, but mainly to see how much I can reuse in code and logic, and if ultimately it make things easier for me (as any dev I'm lazy).
The result is quite interesting, so far I can run AS3 in shell scripts, as server side CGI, as command line tool, and tons of different use case I would have not necessarily explored if I didn't forced myself to use the same language for everything.
My point here is the same way you can learn a different programming language every few months/years to learn new stuff, there is also a value of forcing yourself to use only one programming language for everything.
In my case it forced me to explore some context deeper instead of taking them for granted, sure some ppl could say you waste your time because you're reinventing the wheel, but I would argue you learn a lot more when you try to know all the little details that make a wheel works :).
and yeah it's kind of why I'm doing that,
AS3 is for me a good balance
as a side note, the way redtamarin is implemented
you have access to almost all POSIX C functions from AS3
which can also be seen as a "Friendly Dialect of C"
First of all, I want to say that if you like Java, and know it well, and believe it to be the right tool for your particular application, that you should absolutely use it.
> That Java is the right language for all jobs. (Emphasis his.)
> The advantages of C and C++ [...] don’t apply to my work.
So, choose the right tool for the right job.
As for the examples given:
> At one company I wrote a simulator that allowed me to run my Java services without a fully-functional site. (The unit under test is Java, so it makes sense to write the simulator in Java, rather than Javascript)
> My partner Dan Collens suggested Java [for a log parser], since it’s right there and we know it and it’s fast. (The log parser is used so often that the amortized opportunity cost of developing in Java is more than paid off by faster processing, therefore Java is the right tool for the job)
> And finally, I went to write a simple program that put up a web interface. (This is something the author has done many times before and knows how to do well in Java, and his primary goal is getting it running ASAP, therefore Java is the right tool for the job)
I still think you should choose the right tool for the right job. It just happens that the author's work is constrained in such a way that Java turns out to be the right tool in most, if not all cases.
Honestly, though, I would rather choose the same tool for a job each time by deciding that it's, by merit and virtue, the best tool for the job, rather than relying upon the author's silly heuristic.
This is the correct response to this article. He makes a big deal out of saying he doesn't need to "choose the right tool" anymore. But then later, he feels compelled to qualify that Java is the right tool for him, which sort of invalidates his former point.
In other words, I viewed this article as a large waste of time. Nothing has been added to what is already conventional wisdom.
It's not so much that Java is great at everything. It's more like it doesn't suck at anything. Every other language has, somewhere, a deal-breaker for some particular use. I've not found one for Java. And Java's biggest downside, frankly, is that it hasn't attracted fresh young talent in a while, so it doesn't have really hot frameworks and libraries.
While I do think Java is great I think that's an exaggeration, I'm sure there are quite a few deal-breakers for particular uses. Personally I've opted not to use Java before because it cannot compile to a self contained native binary.
Java projects can be compiled to a self contained native binary using http://www.excelsiorjet.com/ (though this is a proprietary tool, with a gratis license option for non-commercial projects).
You will be excited to learn about gcj, then. The Gnu Java compiler compiles to native code, but it's currently not maintained, so newer Java features are out of reach.
You will be excited to learn about gcj, then. The Gnu Java compiler compiles to native code, but it's currently not maintained, so newer Java features are out of reach.
gcj has been abandoned. It was last updated over 5 years ago. It's not clear to me why you would even mention it.
I'm a software developer that primarily uses and likes Java, and the lack of a good and free ahead-of-time compiler for Java that produces native binaries is what I miss most in the Java ecosystem.
There's Avian. It can produce standalone, compact ELF files that have no dependencies. It's not an AOT compiler though. The problem with AOT in the Java ecosystem is quite a lot of modern frameworks and the like have ended up relying on the ability to synthesise code at runtime. Android has put a check on that kind of behaviour but it's still there.
There's also Excelsior, which is an AOT JVM, but it's for Windows only.
I agree that a really good AOT JVM would be very nice. It doesn't necessarily imply better performance however. I remember when GCJ compiled Eclipse for the first time, lots of people were surprised that it didn't magically fix every performance problems. GCJ engineers view was "HotSpot is an excellent compiler and it will take a lot of effort to beat it". When Sun Java became open source therefore, a lot of the incentive to develop GCJ disappeared. It was always primarily a licensing project not a performance project.
There's also Excelsior, which is an AOT JVM, but it's for Windows only.
Unfortunately, it's also extremely expensive. That's not to say it isn't worth every penny in some situations, but I've gotten kind of spoiled by free development tools for personal projects. I'm glad the days of spending hundreds of dollars for things like C compilers are long behind me.
I agree that a really good AOT JVM would be very nice. It doesn't necessarily imply better performance however.
For some application domains, I would be happy to trade speed -- and even features -- for the ability to create a native binary with no dependencies.
This is one area where I find the Go programming language interesting. I prefer Java, but the lack of a good and free ahead-of-time compiler for Java that creates native binaries with no additional dependencies is a killer feature for some situations.
IMO, being tethered to the JVM is both its greatest strength and its greatest weakness. The JVM really is a masterful piece of engineering, but it is optimized so heavily for the server that any use case that deviates requires huge hacks to get what you want. For example, running a JIT on Android was so sluggish that Android had to design an entirely new runtime(ART).
The JVM runs very well on the desktop as well as the server. I have to point out: Android runs Dalvik, not the JVM. But here's the point: Java isn't tethered to the JVM. Use the JVM for server, desktop, Use ART or Dalvik for Android. Use Jikes, Excelsior Jet, RoboVM or other VMs, compilers for other targets. The limitation you raise doesn't really exist.
Well, Dalvik is a JIT and ART can also do JITC and is designed for newer devices. So not sure that's a great example. The main reason Android doesn't use the HotSpot JVM is memory usage and licensing, I guess. The JVM class/jar format is very inefficient in many ways. On the other hand Dalvik is a very weak JITC. ART is stronger because it has more time to work and is, frankly, better engineered. Dalvik had a lot of problems even quite late in its lifecycle with things like lock inversions and strange method count limits, etc.
The 'Hello' program there takes a little over 100 ms for me. I guess my computer is even less of a powerhouse than the author's.
FWIW, the Python equivalent takes about 30 ms on my machine. So, you pay maybe 70 ms to use Java. I don't think many users will notice an extra 70 ms on their command line.
Java's notoriously slow startup is really about the slow startup of software written in Java. Application servers are probably the worse offenders - how can it take a minute and a half to start a fancy webserver? What's it doing in there? They've got a lot better, though; the current generation of app servers start in one or two seconds. Not that anyone cool uses app servers any more anyway. Big bloated GUI apps also deserve some shame here (although i will forgive Eclipse, because i like my IDEs with some meat on them). Language platforms like Clojure and Groovy also manage to take their time, but then they're doing some pretty amazing stuff, i suppose.
When did you last try it? Startup time was optimised heavily some time ago and nowadays I don't notice any real difference unless I wrote some toy app and used "time". The JVM starts fast enough that you can write command line utilities just fine.
It is certainly substantially better than it used to be, but it is still pretty far away from an AOT compiled native executable. And forget it entirely if you are running Clojure or Groovy code.
The class of tasks for which Java's startup time is an issue is very very small. I wouldn't use it for a device driver because of resource issues but there aren't many command line commands where 0.08s is an issue.
So what? For most problems there are fast, well-designed libraries available with idiomatic python interfaces; why would you care about the implementation details?
The Oracle one, aka the one production Java code is usually deployed on. I am aware of several of those research projects but they're, well, research projects.
Even if the JVM were fully implemented in Java, the OS most likely wouldn't be. Even if it were, the CPU microcode almost certainly wouldn't be. At some point your Java will be running on something not-Java, even if that thing is "logic gates". But it doesn't matter - just as the implementation language of the libraries you use in Python doesn't matter.
Some good, some aren't, some used to not work with Python 3, some still don't work with Python 3, some reinvent the wheel died due to not being popular (sql object, pylon, turbogears), some looked relic and not worth to learn ( plone, zope).
Like the article said, it's fun and quick to hack in Python but just ain't everybody taste... especially seeing the age and the quality of some of those libraries.
I really wanted to like Java because of the ecosystem and the JVM, but there ARE a few warts that you will face everywhere - verbosity is one, all the Spring stuff using annotations to wire up dependency injection and AOP and whatnot is another.
Scala has the whole JVM ecosystem, static typing and forget about DI/AOP/OOP patterns. Feels like best of both worlds for me.
I've never been a big fan of Spring so I was pleasantly surprised to discover Dropwizard which includes the tools you've mentioned, a few others, some best practices, and a little glue.
80% of the problems with java as it's usually written are bad policy rather than fundamental language problems. But there are real cases where language limitations mean you have to either use an unpleasant framework or write unpleasant code.
Jersey's annotations are pretty nice, but they're still annotations, not really part of your code. You can be bitten by silly errors like an implementation's annotations not quite matching those on its interface, and when (as is often the case) the annotations get repetitive for a group of similar services, there's no way to factor the common part out. In Spray I can write route definitions that are just as neat as the Jersey ones, but it's plain old code which is an enormously powerful concept; a route can be refactored just like any other code.
Guice is similar, e.g. declarative transaction support; better than managing database transactions by hand, but annotation-based proxying is a bit "magic" and confusing to debug. In Scala I can use a monad for transactional operations; the code (using for/yield) is almost as effortless as annotations, but operations which use the database show that in their type and the type system enforces that my transaction boundaries are in the right place. Even more importantly, refactoring in the normal way is safe.
(Also e.g. the lifecycle features in Spring are really valuable (and virtually impossible to do without annotations in Java, at least pre-8). In Scala there's scala-arm, which achieves the same thing in a monadic way, with the same advantages as doing that for database transactions. And since the same abstractions are used in both cases, you can write types and helpers that work with both "database operation" and "requires lifecycle-managed resource")
So here's the thing about annotation and Jersey, I believe you can annotate the seralization of return type once at the top of your resource class, the rest, like http verb, needs to be repeated unless you take the convention one more level up a'la Rails. But that's Rails, a web framework that people said does not fit for microservice. Sinatra is.
But if you take a look at how Sinatra (or Rails) serialize the returned object, you notice the duplicated code. Especially if you want to return both JSON or XML based on the request header. To add to this, both frameworks do this serialization as part of the code logic that you have to write, instead of slapping annotation once...
Let's take this further: exception mapping to http response code. In JAX RS, you can map application exception to certain WebApplicationException with specific http response code, I believe you have to handle them manually in Sinatra. You would have to catch the exception and convert it to the intended one per method on your controller.
> But if you take a look at how Sinatra (or Rails) serialize the returned object, you notice the duplicated code. Especially if you want to return both JSON or XML based on the request header. To add to this, both frameworks do this serialization as part of the code logic that you have to write, instead of slapping annotation once...
I can't speak for Sinatra, but in Spray I'd just write a directive for this - maybe it exists already, but if not, it's a couple of lines - and then I can use it just like any of the built-in directives. And this is a perfect example of why "just code" is so powerful. Jersey is a very well-designed framework and I'm sure you can find examples where the built-in Jersey thing is better than the built-in Spray thing. But no framework is perfect, at some point you find yourself having to extend these things - and in Jersey's case, IIRC once you want to write your own annotation you need a magic .service file containing a class name to use to interpret that annotation. And then the only way to pass dependencies to that processor is by static global variables. Good luck refactoring that, and don't expect to be able to use hot code replace when debugging it. And good luck remembering how the mechanism works in six months' time. "Plain old code" has a lot to recommend it here.
> Let's take this further: exception mapping to http response code. In JAX RS, you can map application exception to certain WebApplicationException with specific http response code, I believe you have to handle them manually in Sinatra.
Again, trivial in Spray - I do my error-handling with Either and then I have a meta-marshaller that knows what to do with the error case. Better still, error handling isn't a special case - I do exactly the same thing if I have async code in my methods (can JAX-RS handle Futures? Can it handle a different kind of Future from a non-standard third-party library?). I can do exactly the same thing with a database-transaction monad, and then I can have session-in-view but in a principled, safe, zero-magic way. I can do the same thing to e.g. show debug traces if a special header is present - like Jersey's dynamic choice of serialization format that you were so impressed by, but it doesn't have to be built into the framework, it's just code that I can write myself.
I've been using Jersey since 2010 and I have never need to write my own annotation. Maybe I'm lucky enough that Jersey fills my need perfectly and maybe you're right that once I needed to write my own annotation, I may run into a bit of trouble (though some people do write annotation only to be consumed by reflection, hence bypassing the service file) but I guess... that's like.. what... 1-5% extreme use-cases? Like... LISP macros that makes programmer reached nirvana or something?
But in my case, Jersey fills my need without me writing low-level REST code (dealing with exception to HTTP status code, marshalling objects to different formats) embedded in my controller/business logic.
> I can do exactly the same thing with a database-transaction monad, and then I can have session-in-view but in a principled, safe, zero-magic way.
You sound like programming in another level higher than mine. I applaud that. I'll revisit Spray/Scala _when_ I found a definitive use-case for this. For now, Java seems to fit the bill for pretty much 99% my use-cases and fit my taste as well (less low-level code stuff because it is built-in the framework that is well-architected/well-designed so that I can focus on business logic code).
> You sound like programming in another level higher than mine. I applaud that. I'll revisit Spray/Scala _when_ I found a definitive use-case for this. For now, Java seems to fit the bill for pretty much 99% my use-cases and fit my taste as well (less low-level code stuff because it is built-in the framework that is well-architected/well-designed so that I can focus on business logic code).
A lot of it is just being able to track things in the type system that you wanted to track in Java anyway, but it seemed too hard. I mean, I've worked in Java codebases where it would have been very nice to see which methods accessed the database as part of their type. I've even seen one that used a kind of Hungarian notation to express this - in fact if I can point to a single place that set me on the road to Scala, it's http://www.joelonsoftware.com/articles/Wrong.html . Because I read that and then thought: hang on a minute, why not just make whether a String is encoded part of its type-type, the type that's enforced by the compiler?
Ditto. Spring feels like "the worst of Java", while the exact combo you list above is some of the best and the set I reach for. Jetty is showing its age a bit right now, but it's so much nicer than dealing with Tomcat.
I think the difference is that stuff is less hastily cobbled together. People use additional libraries because they add value, not because they paper over ugliness and holes of existing libraries.
Scala feels "designed", while Java feels "evolved".
That even though Scala is better designed than Java, without Java's cruft earned through evolution, most companies will keep on searching for Java developer skills.
C#'s one of the most versatile languages which can target most of the popular platforms, e.g: iOS/Android (Xamarin), WindowsPhone, Windows, Linux, OSX, Silverlight, PS4, XBox (announced), Unity3D and NaCL.
C#/.NET's biggest weakness of sub-optimal cross-platform support should also be resolved in the near future now that .NET's compiler, core runtime and class libraries are OSS and with Microsoft announcing support and plans to release official distributions for Linux and OSX - so .NET will finally have multi-platform support of a single code-base resolving earlier issues or running .NET on OSX/Linux due to different impls.
My version would be "what he said, but choose any well-supported statically typed language, particularly one with decent type inference, since that gets you a lot of the convenience of dynamic typing without all of the very many runtime-error downsides".
C# has replaced scripting languages for me. It might be faster to write a python program to do something simple, but the amount of time saved on such small things is minimal.
As soon as a project gets large, it outgrows the scripting language anyway.
Java is perfect also for client side.
We have a client app (a complex VoIP softphone) with different codebase for all platforms (C++ for windows, java for android, ObjectC for iOS). Right now we are in the way to reduce all this in one single codebase written in Java and the user interface in html/css/javascript, so the user interface is always running in a webview.
-Java for windows desktop (there are pretty installers which automatically download and install the JRE if not present)
-Java for MAC and Linux desktop (same as for windows desktop. the same installer tools can generate also Linux and MAC packages)
-Java for Android (with a very minor conversion for which we already wrote a converter app)
-Java for Web (currently using a java Applet which works perfectly. We plan to use GWT to transform to JavaScript in the future)
-Java for iOS (will see)
This way we plan to cover 99% of all devices with java only (with some minor transformation for some platforms).
What is your opinion on this? I am in the right direction?
This is horrible, but not because of the Java part — it's the webview that puts your desire for a single UI technology stack ahead of user's desire for a decent UX.
On mobile devices the issue is Oracle dropping the ball and leaving to third parties (RoboVM, CodenameOne,...) the work of providing JVM implementations.
This on iOS, still no story on Windows Phone, which actually happens to be over iOS on some European countries.
I am using java 1.5 features only :)
Actually i never understood this spike about language features. For me the focus is always on the problem what i am trying to solve (VoIP in this case) and never the language. Actually any language would do for me in which i can apply some encapsulation for better code management (think of java classes). The rest doesn't matter :) I was started with C and then C++, but for me C++ is still C with classes :)
>i never understood this spike about language features
You should really read about the Blub Paradox. Imagine writing all your coded in assembly. It would suck because assembly is an inferior language To those you mention. Now imagine working in a language that is higher level than what you've (yet) been exposed To.
We are working hard on making RoboVM as mature as possible. There's already plenty of applications on the App Store using RoboVM. Happy to talk if you need more info for decision making. Ping us at hello@robovm.com.
Unless you want it to look totally native client-side. The extra effort required to make a Java app look platform native is something that (near as I can tell) no one has ever attempted.
The trick is to use the Java SWT library rather than Swing. (In my case I also added a few platform-specific hacks such as having a big toolbar at the top of the main window in OS X but not Windows).
IntelliJ has historically looked pretty native on MacOS X. At least until Yosemite pointlessly reskinned Aqua to look more ugly. Now I find myself quite happy that IntelliJ is not a native Mac app because I preferred the old look anyway :)
You can make the apps look native, if you really care. But in an era when web apps are the shizzle why would you even care? No web app even tries to look native. They just do their own thing and nobody cares.
For development speed and code maintenance, this is ideal. Your team only needs to master one language and its set of tools and libraries.
You are pinioned by this choice on some practical levels. Mainly, some users and use cases demand the speed and lightweight user-experience of native apps. The native-vs-[java] experience is typically quite noticeable on all the platforms you've mentioned -- desktop, web, and mobile.
Right now I am working on the windows desktop app. I can tell you, that you don't notice any difference at all in speed (I also wrote a simple "container" app in native c++, so it is also loading instantly ..there is a ~2 sec delay to load the JVM, but meantime the user already sees the UI)
I've mostly embraced the JVM (as opposing to hating it), but I find myself reaching for Clojure a lot more than Java (although I have an Android app that I'm tinkering with). I find that an IDE helps (I use NetBeans for pure Java), but whereas I can hack just about anything in Clojure, Python or Go without much hassle, Java slows me down for some reason - I suspect it's the humungous class hierarchies and the time required to find whatever I need to accomplish simple tasks.
Once you get used to working in Java (and have a relatively stable toolchain you can depend on), it's realistic to develop applications in Java almost as quickly as Clojure, though complex aggregations that Clojure makes one-liners will often be vastly slower to develop.
IntelliJ makes a lot of things easier as well.
When it comes to Java, you just need to really get familiar with your tools before you can be as productive, but once you are you can move quickly. Using Java 8 doesn't hurt either, streams are pretty decent.
This whole "expressive vs. performance" is a false dichotomy. Languages like Scala and Haskell are performant like Java and expressive like Python. Not to mention the work being done on JIT compilers by V8/HHVM/PyPy that are helping to close the performance gap for dynamic languages.
(Although the Google Inbox team didn't produce a Windows or OS X native client, there's no doubt that such a client could have run the java code shared between Android, iOS and Web)
Java doesn't seem too popular here but used right it can work pretty well, imo.
For instance, I use Java for the backend of a name generator web app. It's astonishingly fast and displays results almost instantaneously despite running a good amount of backend calculations.
This speed became an issue because you'd push the go button and the names would update - but it seemed like nothing happened. So I ended up adding an artificial delay twice (the first time it wasn't enough of a delay).
On the other hand, its structure and methods can at times be frustratingly complex.
In real-world benchmarks in a real app I have tried to make Clojure slower than Java. I can't. In rare cases Java will beat it in insignificant ways in insignificant amounts, but I found that Clojure sometimes beats it in significant ways because of the runtime's tendency toward laziness. Furthermore, Clojure is a very dynamic language that can leverage every library Java has plus all its own.
As a result I will not program in Java willingly. There's just no reason to do it. Not with at least one language that's far better in real, quantifiable ways. There are other languages that run on the JVM that could tell a similar story. Unfortunately those are not Jython or JRuby.
Its hard to explain, but I feel like Java would be a better choice for doing something like audio decoding, while Clojure is orders of magnitude more productive to prototype a webapp.
You have to admit that for coders, the joy of writing helps a lot for job satisfaction. I write both Java and Python (for very different applications) and I just always feel like Java makes it hard to write anything elegant almost on purpose. The proliferation of huge frameworks and FactoryFactories clearly doesn't help.
I think you can underestimate the value in actually enjoying writing - I'm just more motivated every day I can write elegant python code. Conversely every day I spend fighting Java for an elegant solution and winding up inevitably with something a bit half-arsed because of some limitation in the language I just feel grumpy.
I'm of two minds on this. Certainly it's important people find enjoyment in the day-to-day reality of their job. Unhappy people don't write good code in any language. But I honestly do thing people can have too much fun writing code. We've all fallen in love with something we've written even though it might not have been the simplest or most understandable or idiomatically sound.
Writing Python is fun. But that joy can cloud your judgement, and if we are to consider ourselves professional, we have to look beyond just that and make decisions based on our employers best interest. Sometimes that might be Python, but in my experience, quite often that's boring old Java.
The problem is that one guys "Joy Of Writing" rapidly becomes the next guy's "Torture Of Reading", and with enough of a time-interval those two can be the same person.
I feel Python is good in this regard compared to other interpreted languages. There's a lot of emphasis on "Pythonic" style which you tend to pick up as you learn, so people are discouraged from excess magic (Explicit is better than implicit) and the syntax at the very least lends itself to sane formatting (especially with PEP8). Personally I've rarely had any true WTF moments reading either my own code or code from (reputable) OSS projects.
You might not need factories, but they get foisted on you anyway. But the proliferation of "programming patterns" in java I think is symptomatic of a basic user-unfriendliness in the language.
Off the top of my head I can think of three Patterns just for creating objects (Factories, DI, Builders) - the fact that these are even required, that object creation isn't self evident, suggests there's something wrong in the language design
Having literally deciding to learn java last week for no particular purpose other than having enough understanding to be able to comprehend our software (which is written primarily in java) and prevent brain deterioration, I'm encouraged by the fact that the comments in this thread (so far) don't appear to be very negative (like when reading about php).
While I did buy a book, I wonder if anyone has any suggestions on a good java beginner's book assuming someone has "prosumer" programming knowledge (shell programming, some perl, some php, sysadmin skills and so on). Suggestions?
Welcome to the Java world! Like some of the comments so far I think the Java world is actually a pretty cool place to be right now, the language and approaches are becoming a lot less verbose. I blogged about some of the best Java books, hope it'll help you out! http://scalabilitysolved.com/dont-hold-back-your-java/
"Learning Java" http://chimera.labs.oreilly.com/books/1234000001805/index.ht... seems to be a decent review of the language and ecosystem, although it doesn't cover many of the new technologies in common usage (many of which are mentioned in this thread).
Question though. The first book you listed (which got excellent amazon reviews as well) was published in 2008. Typically I've been biased into thinking that a book had to be somewhat recent. Obviously this isn't the case here though. (Do you agree with that in some situations btw?). I would have never purchased this book if you hadn't pointed it out so thanks it's in my cart.
Effective Java is a solid choice, and a lot of the advice is still relevant six years later :) Also, JCIP is a go-to if you want to get more than a passing handle on concurrency in Java.
Agreed, the java books I listed still provide more value to my core Java than more recent books. I do the majority of my Java work now in the Play framework, when I use a new framework or library blogs and stackoverflow are my go to resources, for a deeper understanding of the library then those books are the way forward.
I think that the argument about verbosity is a subtle red herring. It's not that you just have to write slightly longer words to do the same thing. It's that you can't do the same thing at all because the underlying constructs of the language are lacking in key powers of abstraction that make it easy to simplify the problem you are trying to solve. You end up inventing whole class hierarchies and patterns to emulate things that are either just built into other languages or are easy to achieve because they offer more powerful language features (like reified generics, etc.). Java 8 helps a lot, but there are still fundamental weaknesses.
Having said that, I'm still a fan of Java. There's no other language that I can sit down and reliably navigate through someone else's code in as easily - and that comes partly because it's powers of abstraction are so limited.
I've been writing Python and Java(Android) side by side for a few months. I feel that for all the advantages of initial speed that python offers it takes a lot away. Especially in large projects. I spend a significant amount of my python time trying to understand Types, and if those areas are not covered by tests then I'm Fked, I'll have to spend hours trying simulate the exact conditions of how an error occurred.
Don't get me wrong, I love python, but writing python requires a lot of restraint and experience. Novice programmers who build a python code base just screw things up, especially those who don't yet understand the value of readability and maintainability.
I'd much prefer novice code on Java than on Python.
The headline does not match his conclusion at all, in my opinion. What he's trying to say is that "dynamic scripting languages are slower and more error-prone than compiled, statically typed languages". And to determine whether or not a scripting language is ever a good idea from 3 or 4 examples does not seem like a good idea. E.g. Lua seems to be a pretty good fit for the WoW UI scripting stuff and EA used Python (apparently successfully) for their Sims 4 scripting (sorry for it both being examples of games, those were just the first that came to my mind :D)
That's where Go comes in very well in the interviews assuming interviewer also knows or can understand Go. It has short and precise syntax and the code usually doesn't need explanation.
You know, one of the things I notice about Java adherents: they think programming is hard. There's this weird conservativeness to their culture. The only times I've worked on Java teams, I felt like the biggest hurdle was convincing people that things could actually be done. Its like they're convinced that every programmer sucks.
I don't even hate java the language. It's far too mediocre to even bother to hate. I just dislike java the community. It's so depressing.
> I’m even taking this to an extreme and using Java shell scripts.
Having a strong Java background, it is a pleasure to write Groovy for shell scripts.
I like the blog post. Whenever I looked into other languages/platforms, I found the "tradeoffs" of Java (as pointed out by the other languages/platforms) to be less important for me. Java/the JVM may be evolving slowly. But it evolves and does it in a reasonable way (JCP, frameworks).
Speaking of - how is Groovy doing these days? I looked at the Groovy webpage and I saw ads splattered here and there - never a good sign, I also see that the mailing lists are pretty quiet. Is Groovy dying?
The site at groovy.codehaus.org doesn't mention anything about the new site (actually www.groovy-lang.org). Until it does the new site is unofficial and just one of the 5 despots at Codehaus trying to grab control of the product away from the other 4 despots there. That despot has tried other tricks like soliciting for subscribers to his weekly "news mailout" which is mainly links to tweets mentioning Groovy.
If an old site for anything (here, groovy.codehaus.org) doesn't mention it's moving to a new site (here, www.groovy-lang.org) then I question what's going on. As for your link, it's a link to a personal blog and not an article on the Codehaus Groovy site so it's just as unofficial as the supposed new site for Groovy.
Of course there are those two projects everyone mentions, Grails and Gradle, but I would say it's more correct to describe them as the only two niches where Groovy is actually used a bit, it's not like Gradle and Grails are just "flagship products" of a greater ecosystem.
For both, there are already better replacemens available, so I don't think they will grow much in the future.
It's a stretch to say that Gradle actually uses Groovy. Groovy 1.7 added a "DSL" into its parser whereby we could omit parentheses in function calls. Gradle uses this facility for its CSS-style syntax.
In theory, we can drop out of the DSL to add Groovy code (as you can with Leinengen to add Clojure code, etc etc) but in practise virtually no-one does that. I've checked the Gradle build scripts for some large open source projects, even Groovy's own build scripts, and nowhere have I seen anything other than the DSL syntax used.
Gradle 2 brought the facility where you could configure a build using any JVM language via an API, and now Java 8 has lambdas I suspect this facility will get used more, and Gradle might even replace Groovy with a custom lightweight DSL for builds not requiring extra programming.
Up to a point - I found the static support was quite buggy and I got the impression not many people were actually using it. Has it improved in the last few years?
There are not many technical reasons for not to do that (like the speed of invokedynamic). It has been a consideration for at least one project I was part in.
Everything in Java? Thanks but no thanks. I understand the author's point, but he's choosing the wrong language. Does the perfect language for this purpose exist? No - sorry. I've been charmed by Go lately and replacing python, small C/C++ and shell-scripts with small tools written in it. It has great potential for services and small tools and has a surprisingly large amount of libraries available for it given the language's age. But would I say Go is perfect for everything? Hell no - but it happens to be pretty good for what I need.
My view of Java may be a bit biased, since I also tend to look at things from the sysadmin pov nowadays. I can only tell that I never disliked Java until I had to take care of the monstrosities the Java developers bring to life, and mind you - I started out as a Java dev back in 2000.
The main issue I have with Java is the JVM and memory usage and leaks. No matter what people claim - no memory leaks in Java is a fairy-tale. We run both custom C++ and Java services (about 50/50) on a few hundred servers - and I cannot find a single issue in our ticketing system related to memory problems with any of our C++ services. Java services? Every. Single. Week. When I get an alert some JBoss unexpectedly died or became unresponsive - "java.lang.OutOfMemoryError" is most likely going to be the problem. A lot of those are permgen space errors, and yes you can try all the "fixes" like increasing the permgenspace, permgensweeping, enabling class unloading, ... but these don't always fix the problem and slow down your services. Every time this happened in our own services, this had to be fixed by our developers. It takes weeks to locate the problem, and you end up deploying new versions, upgrading JBoss, JSF, Bouncycastle, ... whatever.
can you talk about your jboss configuration ? We are thinking of building our API stack in java and are considering wildfly (undertow). Honestly, you are the first person who has talked about problems in Jboss and would appreciate some more info.
The problems aren't really JBoss related. I have very little problems with Wildfly itself. It is a clear improvement over previous versions, I had some problems with v7 which required me to upgrade the JSF modules, otherwise JBoss would suddenly die (in a crash & burn way) with a certain application we had.
It's mostly the "memory is not an issue" attitude most java devs have. It's not JBoss specific, we also have some services written in pure Java suffering the same problems - but the majority of the Java apps run in JBoss here. Stress tests in test/qa usually don't bring up the issues I've seen, which sometimes only occur after weeks of running flawlessly with production-grade loads.
The 'fix' is then running the critical apps twice behind a load balancer, waiting for one of the 2 instances to die (for logs/memory dumps), automatically restarting them - and hoping they won't go down simultaneously. Truth is - memory management in Java is HARD. When problems pop up, apparently finding the source of it is very difficult. I can't count the times I've heard "we think it should be fixed now", only to be confronted with another alert that the service died again a few weeks later. If it was one service we'd run, it would be fine, but we run quite a few more - resulting in weekly interruptions, tickets, sending of memory dumps to developers, convincing them - again - that it is their problem and not mine, ...
So well - I'm sick and tired of Java. The only thing worse to deploy and manage are Ruby apps. But that's a personal opinion.
The article could be appropriately titled to reflect this wisdom: solve every problem in whichever language is your strong suit. It's not always Java, and arguing that Java is the one-size-fits-all would earn you few friends. For web services the importance of the language is diminishing with solutions such as cache, messaging queue, etc. I'd go on a limb to say getting your cache right is the most important web service optimization.
All statements of the form "it's relatively faster to write programs in language Y than language Z" are incorrect because it disregards important parameters such as programmer experience with languages Y and Z, and whether or not it's a comparison between 2 different programmers.
Also there are some performance gains that only pay off at Twitter or Facebook scale [1]. Sometimes shaving milliseconds costs time but rakes in little to no benefits.
It's easy to make python faster, you have PyPy, you can even program everything in python and then make a simple C code for the bottleneck and wrap it with python.
Php it's another example, Facebook uses php and it made changes to its compiler in order to make it way faster.
So bottom line, if people feel better writing in Python let's write Python and improve it to make it faster.
The problem with 'use the best tool for the job' is that everyone's 'best tool' is selected from a relatively small pool. The choices for some use-cases have a multitude of similarly worthy choices. Thus, not likely really the best available. Just another subjective choice.
That said, I don't understand the obsession with 1 language to rule them all that the Java and Javascript crowd seem to share. I do understand having 1 go-to that you reach for to build projects. Something broadly applicable like Java, C# or Python.
But shell scripting in Java? Seems a bit extreme, I'd never bother. You can pull out a Python/Powershell script that does whatever you're trying to do and do it much easier and faster. There's a reason Windows has C#/Powershell, and Linux has (as an example) Java/Python.
I'm thinking "Node.js for everything." It's way more fun, more productive, and runs small and fast. Forget threads. I too used to believe "Java for Everything." Over it. Write microservices in Node. Build front-ends in Angular. Talk JSON.
No no, not Java for everything. I know Java, use Java, and don't hate it. Some of the best tooling available (similarly C#, but .NET isn't my thing.)
Here's my issue: no matter what problem you try to solve the solution looks like Java. I want my solutions to look like my problem.
Static imports go part of the way there, and if you're good at naming and architecture, the learning curve for any particular system remains relatively low. It's a hack/sugar, but it helps.
But that's about as far as you can go using only stock Java, e.g., no syntax extenders, no byte code treachery, etc. AOP can help, but everyone has to be aware of it, and comfortable with a system designed with AOP from the beginning.
I read and liked your post. I like you love python but have to deal daily with Java at work and have the same kind of thinking. With the age, I guess that what matters is the result and not with what it has been built. Of course I like experimenting with new technologies but I have abandoned to spend energy and time in church battles because in the end you realize that you can very often answer a problem with your usual tools in computer science at the moment.
Anyway I liked your java_launcher trick and would like to benefit from it if it is freely available of course.
However I could not find it in the teamten repository ?
Thanks for letting me know.
I like how the author made the point about the commenting. I never realised it until I started my work training at a big company. I'm reading my colleague's C# (ASP.NET MVC) code and find it requires no commenting to understand even though I started learning C# pretty much on the job.
I then had to laugh when I needed to explain some JavaScript (and jQuery) I wrote to him and exclaimed, "What the hell is this doing!". I had to get back to him a few minutes later on.
As for Java and C# on the web. I just wish it was more accessible to smaller companies. 100% of my freelance stuff are using cheap hosting that rarely support anything more than Perl/PHP.
> As for Java and C# on the web. I just wish it was more accessible to smaller companies. 100% of my freelance stuff are using cheap hosting that rarely support anything more than Perl/PHP.
One year ago I would have agreed with you, but I have since discovered some of the newer PaaS solutions like CloudFoundry / Pivotal CF [1] and OpenShift [2].
I'm using Pivotal CF for my current side project (a public website + web service) and am paying about $7/month.
PHP vs ASP.NET hosting prices are close to parity now.
Some ASP.NET web hosts offers $10/mo plans (a bit more if you want to use SQL Server). Or go with Azure Websites (Shared), starting from ~$15/mo if you think you need to scale up real soon.
The same goes with development costs as well (if you are using a Windows machine already).
Visual Studio Community edition is free and has support for extensions (where Express does not). They are great for freelancers. Do note that commercial licensing kicks in for > 5 developers.
BTW. I work with Java & GWT and I find it overkill for our needs. It took 5 months to make a 4 views, each with image or video grids and upload button.
On the side. I have on my free time working with Django and have a website with Authentification, comments, categories...
In the end, my personal project has more features.. less lines.
Instragram uses Django and so is Disqus. Are those slow?
> BTW. I work with Java & GWT and I find it overkill for our needs. It took 5 months to make a 4 views, each with image or video grids and upload button.
I work with the same stack and don't understand what could have taken so much?
Do Java/JVM folks miss the simple deployment of Go? I haven't used Java for a while (used Jetty to deploy), but words like "application servers" are the things that make Java sound "heavy".
"Java for everything, because it's the only statically type language with a fast runtime I know well".
Ok, Java is not terrible (PHP is terrible), and the JVM is a marvel of eat-your-RAM engineering, but this makes me sad, because there are only two things that can be said about Java: it's not terrible and it has a big ecosystem. There is nothing brilliant about it. It is slowly crawling toward convenient feature, but it's never going to be at the same level as a well-designed functional language in terms of correctness and readability-to-expressiveness ratio.
I cannot keep my sanity when I use dynamic languages in fairly big projects. I just cannot organize my code and all the functionality good. So, I looked at the options at Java and most of them looked either very complicated(Spring) or insufficient.
I am developing a very simple framework, insipred from Sparkjava and Play Framework: https://github.com/mustafaakin/WebOM It basically maps either HTTP requests or Websocket connections to Java objects with typed parameters.
I'm not sure what you're trying to do. If you're talking about dependency injection:
1) be aware that you're ditching some safety by relying on it
2) look at Guava
I just map a request like /users/:groupId?orderBy=name to A java object like "int groupId", and "String name" and it puts them automatically by converting, and if you wish you add some checks, notnull, range etc. and It replies bad request to client. Therefore, I do not do this conversion and checking each time.
I'm starting to put together my own Java web framework to make things easier to get started quickly and borrowing ( heavily) from other language frameworks. https://github.com/bluedevil2k/Jiffy
This post makes me wonder, what about Jython? I don't use it, but it would be a nice fit for the OP (writing performance critical code in Java, and use Jython as a glue).
The same argument can be made for any mature language with a solid ecosystem of tools and libraries.
Except the part about scalability, that's just BS. It has little to do with language and is all about architecture. Sure, at some point language can help you squeeze every ounce of performance out of the hardware (although my money would not be on Java for that), but that's only in cases where either performance is critical or the scale is so huge that saving on hardware makes a big difference.
It has a lot to do with language.
If your language's runtime has solid threading and reasonably pauseless GC (at several gigabytes heap) you run into much much less problems with scalability.
You forget just how much difference there is between languages. Comparing Python and Java for example, it's easy to find things that take 1-2 cpu cycles in Java (or even 0), that take thousands of cpu cycles in Python (e.g. function calls).
I mean, I would agree that 1s versus 1.3 seconds doesn't really matter. But look at those numbers we're talking 40-50 TIMES faster in half the cases. The number I tend to use is that one programmer is worth 10 servers. But this has diminishing returns : the larger the site gets, the more you'll focus on servers.
But even for small sites. Python is about double java's productivity, no more. That only helps you for very small programs.
So for large sites, python would have to be 40-50 times more productive than java. This is exactly python's weak point, and java's strong point ...
And from experience I know. Large python programs are horrendously difficult to change. They're like how large perl programs used to be. Changing a tiny thing in one far removed part of the program affects 10 other places in the program, with absolutely no warning, until the site crashes. And then you put a try-catch in your main loop and AAARGH.
I agree that the project size (LOC and usage) matters a lot and that small projects could use almost any language. I don't agree that everything i linear. A project with 10 times the LOC is not just 10 times harder to build, it might be anywhere from 20-100 times harder. For example, 10 000 LOC is possible for a developer to read and remember quite well, 100 000 LOC is much harder and takes longer to read. 1 million LOC is probably really, really hard to read and understand (especially when we are talking about old code with a lot of cruft and possibly multiple changes in the design over time).
So for a small code base that happens to have millions of users you should probably go for a fast language and take the time to optimize a lot. For a large code base with very few users you should probably use an expressive language and don't care about performance. And then you have all in-betweens which are left as an excercise to the reader ;-)
And yet there is a benchmark in that particular set you linked in which Python runs in 3/4 the time.
Also, I don't like the CLBG - it removed PyPy and a bunch of other implementations of various languages. I would be intrigued to see the speed of PyPy on that particular set of benchmarks, for instance.
But we all seem feel the same way about this, we all feel that we should sit on our hands and wait for someone else to do the chores we don't wish to do.
"No, actually, typing Foo one extra time does not “really suck”. It’s three letters"
Hah, if only it was always just three letters... :)) Usually more, and it's called NOISE. That's why C# has "var" and C++11 has "auto" (with all the benefits of strong typing still in place, obviously)
"And other languages like D and Go are too new to bet my work on."
I'd argue that D isn't really that knew, only niche. It's been around for over 10 years now.
>> Whatever time was saved by the developer when writing the Python code (if any) were lost many times over as dozens of users had to wait ten times longer each time they fished through the logs.
I was first exposed to Python in 2002. The sentiment in the quote above is reminiscent of the reasons I came back to Java. With a little Bash and some Java or a little Python and some Java I can do pretty much anything I need from system services to web to rich clients.
This post relies on the assumption that all dynamic languages are an order of magnitude slower than java. Not very long ago, the OP would have used the same argument in favor of C++, and against java.
In fact- many dynamic languages have proven To perform better than traditional ones in some areas, such as javascript on node for web-dev.
Clojure, for example is WAY faster than python. Incremental typing can squeeze out some additional power as well.
That surprised me as well; though perhaps it's just that "such as parsers" applies to more code than the author realized.
A parser is a discrete chunk of code that's general-purpose (likely to be called from lots of places with different content), but with a fairly straightforward list of cases that you can/should test to see how correct and robust it is.
There's a lot of code that fits into this category; not just parsers.
Does anyone know a good starting point for learning not just Java, but how to install everything I need? I consider myself the Neo of OOP and a master devops, but every time I tried to use Java I hit a wall of unreadable manuals/guides , software impossible to install/maintain, and mixed opinions among Java devs. Like it can't be used without a dedicated sysadmin.
My opinionated viewpoint, if you want to learn this stuff for a job:
Install eclipse. Get a non-JavaEE version - probably "eclipse for java developers". It's flaky software and you will have to babysit it sometimes, but it's still the best choice.
Use maven, then you don't need a sysadmin to maintain your libraries. You just add libraries as dependencies (you can even use a search wizard in Eclipse) and it Just Works. Start by using the new maven project wizard; I would skip archetype selection entirely, but if you want to use a particular framework you can choose one of those and get a "hello world".
Add libraries one at a time. If you're writing a web application I love Wicket which is literally the best-designed library ever. Aside from that you're facing things that, like eclipse, are a bit clunky; sooner or later you will have to learn Spring and Hibernate. Everyone loves to hate them and with good reason, but people will expect you to know them, and they do have good parts.
Try to do as much as possible in pure java. Use embedded jetty and write a normal application rather than messing with war packaging. Use annotation-based Spring configuration rather than XML, and the same for Hibernate.
The whole ecosystem is old and crufty. You will have to get used to random crappy workarounds for all sorts of problems, and you will probably have to cargo-cult some things to get stuff working. This is unfortunate, but I guess it's the price of stability. There are good sides to the ecosystem too. Sorry to be such a downer.
> I'm confused. Is there something else in another language with better solutions for IDE, dependency management, dependency injection, etc.?
Other languages are less dependent on a heavy IDE; I can write Python or even Scala in vim (+ repl in another tab) reasonably comfortably, and while vim has its warts it's a lot less fragile than eclipse.
Spring is IMO not worth the complexity compared to explicitly constructing things, but if you really want to do that there are ways to do it in Scala (e.g. just using implicits, reader monad) that don't require annotations or XML and don't have anything like the number of quirks (e.g. autoproxying, about 10 magic lifecycle methods, configuration-dependent behaviour on duplicate beans) that Spring does.
Likewise Hibernate is nice but it has some irritating misbehaviour (e.g. passing empty lists can cause it to make SQL syntax errors) that isn't present in ActiveRecord or even modern JVM alternatives.
I didn't expect my comment to be so negative when I started writing it, but as I started to try and explain the basics I realized how many arbitrary workarounds a very basic Java app needs. A lot of this is 10 years of accumulated cruft rather than fundamental problems, but at the sharp end new users still have to deal with it.
For me I've found I only need a few things to get started. One is the JDK, obviously. Another is Maven. It downloads dependencies for you and is pretty standard (there's also Gradle which some projects use). Finally there is IntelliJ for development. That's about it. Pretty much everything else can be downloaded and installed automatically be Maven or your IDE.
For web development, I've found Ninja Framework to be quite nice. The documentation is very good. The biggest problem is that it tends to delegate to lots of other libraries for functionality, and often those libraries have been around a long time and in some semi-standardised state that can be horrifically confusing (e.g. Hibernate). The Java world REALLY likes to take good open source libraries and then copy their interfaces into standards that other products can then implement. This sounds great in theory, and I'm sure some people do benefit from that, but it makes learning this stuff a giant PITA because the documentation for everything always has five versions, four implementations and every annotation or API has two identical versions in different namespaces, only one of which will actually work. Argghhhhh.
However if you do make it past this swamp, then the tools themselves are actually rather powerful and performant.
Your package manager will get you the compiler (probably as part of a package for the whole JDK).
You can use whatever editor you already like. It'll help if it has some support for Java's syntax, like highlighting or whatever.
If you want to add one non-essential tool, it should probably be a build tool that knows how to download libraries and compile your code against them. Gradle is the only sensible choice right now - it's far from perfect, but it should be tolerable. Again, your package manager will probably have Gradle. You only need it on the development (and CI) machine, not on the target.
At some point, you should probably give an IDE a go, to see how useful automatic refactoring is. Eclipse and IntelliJ are both free and pretty good (IntelliJ has free and paid versions, but the free version has everything you'll need to begin with). People love to argue over which is better, but the truth is that there's not a massive gap between them. Any IDE takes some getting used to, so it's probably better to start with a straightforward editor rather than an IDE.
If you want to use IntelliJ on the Mac, you might need to edit its Info.plist file to allow it to use a current version of Java. For some reason it's pinned to 1.6 by default. Gets me every time.
I can't think of anything you need to do to use Java that is remotely sysadminish, unless you count installing packages.
It's been years since i've read a Java book. Back when i did, by far the best was Just Java. Thinking In Java was also great. However, those were last revised 10 and 8 years ago respectively, so possibly not worth picking up today. They certainly won't tell you anything about the rather crucial new stuff in Java 8.
Great list. I wish this list and ones like it had a name other than "modern java" to distinguish tools/projects/people/interest/books. Because it's hard to name something that's a synonym for "new". Eventually "more modern java" is needed. And then "most modern".
I've heard mixed things about Play's Java version. YMMV, but the last I heard it was a "second-class citizen". Unfortunately I don't work with any templating myself, but I note that Dropwizard supports both Mustache and Freemarker. Would those work for you?
The argument can be made both ways. One can say that Python is better cause readability.
Many can give examples of successful or failed projects in both languages but it's just conjecture.
The only correct way to look at language choice, and the only objective one, is to use the language you are productive in. The best language is the one you master.
> You can complain all day about public static void main, but have fun setting up 500 servers. The downsides of dynamic languages are real, expensive, and permanent.
Love this quote. This is a thought-provoking article, even if you don't agree with everything as stated.
The point being that you can start 500 servers with a trivial amount of effort, rather than it being some kind of major undertaking as the author pretends. This is 2014, guys. You don't have to unbox and plug in all the HDs yourself.
If they're (e.g.) ec2 microinstances, 500 servers would cost you about $6,000/month, which is comparable to the monthly cost of just one extra programmer (maybe much less, if you're in a high wage location and you add in all the benefits, etc.) And remember, that's assuming you're operating at reddit scale, which, to be blunt, you're not likely to be doing.
The article is full of similar handwaving (e.g, "it's only 3 extra characters" when most class names are far longer than 3 characters, and you also have to multiply that extra typing by the number of lines in your codebase).
I'm glad Java works for him. Me, I abandoned it around the year 2000 and have never looked back.
* C# (and/or F#) to build iPhone, Android, and Windows Phone apps [1]
* F# code that compiles to JavaScript for front-ends [2]
* C# (and/or F#) code for Windows and *nix clients [3]
They are not perfect (nor the tooling are free), but it is possible.
iOS got this far on Objective-C. Seems like nobody really complains about that one the way they complain about Java.
I think he goes a bit too far with "unit tests are a waste of time" (maybe he just means for type checking). But other than that this perfect captures my very pragmatic view towards Java. There's a lot to be said for consolidating on one server language, and if you're going to pick one language, that's the one.
The Obj-C stuff always had a very low cost to bring in C stuff. I've not done a lot with Java's FFI in terms of writing code, but every time I've tried to manage a build with Java that uses external C libraries, I want to cry. That alone pretty much erases the differences in hassle between Java and Obj-C in my opinion.
I maintain and develop a large code base written in (mainly) Python with some C thrown in here and there. It was maintained and developed by a number of people before me over several years, who have come and gone. And yes while there is rust and cobwebs, I don't attribute any maintenance issues to the fact it is Python or a dynamic language, but rather higher level design decisions about interfaces and boundaries and responsibilities. Often some module that wasn't supposed to know something all of a sudden needs to know due to some new/changed requirement, and redrawing data flows and structures to ensure the right information is where it needs to be can be challenging. But this situation can be applicable to a system developed in any language - if anything Python's flexible data structures makes it easy to accomplish such re-engineering.
The last time I tried to do anything in Java, I was instructed to "just run the maven build script". After watching that flaming train wreck I walked away and haven't looked back since.
LOL, I spend all day next to java programmers trying to get GUIs to work in a performant manner.
Just pickup any Android device and you can see the lag, ever wonder why all the java phones have 4 GB of memory and a quad core processor just to draw a 1920x1080 screen?
How do you even parse JSON in Java? I remember in the days of XML, there was a kind of specification standard for the xml (a specification for how to specify a specification?). From that you could generate Java classes that would correspond to the elements of the XML. But for JSON there is no such meta description, so you are stuck with manually parsing the JSON and hoping you catch all nuances?
Typically you create your class manually and map to-and-from json-strings. In a web-context you'd usually let the container handle the serialization/de-serialization (jax-rs), in other contexts I tend to use Google's GSON-library.
But I feel things have improved over time. Dropwizard, gradle, embedded jetty, jersey, guava, Spring boot, etc... The trend is towards minimizing configuration and overall, the ecosystem has become somewhat more manageable. I wouldn't necessarily call it pleasant, but it's better.
An as for the language itself, Java8's lambdas + streams provide significant improvements.
Compare this (Java 7):
to this (Java 8): (Example is contrived, since you could use the built in Collections.reverse() to achieve the same result. My main point is that we have eliminated ~4 lines (counting braces) of ceremony.)All that said, I'd rather be using Clojure.