Java for Everything (2014)
teamten.com
teamten.com
Language wise - you need for loops for everything, no maps or streams. Also where are the concurrent collections in the stdlib?
I wonder if all the Go love here is from people who never worked in earnest with Java ? Or only worked with dynamic languages before?
If you're already comfortable with IntelliJ, you can continue to use IntelliJ.
Anyways, just my two cents as a almost decade long "enterprise" java developer, who has used his fair share of netflix packages as well.
Wait, what?
I spend my life nowadays writing boilerplate in Go. The language and ecosystem is riddled with boilerplate and needing to repeat yourself. That said, I find the language plenty productive, but concise and reusable Go is not.
The rest of your post has nothing to do with the Java programming language and instead has to do with your frustration at the Java enterprise ecosystem, the desire to make things abstract for extendibility etc etc... considering Go is now being adopted heavily in those same enterprise shops and often being written by former Java developers I predict it will suffer a similar souring of public opinion by 2030 or so.
Enterprise Go is coming.
I think Go will not ever be as bad as Enterprise Java because language and community culture which is shaped by language, don't give you as much opportunity to abuse it. If Go gets some new features that may enable abusing it, then yeah, history will repeat :)
Or you could just not do that. The Java culture is heavy on those things, but nothing forces you to participate in this if you're building from the ground-up.
Nothing in Java drives you to write bloated code with tons of classes. javac will not throw an error if you write proper simple code.
If you chose, or were forced by bad team culture somewhere, to write 20 classes for what should've been one function, that's a people problem. Java didn't make you do it.
That team who loves complex overengineering so much will do the same thing in whatever language they switch to someday.
In many cases, that is a function. Functions you can keep mostly on the same level of nested-ness. Occasionally you will have a higher-order thingy. A class, which gets instanciated but then the instance is not used? Well, that's a code smell. Probably not a real class you're dealing with, but someone had the urge to hammer it into a class thingy. Then the next person will come along and inherit from that and the one after that will write an adapter around it and so it goes on, until a degree of complexity is reached, that is mind-boggling.
A lot of classes also disappear when you simply create a struct and write the functions that deal with the struct's members, decoupling state and behavior. Of course this is not how it is done in mainstream OOP. Some language have adopted this kind of approach. For example Rust with structs and traits being implemented for a struct separately.
Hypothetically speaking, when using the concept of a class, one would expect an instance creation somewhere and that instance to be actually used. If it is not used after creation, then that means, that the constructor can probably be written as a function, saving one level of nesting and also using a simpler concept to express the same thing. When looking at a class, I might need to also consider what its base/super class is and might need to look at what members and methods that one has. I might have to look at what interfaces it implements. When I see a class, I expect some kind of state to be stored in it. If there is no state or only a single attribute, then that might be another sign, that I am not actually dealing with a thing, that needs to be a class.
A class is quite a complex thing, wherein one needs to look out for a lot of things.
Often making everything a class comes with another disadvantage when writing unit tests. You always have to instantiate (assuming not everything is static) and, if you hold state in member variables, you need to account for that in tests, covering various values of that member variable. Writing things as a class makes it easy to have side-effects updating your object internal state. This can make testing even more difficult.
There is complexity, which is inherent to a problem, and there is complexity created by people trying to solve problems with more complex than necessary means. Use a class when necessary and useful. Not for everything that does not hide on the count of 3.
For the use I take from your question, I would recommend simply using namespaces for implementing namespaces. If the language does not provide such, then see if there are modules, which serve as namespaces. Only as a last resort use a class to build a namespace. In that case I would already ask myself, why my language does not support something as basic as a namespace.
But viewed as a namespace, there is at least no global namespace pollution.
Modern Java is a much more pleasant developer experience than that. For extremely large applications it also comes with the benefit of being able to remove the boilerplate and ceremony required to do basic things like call an internal service, internal service auth, rate limiting, circuit breaking etc.
otoh, you are totally right about the 8 layers deep root functionality, but that IMHO reduces to mindless application of textbook oop patterns to applications (I still have to see a company randomly "changing databases" so the 8 layers of abstraction over the db are correct).
still, I adhere to a lost standard these days, which is less code as possible. golang is automatically disqualified since it thinks that a 8 LoC for loop with temp variables is "simpler" than a .map(fn) (so much for "throwing boilerplate away"). it likes to introduce point of failures, and I dislike point of failures
I'm happy I don't have to work with any kind of Java any more.
Are you 10 years behind? Modern Java moves the complexity into compile time annotation processors, so it's even more difficult to figure out what's happening when something breaks.
For better or worse, Go is where all the energy is in terms of OSS, so I do hope I see the light some day, but for now, the dev x for me is pretty underwhelming compared to Java
Most of the criticism about Java seem to be about old codebases that overused Gang of Four patterns, when that used to be more of a thing. Don’t blame the hammer for the shoddy building, blame the hammerer.
And before the inevitable, a map[T]interface{} only provides part of what a real set does. The rest is for loops.
If you chose to write that kind of code and then hate it, that's all on you. Neither the Java language spec nor the JDK make any effort to steer you into such baroque complexity. Keep it simple, best Java code is very simple.
I wrote Java for about 20 years (many of them at Sun) and have never written a AbstractFactorySingletonProxyFactoryBeans or anything like it. Don't do it.
I think that's library wise.
Language-wise I wish I could write a map interface in Java. But soon Go will get half-arsed generics and I won't be able to write a map interface in that either!
I think this is the crux of your issues with Go. If you're going to learn a new language, learn the new language. Don't try to recreate your existing language with a different syntax.
Java and Go have different strengths and weaknesses, and they are not used to build software with the same architecture. Java is useful for writing big monolithic servers while Go is better at building smaller independent modules communicating with each other, but there is much more to them than this.
I work with Java but still prefer to use Go for my hobby projects because it makes concurrent processing much easier to reason about. Also it's far less tedious than Java to install and use, but the bar isn't very high to start with.
There's nothing that makes Java any less suited than golang for writing small independent cross communicating modules.
For all the hype in golang about it being useful for concurrency, the fact that it lacks a concurrent collections library sticks out to anyone who used it.
And, IMHO, no implicit nulls, proper sum types, pattern matching was all it needed be considered modern. If left the last 40 years of compiler/language research outcomes on the table. Such a pity.
And give that the std lib is not riddled with implicit nulls that mean all kinds of things (like any kind of error, or absence), this will not be fixed in the next decade. What a waste.
This is the type of non-constructive statement I’m used to seeing on programming forums elsewhere on the Internet. The thing is, it’s just dismissive and irritating. All it says is, “I don’t understand why this thing is popular. Could it be that all of the proponents are simply inexperienced and don’t know any better?” — of course it’s possible, the same way that it’s possible that everyone who says my cooking is terrible just has bad taste and doesn’t understand good cuisine.
It could just be that your experience of Go was not very complete. There are certainly sore spots in Go. Maybe gopls was broken when you tried (I just tested and VSCode Go is faster than Goland on my machine, so I actually suspect something was wrong.) Maybe you picked use cases that it was just not very good for, or possibly you missed some of its utility in the time that you used it. There’s no way for me to know. I’m sure you have enough Java experience to see how someone fiddling with Maven, Eclipse, Spring, Hibernate, Guice... and running into problems could spoil them on the language or its ecosystem early on.
And yet, what disappoints me more is that when I saw this comment, it was the second highest on the page. Meaning the statement seems to have resonated rather than raising red flags.
I kind of get it. Go is one of the trendiest languages to hate now. I would guess it is in third behind Perl and PHP. Don’t get me wrong — many people unfairly hated Java too, but let’s face it, it hasn’t been trendy to baselessly hate Java in a long time. Especially not with how much it has changed and improved. I still don’t like that people do this. It feels like on at minimum a weekly basis I get chastised or see others get chastised for expressing our satisfaction with Go. Thankfully it is uncommon here, but in other online programming circles it is common enough.
Imagine you’re a beginner who is learning Go as a first programming language and they read your message. What message is it really sending?
Perhaps you did not mean for this to come off this way, but to me this is the language of condescension.
> of course it’s possible, the same way that it’s possible that everyone who says my cooking is terrible just has bad taste and doesn’t understand good cuisine.
I could’ve answered anecdotally about my experience with Java, thus proving or at least claiming at least one person has earnestly used Java and still likes Go. I have no idea what value that could bring to this discussion. Does anyone actually believe there is a possibility that not even a small amount of users of Go, the ~14th most popular language according to TIOBE, have not used in earnest the ~2nd most popular language according to TIOBE?
I dislike the question. I repeat my own question and now ask you to answer it:
> Imagine you’re a beginner who is learning Go as a first programming language and they read your message. What message is it really sending?
The value would be highlighting the upsides of using Go for people who're comfortable with Java, in spite of the disadvantages mentioned in the parent comment.
That information is valuable to people considering picking up their Nth language.
What value does the comment that you ended up writing add to the discussion?
>I dislike the question. I repeat my own question and now ask you to answer it
I dislike the question. I repeat my own question and now ask you to answer it:
What value does the comment that you ended up writing add to the discussion?
It's not dismissive. I have worked in Java and Go, and i ask the same question, entirely genuinely. It's up to you if you find it irritating.
> it hasn’t been trendy to baselessly hate Java in a long time
It's happening on this page, today, my friend.
Also, if it wasn’t clear I was addressing programmers with experience in more than 1 language, not absolute beginners. If someone who is learning Go as their first language, I wholeheartedly endorse learning it! (Although Python would be better :-))
TypeScript fails me almost exclusively due to `!`. The association is so strong that whenever I encounter an error, I am excited to see if it's due to `!`. In the absence of non-null type assertions, TS feels very safe to me, largely due to experience of not seeing it fail.
export function assertIsDefined<V>(
value: V,
buildMessage = defaultAssertIsDefinedMessage
): asserts value is NonNullable<V> {
if (value === undefined || value === null) {
throw new Error(buildMessage(value));
}
}
It would prevent follow up errors if the value in fact was not defined.I often use that utility when I have some type where under certain condition a value will always be defined, but a union type would make it too complex to be useful.
For example, suppose I have a variable of type
type Name = string | null
const name : Name = null
and I pass it to a function that expects just a string (not null), function len(str: string) {
return str.length;
}
Then len(name);
will fail type checking, but len(name!);
will not fail type checking, but will fail at runtime.[0] https://stackoverflow.com/questions/38874928/operator-in-typ...
Do you know why it was added? Ive used an annotation that disables type checking on a couple unit tests, but this seems much harder to notice
An example that pops to mind is how React’s createContext() typings for some reason require a non-bill default value, but you may not have such a value at the time the call is made. Personally I think it’s totally legit to just do createContext<T>(null!). I don’t think this leads to errors that won’t get quickly noticed.
But if you get carried away, it’ll bite you for sure, especially in code that has more going on than define a React context.
Like, if you have an interface...
interface MyInterface {
someValue?: string;
/** Let's say this only exists if `someValue` exists */
someOtherValue?: string;
}
And then in some code later... const myFunction = (someParam: MyInterface) => {
if (someParam.someValue) {
myOtherFunction(someParam);
}
}
// let's say this function is only EVER called if `someValue` exists
// we know more than the type checker in this case
const myOtherFunction = (someParam: MyInterface) => {
console.log(someParam.someValue!.length);
console.log(someParam.someOtherValue!.length);
}
There are definitely more "correct" ways to do this (i.e. using `Partial` or re-casting to another type) but sometimes there are edge cases that aren't worth doing things more correctly (like, if this is only happening in one spot)Lots of folks make the mistake of assuming the TypeScript is strongly typed, but it's not really... I like to think of its type system as "squishy" in that you can very very easily fake things or trick it into compiling. I think of the types more as comments and hints about the code and not there to ensure program correctness.
This is actually one of my favorite features of TypeScript; it's not as strict as, say, Java or Scala, and it lets you get away with some things without having to rework all of your types. This can be a bit of a footgun, BUT if you're also writing unit tests and integration tests then you'll have all of your bases covered.
Yep!
> Lots of folks make the mistake of assuming the TypeScript is strongly typed, but it's not really... I like to think of its type system as "squishy"
Totally! That’s what makes it so nice. Great way to describe it.
That's not true, right? AFAIK, the Java type system is broken and any type might silently be another type which doesn't support any of the methods the static type would indicate. It's basically as type safe as C in my eyes.
> any type might silently be another type which doesn't support any of the methods the static type would indicate
When an object is typed differently from its actual runtime type, it's usually because it's hidden behind an interface type. So it indicates fewer methods than it supports. Safe, but unergonomic!
In Java, every access of an object variable can blow up your program even though the type checker is happy. In C, every access of a pointer variable can blow up your program. This seems very similar. Neither language provides type safety.
EDIT: To be clear, Java is definitely safer than C. When Java "blows up" due to a null variable access, it throws an exception in a well-defined way. When C blows up due to a null pointer dereference, anything can happen, and if you're lucky your program terminates unconditionally. It's just that neither error is caught by the type system.
int square(char* string) {
int *number = (int*)(void*)string;
return *number * *number;
}
It's UB, so in principle it can do anything, and in practice, the best thing it might do is return gibberish.The Java version of this would throw a ClassCastException on the first line.
I don't see how external static analysis tools are that relevant when we're talking about type safety.
I just don't consider the language to be "type safe" when every single variable (except for primitives) can explode at runtime with no warning from the type system. At least with C++ you can have references which you know won't be null.
The fact that you bring up JS, a language with _literally no static type checking_, confuses me. Are we even talking about the same thing? Maybe I should've used the phrase static type safety rather than type safety? I thought it was clear from context (as a response to "with Java if it compiles it definitely works"), but maybe not.
That’s just false. C has really “random” implicit casts everywhere, not having is already great.
And I agree with you that nulls are a huge mistake, but that’s one aspect of type safety.
> At least with C++ you can have references which you know won't be null.
Yeah, they are just uninitialized.
I think it is a fair point. Staying within a language and an eco-system of libraries, tools etec. makes sense so you can get profiency and just know how things work without too much thinking about it.
However it only holds to an extent as many languages are tied to or are native to a particular platform. I.e. JavaScript in a web browser, Java on the JVM, Java in Android, Objective-C in iOS etc. And some are definately not mature when you go outside their habitat. Try to compile Java into JavaScript (using GWT or whatever), or into a binary. You can do it however it doesn't really makes sense, so much of a language is really its libraries and way doing things. You are not going to get HSQLDB and JPA running inside a web browser for any reasonable application.
This is the exact opposite experience for me.
I find Java's type system to be extremely lacking (e.g. nullability, no discriminated unions, etc.), such that I write plenty of application code to mimic what a robust type system would enforce. Unfortunately, since it's not a compile time check, if you do it wrong, you get errors in production. In this way, it is the same as a fully dynamic language—what compiles has loose guarantees about correctness.
Excuse me for a moment, but I'm going to be that annoying guy—but once you get some experience with an ML style language (e.g. Haskell, OCaml, SML, etc.) it's painful to go back to these class name based type systems.
TL;DR: F# is only worth it if you need to take advantage of the .NET ecosystem, otherwise just go with SML/Haskell/OCaml
I don't understand this, this is extreme hyperbole. Even when I used one of the strictest JVM languages where almost everything was a compiler error I still only had the guarantee that 99% of the time it is not going to crash, not that the code is correct. Of course, Java crashed all the time, groovy crashes a lot of the time, but it's a dynamic language that is supposed to fail like that. Once the code compiled, the business logic could still be wrong but getting the business logic correct is my job, not the machine's and the benefits of avoiding machine errors cannot be understated.
Java now has sealed classes/interfaces. They are sum types, not sure what is actually the difference between discriminated unions. And with records, you have named tuples, basically product types. As far as I know, Haskell also only has algebraic datatypes.
The syntax is like so:
``` sealed interface Expression permits Add, Multiply {}
record Add(Expression a, Expression b) implements Expression {} ```
(written on phone so it may not actually compile)
And you also have switch expressions enforcing that you have used up every possibility (even null!), and with the coming better pattern matching, Java will become quite an expressive language.
My critique was more targeted to the Java of the time period this article was written in (2014), but these new additions are another point for the "Just write it in Java" folks.
- At this point you can say TypeScript is mainstream. It's not Java, but it's definitely not a niche toy.
- Many companies stand behind it and use it in production.
- It is widely supported by tooling.
- With TypeScript, every element of your stack can not only share code, but can share types, too. This has been a huge boon for me.
- The type system is really, really flexible. It seems possible to specify the exact degree of safety that you want for any given situation. I never feel bound by the type system. It's very liberating. Not so with Java or C#.
- It compiles to JavaScript, so it can run anywhere. On the backend you can run it natively with Deno. I haven't tried this yet, but am looking forward.
https://visualstudiomagazine.com/articles/2021/04/01/typescr...
Personally this is why I believe all languages will converge into the structural, gradual typing model of Typescript.
Typescript allows you to not make typing very strict when it's not important, but also allows you to define things stricter than your average Haskell codebase.
Most other languages have only 1 option about how strict a piece of code is typed.
My question was: what benefits would I get from sometimes not knowing the types at compile time (which is what I guess gradual typing is)?
How many Java apps do you think are out there that are not even worth the energy that they're using to run? How many absolutely asinine startups selling DRM-controlled juicers or internet connected water bottles or NFTs?
I'm not saying that every project that runs on Node or Python or whatever is worth the extra energy it uses, but this is kind of a silly argument to make with the kind of stuff coming out of the tech industry these days.
We have auto-published types generated from OpenAPI specifications that we use in a lot of different projects and it's been really awesome.
It just does not fit together. Want functional? Go with Haskell/OCaml/ReScript/etc. Want JVM compatibility-and-thus-OO-at-the-core (possibly with some functional goodness on top)? Go with Kotlin.
Just like any language, just use the bits you need for your project and apply KISS (Keep It Simple, Stupid) liberally! :)
No, that is the actual problem. Your feelings don't care about the facts. You don't want to filter developers for their tolerance for mindless, time-consuming and painful work. If you do that, Parkinson's law will strike you so hard you'll turn out like IBM.
Of course, you also don't want to end up at the other extreme, where all the parts of your stack are so exotic that only one person on the planet is qualified to deal with it - and they just left the company.
I think the language is very similar to Java but some advantages present themselves 1.it has more modern features than Java, 2. it has mobile (including IOS) and frontend support 3. (possibly not true, but my impression anyway) it has better support for writing close the metal, high performance code
It really is very nice to write everything in the same language.
Between the two requirements, I think Java, C#, and TypeScript might be the only languages that qualify.
says jtolmar in a browser written in C++
Also, the way you phrased your comment is needlessly rude, to the point I almost didn't bother replying. If you actually want to learn why people have the opinions they do, you should consider being more polite.
Assuming you’re doing reasonably high level work (like building a typical SaaS product, not a database), I also think you’re probably best off choosing a language with the following properties:
- statically typed
- garbage collected
- reasonably performant
- reasonably easy to hire for, or at least pretty quick to learn
- compiles pretty fast
- has a strong ecosystem, great libraries/frameworks/tooling
Java fits, but so do Go, C# and TypeScript. This article says Go is too new, C# not cross platform enough - both true in 2014, but not 2021. And it doesn’t mention TypeScript, but it was VERY new in 2014, so understandable. It’s performance isn’t as good as the other 3, but has the major advantage of letting you have a single FE and BE language for a lot of projects. My current company is full stack TS (RESTful services with TS/React on the web, TS/React Native on mobile), and it’s very convenient/productive most of the time.
Scala is my personal favourite language, but I’ll agree it’s too hard to hire/train for to be a practical choice. But Java has plenty of competition from Go, C# and TypeScript.
Perhaps the real kernel of the advice in the article is "try to use your primary language as much as you can, even for things it is not traditionally used for".
My team mostly writes Java. We do write Python for a lot of little scripts - collecting and munging data, dashboards, etc. I have come to think that we should just do those in Java as well.
My favorite language to develop in is Typescript/JavaScript, but daily use Java 8 due to legacy application and would love to upgrade.
That tweet was from 2010. Modern Day StackOverflow
1.3 BILLION page views per month, ~20X! 23 Servers including Redis, SQL and Elasticsearch. ~5x.
Although Stackoverflow is pretty much a read heavy site.
And while people can have an opinion on Java the language, the JVM and its ecosystem is often overlooked and under appreciated. Look at GraalVM.
Java was the magic pill in late 90s in India and every Engineering graduate irrespective of their domain was told to get certified in it for a job. My sister(ECE) was one of them, my father got our first computer (Pentium-III ~900 MHz)to help with it in 2000 (which was a big deal for a middle-income family in India) and unfortunately the Dot-Com bubble crash hit its peak with absolutely no recruitment for java developers. My sister struggled for a while, fortunately was able to switch domain(non-SW) and has a great career now.
Fast forward to 2005, it's my turn in the Engineering college - CSE (A premium one, so job was pretty much guaranteed). Our 2nd year has introduction to programming with Java, No C, no low level languages, straight up Java. Since meritorious, Many in my college are from very poor backgrounds who never had access to computers, taking in Java directly was very tough for them. So almost everyone went for C-programming training outside our college run by one of our alumni(He has now started his own Engineering college, one of the largest in the city!) all of them studied C, so they could understand Java(programming) better!
In late 2000s it was common to define your job as a 'Java developer' and it was understood in even rural India. Famous movies were made where a character goes from rags to riches because of Java. Then in 2008 during my placements recession happened, only fraction got placed(mostly in java dev), I was into J2ME and so waited for a mobile development job. Then Android happened, got a android development job and of course Java development background helped me a lot(Worked with other major languages every now and then).
Fast forward 2019, I've shutdown my startup due to health issues. I'm not writing android applications or java-back ends anymore. Wanted to switch to some other language as primary language partly because of java fatigue, partly because learning new language could help me divert my attention from the ongoing issues, but mainly because I have less time to code(Any time saved is a time I can put for my health) .
I chose Go, because I've been burned before by Python when the application scaled up requiring expensive optimizations. Luckily Go was everything I wanted from a new language although it wanted me to empty my cup(pun intended). Now, most of my code is in Go be it production applications or home automation scripts. I don't think I'll be able to touch Java again(perhaps maybe it brings back memories I don't really cherish) or may be I'm just adamant.
If you have made it so far, Thanks for reading.
Is this really true? I would love to know more. Could you give any examples?
I'm glad to hear you're enjoying life again.
Glad that you asked. The character name is 'Java Sunderasan' from the Tamil movie 'Arai en 305il kadavul'(2008). Here's a clip[1] from that movie it shows another character explaining how Sundersan went from rag to riches within 2 years because of Java while others stayed/became poorer. Couldn't find one with subtitles but the visuals are clear enough to understand what's happening.
Where as Python did pay really well, I myself paid a fortune to my python devs working on computer-networking projects in my startup between 2014-19 as there weren't many python devs doing computer-networking in India. I guess most python devs are working on Datascience/ML and it sure does pay really well considering cost-of-living in India.
Java is still pretty much the staple in enterprise software and in large outsourcing companies(Which I believe is because of legacy products in U.S. companies/Govt. which provide projects for them). Even in India large Govt. infrastructure SW projects use Java.
You still use the right tool for the job. Java is not always that. Also "right" should factor in your existing expertise, team culture, organizational roadmaps, etc.
Bit of a nitpick, but: GWT enables this, transpiling to JavaScript. Rumours of its death have been somewhat exaggerated (it's maintained but it's not getting that much attention). I'm not sure if Vaadin still makes use of GWT.
I really regret not diving into proper html+css+js sooner.
I’m pretty sure it’s temporary. There are plenty of projects working in that direction, e.g. https://github.com/i-net-software/JWebAssembly
> you wouldn't write your Tensorflow code in Java
Why?
Kernel modules and device drivers are probably the only example where you need to pick another tool.
As for web frontends, we've also already had GWT. In most cases you're better off going with the grain and using JS/TS, for obvious reasons.
I can continue for a while with examples where Java is inappropriate. Another one would be system daemons that need to use minimal memory. There is Graal but it has so many caveats that I can't really take it seriously yet (and I've tried, multiple times). In this same vein, serverless applications are generally more painless with languages whose ecosystems emphasize fast startup, which Java historically has been terrible at. And on top of that you'll pay for the memory the JVM hogs.
I really want to try out htmx (https://htmx.org/docs/#introduction) for my next project because I feel it's the only logical next step to HTML, so yes, I could definitely write it in Java
I absolutely would (well, I'd use Scala myself, but I'd absolutely use a single language for all of those). I think the article makes a good case for it.
If you are a web development shop, you will not be writing Tensorflow or device drivers. You don't need to worry about picking a language which can do those.
You are quite write that you shouldn't write a web frontend in Java, though. For web development, in practice, anyone picking a language which is not JS/TS will have to use two languages. That's still better than more than two!
Despite Java’s verboseness and all the factory hell, with recent tooling and the massive library of great open source libraries, I do enjoy writing it. I prefer strong typing personally. But I don’t agree with Java for everything. Recently I did some data processing work on Spark. I wrote everything in Scala. The whole “trait” functionality was very nice and elegant, and it allowed me to incrementally build some nice abstractions that my team can use to quickly build and deploy spark jobs.
This gets repeated so often, but it's mostly never been true in the general use case (it was mostly a J2EE/EJB thing). It's a silly Java meme that I wish would just die. If you don't like the factory pattern, don't use it.
A lot of programmer effort in any organization goes towards supporting existing software, which in the Java ecosystem tends to full of all the factory non sense. I’m sure these concepts started off in the J2EE space, but it’s infected a lot of different types of projects because people assumed these patterns were “good” or inherently part of Java. And here we are now dealing with the mess.
I'm sure there are shitty programmers in every language community, who will write things using concepts they understand only marginally, and I'm sure it has lead to a couple of FactoryFactoryFactories here and there. But the ecosystem is not "full" of this at all.
Java isn't the same as it was 20 years ago. It grew up.
The hate for Java is so strongly meme based.
It is just that thing ... there are patterns that are tedious. The object mapping before hibernate was extremely tedious for example. But factory pattern ... seriously?
> Foo f = new Foo(a, b, c);
Factory:
> FooFactory ff = new FooFactory(); > ff.setA(a); > ff.setB(b); > ff.setC(c); > f = ff.create();
...or the same in XML. Fluent APIs turn it into oneliner, but it's still good only for adding hours to your bill.
Second, factory methods today have arguments combinations too. fd.create(a, b, c) is the most normal thing in the world.
Seriously, this is ridiculous.
http://mail-archives.apache.org/mod_mbox/ws-xmlrpc-dev/20070...
as well as the mental effort it took me to figure this out – by no metric I would call it "braindead easy".
At write time, verbosity is mostly solved by intelliJ. Code gen and tab complete make it at least as fast to write code as any other language in any other editor.
At read time, verbosity is your friend.
That being said, I like Java. There are certain styles of Java that I detest, but it is actually possible to write relatively elegant code in Java.
Java for Everything (2014) - https://news.ycombinator.com/item?id=11386306 - March 2016 (83 comments)
Java for Everything - https://news.ycombinator.com/item?id=8677556 - Nov 2014 (338 comments)
Sometimes I wonder if the language matters or the community/ecosystem for the domain is more important. I like Java myself but is it ever used for a small SaaS startup? Does it have great things to empower single developers? Rails land has things like ActiveStorage, Hotwire, super easy migrations, great CLI tool etc. SpringBoot is not the replacement you want.
Java feels terribly corporate and I feel its libs reflect it. I was recently looking for a Sidekiq alternative for Java land and the experience is so dramatically different all the way from pragmatism of the library and how its marketed to the beautiful documentation provided by Ruby land people.
I imagine it being the exact same case for Python and data science. The language you want to go is probably the language were millions of people before you went for the exact same scenario.
This is just a silly take and I will probably have changed my mind by the end of the year but a thought nonetheless.
> incredibly mature runtime Cool, but do note that modern is by definition the opposite of mature.
If A was invented before B, who cares? I want whichever one's better.
Also, there are very small libs for java, you don’t have to create a spring/JEE app.
I hated my time with Spring. Compile-time bugs became runtime bugs (Cannot startup one bean because cannot find other beans). Startup was slow (looking for all the beans!). Solved problems like null-checking constructors and 'final'ing all variables became unsolved once you needed to leave them nullable/mutable for Spring to update them post-constructor. Testing a single class became slower and flakier when you needed to spin up the IOC to test - because it would start building config for all the other classes too.
Keep in mind, Spring is already touting itself as modern. But along comes Micronaut[1] with a new set of promises:
"...monumental leap in startup time"
"Keeps your startup time and memory footprint low by doing the heavy lifting up-front"
"Easily spin up servers and clients in your unit tests and run them instantaneously"
Which is EXACTLY what I want in a framework. Having built two greenfield Micronaut services at work, as well as maintaining a few others, I can say it's bullshit. All the stuff I listed about Spring above is still true of Micronaut.> Also, there are very small libs for java, you don’t have to create a spring/JEE app.
I like https://sparkjava.com/ but I'm never going to be working with colleagues who choose it over Spring/Micronaut.
Having said that though, some languages prevent themselves from being used for "Everything". Python, Perl, PHP, Ruby for example often needs to be paired with another language for performance reasons.
The ergonomics of "modern" compiled languages is good enough for everything now.
I've been using Go for everything for many years now, and it's fine. I know people/shops who use Java or C# for "everything", and it's fine. Fine here being defined as "not needing to learn another programming language to solve my problem".
If you pick something really new, tooling and libraries are typically a bit lacking. It's the reason why Java stays so popular. The language is a bit dated at this point but the tooling and library ecosystem are still top. I used it for more than 20 years before switching to Kotlin. With Kotlin you have the same level of awesome tooling and libraries but with a bit more modern language.
Beyond Java/Kotlin, there is of course lots to choose from but you get a significant downgrade in tooling. Jetbrains takes care of IDEs for Ruby, Python, Go, Rust, Javascript/Typescript, etc. and they are nice. But it's typically with a lot less refactorings, auto fixes, etc. than they provide for Java and Kotlin. It's just not on the same level and a bit of a downgrade in that sense. Out of those, Rust is the most disruptive IMHO. Worth investing in and a very solid library ecosystem.
The problem with Java is that it clearly shies away from more direct memory control, and as a result it's significantly disadvantaged on modern hardware in terms of raw performance.
You may dismiss this and say "but Java is faster than C++ in some cases". In some cases yes, like when you do raw math and don't load and store much state. But handling state efficiently is Java's weak spot. Objects are tiny fragments scattered around the heap.
Look at .NET and C#. Unity can implement architectures like Entity Component Systems, because C# has decided long time ago to be the "Java for everything" and that's precisely what it ended up as. It started as a Java clone, but added some features of C and C++, it has some features of JavaScript and Python, it has everything. EVERYTHING. It even has a native AOT profile, in case you wanna write a kernel driver or an entire OS in C#.
The only thing stopping C# from taking over the world is the association with Windows, I bet, otherwise everything would be C# by now.
As for Java... it FELT completed a decade or two ago. But now, it feels lacking. It's basically become EnterpriseScript. We'll see how Valhalla and Panama pan out, but for now evolution is a bit slow.
There is an interesting issue on benchmarkgame’s repo, where C# is ahead a bit using a clever trick. It basically halves the required allocations. And Java is insanely close with double the allocations.
I am as much of a Java fanboy as it gets, but football team level love-hate of languages is stupid. Also, this benchmark is not necessarily applicable to reL world programs.
The CLR provides some access to low level primitives, while the JVM rather hides them. The first choice allows for more optimization by the developer, but that will be explicit and will potentially disallow some automatic ones.
Java on the other hand hides most of these details and depends on a very advanced JIT compiler for most optimizations (like escape analysis), in which way even a decade old program will get magically faster. Of course it is only a crude difference between them, with Java getting primitive types, and CLR continuously improving in JIT and GC.
No.
There was an interesting issue.
The clever trick was disallowed and the programs that used the clever trick were removed.
> … insanely close with double the allocations…
No, what you see is not with double the allocations.
The clever trick was disallowed and the programs that used the clever trick were removed.
Read the program source code.
Especially that my whole comment was actually defending C#, even though I’m not particularly fond of it.
That only works when you make little quoting gestures with your fingers.
All mainstream JVM GCs are compacting, but I agree that without “value” types, an ArrayList for example will point to objects that can hurt performance. But that’s why you profile, if a given part is a hotspot, then you can rewrite it as an array of primitives. But due to compacting, allocating objects randomly in C++ vs in Java, Java will likely win.
And valhalla is coming, and with primitive types, the JVM will have a way for that last piece of performance.
Python is a wonderful language and exemplifies the "essence" of programming in that it nearly looks like pseudocode on a whiteboard. The syntactic overhead is minimal. I liken it to solving an algebra problem with pencil and paper - you would never write "int x = 5" on paper, just "x = 5."
It's this simplification that makes Python a joy to use...but also difficult to maintain. Programmers have to get in the habit of following code style guidelines, rather than being (somewhat) coerced into them by strong typing.
A simple example of this is the question: Where does a Python program start? If I provide a Python script, the reader would have to scan from top to bottom to see the first non-definitional line of code. With Java, there is no ambiguity; it is the main function. A company may declare a style guidline that requires Python programs define a main-check function such as:
if __name__ == "__main__": main()
but the developer needs to learn this policy.
My current favourite is Poetry but it still feels lacking compared to Maven or Gradle.
But it has lambdas that are not as good as haskell with currying, but quite concise, it has type inference with var (that can even infer the Generic’s arguments), with records class definitions are one-liners.
Properties are verbose but they are absolutely not necessarily for not-bean-oriented codebases.
another issue is OOP damaged a lot of people's thinking. Is it a Dog or a Cat or is it an Abstract Animal ? How come the LISPs, and other functional dynamic languages don't need static type declarations. Btw LISP can be fast as C. I will give you a tip: those dynamic languages knew beforehand to separate code from data.
These days they call it Data Oriented Programming. Before not so smart folks like called it dealing with values. Values don't change and easier to deal with negating types.
Python performance sucks, wish there was something better with close to an equivalent community. F# would've been that language but it's treated like a red headed step child by Microsoft.
And one thing about that sucks about Java and by large JVM languages well besides Clojure is the ergonomics to get started. do you use Maven, Gradle ? whereas with python -- python script.py n pip install. Yeah java has javac but you won't find anything that says use the java compiler for simple programs.
if they really didn't we'd be using operating systems written in LISP instead of C
> Btw LISP can be fast as C. I will give you a tip: those dynamic languages knew beforehand to separate code from data.
ditto
Some people live happily inside Emacs. It has become an OS for them.
Assuming you're talking about Common Lisp, you definitely need to make heavy use of type declarations and be using a very performant implementation for its speed to be anywhere as fast as C.
And modern Java is great and getting better at DOP/FP.
> do you use Maven, Gradle ?
And my experience is that tooling around java is superb. You just mvn install/gradlew build and it handles dependencies and everything for you.
Of course, it’s not new but adoption took some time
I also like to explicitly declare immutability/ mutability
let x = “hello world”
var ctr = 0
var mutableVar = "Foo"
final var immutableVar = "Bar" final ArrayList<String> foo = new ArrayList<>();
foo.add("Foo"); // Compiles and runs - this is mutation
foo = new ArrayList<>(); // Compiler error - this is re-assignment
In your example, both Strings are immutable, since Java Strings are always immutable.Scala takes this approach, using var for declaring mutable variables, and val for declaring immutables. In my experience, in well designed imperative code, only a small proportion of variables need mutation, so using keywords like const and final is backward. It would make more sense to use a mutable keyword, or to do as Scala does. (C++ has a mutable keyword, but it's for a different purpose.)
https://docs.scala-lang.org/overviews/scala-book/two-types-v...
Little things like this make a language so much more pleasant.
LinkedList<HashMap<MyFancyBusinessObject, String>>> is the culprit.
Also something I don't like with Java is that it is a lot of ceremony to actually start a new greenfield project or script in it. My favorite experience with this sort of thing is Racket where I just launch DrRacket (after ONE very easy install on any platform), start writing my program, and hit run. I don't even need to save my program if I don't want to (it does autosave though so you probably won't lose your program even if DrRacket crashes!).
To be fair to Java though, jshell is a very nice REPL which is surprising for a language like Java. It is actually my preferred way to do one off date calculations since most languages don't seem to have a nice way to do date arithmetic built into the language itself.
The situation with one off scripts is something that could really be improved in Java by having a dialect which just runs the file top to bottom like C# recently did with top level programs.
Once the team shifted and we outnumbered him, he didn't seem to push that argument any more.
One could also use D and rdmd pretty much for the same purpose, I imagine.
> And other languages like D and Go are too new to bet my work on.
Java, the author's favorite, is 26 years old. D is 20 years old. I'm not quire what exactly makes the six year difference so important here. (Sure, Go is 12 years old, that probably classifies as way younger.)
(But don’t get me wrong, D is a cool language, but it didn’t get as popular, so smaller ecosystem, developer mindshare will weaken it’s position)
This man has the patience of the gods. Not because of the writing, but because he actually has the time to wait for Java programs to start when he wants to run a small shell script?
You could run 5000 bash scripts in the time it takes java to load. You could run 500 python scripts.
What is this guy smoking!