I nominate Groovy. Many of gradle's failures are just idiomatic groovy. The entire mindset of "friendly simplifications" that work 80% of the time, and if they give pretend that you don't notice, look, there's pretty code over there!
Even kotlin suffers from some of that (you can override a val x:Int with a val x:Int get() unless it's tied down otherwise, talk about principle of maximum surprise) but the genes from the other parent avoid the worst.
It does lead though to one of the biggest lies which is "if you know Java then you already know Groovy!" - that's just a mean trick to play on people.
Groovy is all the more guilty for carrying the bad tradition forward. It's akin to somebody looking at the success of C and deciding that its macro system must be perfectly preserved going forward.
A common set of conventions in the Ruby community uses both options for optional punctiation, with context controlling which is used for a particular case. E.g.,
1. Use a single expression per line, and don't combine the line starting or ending a block with the contents, and don't use semicolons where they are unnecessary (so, semicolons are used only to separate the opening and “end” of single-line blocks.)
2. Use parens among function calls, except omit them in calls that are part of internal DSLs.
I suppose I should more accurately call that thing JSR223 + Groovy, all stored in an extensive XML file and edited through the JMeter UI..
Also, I guess some people genuinely like gradual typing, although I've never found much use for it.
Nowadays, I wouldn't pick up Groovy anymore, but there was a time where it was basically that, or Java (or a different ecosystem entirely; or something like JRuby / Jython).
https://github.com/geb/geb/blob/master/module/geb-core/src/m...
So it looks mostly like Java, its just making use of Groovy's niceties and more powerful constructs in various parts to make the coding nicer.
I would probably do Kotlin, now, but that wasn't an option when I started this.
The amount of boilerplate removed is one big win, but moreover the more functionally oriented aspects of most anything you'd do with a for-loop in java is wonderful.
And with annotations such as @CompileStatic and @TypeChecked, I am able to forgo SOME of the syntactic niceties for the compile-time binding java-comparable speed.
Could you expand on this? I don't follow what you mean. Are you talking about some form of shadowing?
val x: Int // this is an immutable value
val y: Int // this is an immutable Function0<Int> that is executed each time and but pretends to be a val
get() = System.currentTimeMillis()I agree that true immutability - or code that is more obvious about avoiding side-effects - could be useful, but I don't think that was ever the goal.
The kotlin defense to this surely is that immutability happily exists in val constructor args (with the usual exception: not transitive through references), but that's purely contextual and a difference that is very hard to represent at usage site (e.g. they look exactly the same in the intellij "javadoc" view). If for some reason bean-style methods had to be represented through var/val syntax, I think that it would have been much better if read-only calculated getters were represented by a var without set(), leaving val to cases where you're guaranteed to get the same when referenced twice (value set once in constructor or some lazyness shenanigans).
Python getter properties are evaluated instantly on assignment. To convert them back into function-pointers like the Kotlin example above you really have to go out of your way by deep diving into inspect module. The result is a property-object which is not assignable to a int-variable, but type checking probably wouldn't go this deep as inspect naturally is very dynamic in its nature.
My guess is Kotlin does this as a way of structural typing, if it walks like a int and talks like an int it is an int.
i took up flutter a couple of years ago, which means i am now saddled with (ugh) gradle for android builds. i am used to being able to intuit the underlying architecture of various tech things and fix them, which is utterly impossible as far as gradle goes.
not only are the error messages unhelpful, they are usually confidently incorrect. they tell you the problem is likely thing X, which in fact has nothing to do with the problem. (to be fair, this seems to be coming from whatever stuff google has added to the android build process, rather than gradle itself.)
these days, once gradle starts spitting errors, i know better than to read them. instead, i have to start thinking about when the build last worked, and what might have changed. if that path proves not to bear fruit, then it is time to trash that project completely and recreate it from scratch, which experience has taught me will take a lot less time than trying to “fix” the gradle build errors.
0 - https://gradle.com/customers
(Edit: Heh, TIL rage downvotes are a thing in HN as well.)
Or Facebook's Buck.
I do not work on Android apps, but I use Gradle in semi-large web app and lots of fat jar projects. Do you happen to know if there are any perf measurements that outline Gradle is slower?
Tricks that Maven, or the other build systems never required.
Buck looks quite interesting. Thanks for pointing it out!
Gradle has Android giving it wind on its sails, because a couple of people there are really into it.
Yet even Google's own teams rather use Basel and Soong instead.
If Clean Project is required to build the project, why isn't that part of the build process?
When I am tasked with fixong other peoples config I usually move things to the correct location, delete the corresponding configuration qnd then everything works (better).