8 ms·
Maven at its core is very simple. The lifecycle is well-documented and so is the dependency resolution. Many coworkers I've worked with have called it complica
by wellpast 9y ago
Maven at its core is very simple. The lifecycle is well-documented and so is the dependency resolution.
Many coworkers I've worked with have called it complicated and then I find out they really haven't learned the (very simple) lifecycle and how build behavior gets attached, etc. This is all very simple but it is something to learn.
I don't know why this happens. I think programmers are so used to imperative (ant/Grunt/etc/etc) programming/building that it becomes confusing for them when they encounter a declarative system. And their brain revolts. Because they are like how do I just do a thing (i.e., copy some file somewhere, call a "build" method, etc, etc.)!? Instead of realizing the value of the declarative + idiomatic Tao and learning it...they say no, no gimme gimme let meee do it. Much like my two year old. And then I'm left fighting non-reproducible builds and getting their projects going in my IDE like it's somehow 2005 again. But Maven is great, declarative systems -- especially declarative build systems are the optimal way to do builds (in most cases).
- greenhouse_gas 9y ago>I don't know why this happens. I think programmers are so used to imperative (ant/Grunt/etc/etc) programming/building that it becomes confusing for them when they encounter a declarative system. Because, after all is said and done, programming is about having your computer "do" something - whether it be to write some bytes to the disk or to send some bytes to the network. It's just that sometimes there's an advantage to use an abstraction - such as say "SELECT * FROM TABLE WHERE ROW_ID =14" is an abstraction over something like "for (int i =0;i<table.size();i++) if(table.row[i].elem[1] == 14) ... ", but often you don't need such a complicated abstraction, you just "need something done" before (or after) building. Whether it be that you want to download an HTML file to package, or to move the resulting file to a certain directory, or to clean a certain directory, your build language shouldn't be that arcane that you have to create a "build.sh" to get things done.
- wellpast 9y ago— “SELECT...” is not an abstraction for “for...”, by the way. Abstractions are not for specific implementations. “SELECT...” is an abstraction for specifying Sets etc. — Maven is simple, not arcane. I’ve produced countless “custom” builds with wild variations of need and never has Maven let me down. In some sense this is easy to prove (see maven-antrun-plugin); however, Maven’s core plugin/idioms supports 90+% of use cases I’ve seen over many many “weird” build requirements. To your example, “copying files” is fundamental; however you have to learn the idiomatic way to do it if you want to reap the benefits. Otherwise, just call out to maven-antrun- or similar. But then you’re chasing your tail.
- greenhouse_gas 9y agoI've never used Maven, only gradle. The issue with convention over configuration is that you don't see how things should happen, because they're hidden behind the convention. For example, what are the steps behind your Android build? Can you tell me exactly what steps gradle takes when you run gradlew assembleDebug? So if for whatever reason you need to modify something, you're completely on your own.
- frant-hartm 9y agoSure.. $ gradlew -m assembleDebug Learn the tools you use..
- lmm 9y ago> after all is said and done, programming is about having your computer "do" something - whether it be to write some bytes to the disk or to send some bytes to the network. Not always. Often, particularly in scientific computing, you just want to ... compute ... a result. I mean sure, the computer needs to display the result to you, but the computation isn't about displaying it, it's about computing it. Just like adding up a bunch of numbers on a calculator isn't about getting the calculator to "do" anything. > often you don't need such a complicated abstraction, you just "need something done" before (or after) building. Abstractions should be simpler than the thing they abstract over, that's their whole point. Treating my computer's memory as a flat array of numbers is simpler than thinking about how much current is flowing through each RAM wire. "Compile all source files" is simpler than "execute javac Foo.java, then execute javac Bar.java, then..." > Whether it be that you want to download an HTML file to package, or to move the resulting file to a certain directory, or to clean a certain directory, your build language shouldn't be that arcane that you have to create a "build.sh" to get things done. You shouldn't need a build.sh, agreed, but nor should you need particular things to happen to particular directories. Maven has great support for things like "package my documentation in the standard way". It's only when people try to fight it about the low-level details that they really shouldn't be caring about that they run into trouble.
- Feeble 9y agoCould not agree more. Every time I have seen an implementation the imperative type (ant etc) it leads to different ways of doing the same things so over multiple projects things just gets really complicated and difficult to maintain.
- guelo 9y agoI think it happens because maven has poor documentation, a ton of unexplained "convention over configuration", and very strong poorly explained opinions about how you must structure your project. Basically it's a ton of inflexible magic. Also, the attitude in the maven community that people that want to deviate from the god-given-way are two year old children.
- pjmlp 9y agoThe Maven manual is quite good, and there are plenty of books available for those that bother to sponsor development.
- lmm 9y agoMaven's documentation is great, and the project structure is well explained. Inflexible yes, magic no.
- hugi 9y agoThis is basically the exact opposite of my experience with Maven. The documentation feels very clear and good to me and I've always found answers to my questions. I don't recall ever encountering "unexplained inflexible magic".
- harlanji 9y agoIn around 2008 I co-wrote a set of maven javascript mojos (before NodeJS), incl QUnit test integration et all. I collaborated with another fellow on the other side of the world. Documentation was stellar. IIRC, to extend, even the upgrade from M2 to M3 didn't affect most community mojos.
- barrkel 9y agoMaven dependency resolution is not great, mind. For example, if you have a multi-pom project with a parent pom (not unusual in a medium-sized codebase, never mind large), and you have unit tests in your child poms, they'll get executed with dependencies resolved locally for that child pom, and not with the global dependency resolution that satisfies all constraints that need satisfying at the parent level. The upshot is that you easily end up running tests using different versions of dependencies than what you deploy with, misleading you into thinking things are working, and can end up with hilarious NoSuchMethodError at runtime. The "solution" is to pin your versions using dependencyManagement, but that's no real solution at all, not least because it's neither automatic (though dependency convergance using Maven Enforcer helps, and I've developed some scripts that help further) nor is there an easy route forward when you want to bump versions safely.
- wellpast 9y agoHaving the choice to pin versions separately per module is a desirable feature, especially for multi-module builds with different deploy artifacts. So this is no problem at all; deciding which versions to pin per artifact/module is the programming job — no tool can automagically decide this for you correctly.
- barrkel 9y agoI'd prefer the choice to specify versions in submodules, with the versions of dependencies chosen and pinned via the global resolution, producing a fixed set of dependencies in a file I can check in, like Gemfile.lock in the Ruby world.
- lmm 9y ago> For example, if you have a multi-pom project with a parent pom (not unusual in a medium-sized codebase, never mind large), and you have unit tests in your child poms, they'll get executed with dependencies resolved locally for that child pom, and not with the global dependency resolution that satisfies all constraints that need satisfying at the parent level. As it should, otherwise you'd get the even more hilarious situation where your tests pass when you run the single-module build but fail when you run the multi-module build. > The "solution" is to pin your versions using dependencyManagement, but that's no real solution at all, not least because it's neither automatic (though dependency convergance using Maven Enforcer helps, and I've developed some scripts that help further) nor is there an easy route forward when you want to bump versions safely. This is not a maven issue, it's a combination of Java's flat classpath and the reality of diamond dependencies on versioned libraries in any system. We could allow multiple versions of a transitive dependency on the classpath but then you get Rust's hilarious "expected Foo but was Foo" type errors. Java 9 modularisation should reduce the problem by allowing modules to have explicitly private dependencies, but the problem exists everywhere.
- tbranyen 9y agoGulp is imperative, Grunt was designed to be used declarative.
- mypalmike 9y ago> they really haven't learned the (very simple) lifecycle Building is a simple concept: dependency DAG + inputs -> artifacts. The "->" here can involve arbitrary intermediate artifacts and steps. Maven ignores this fundamental concept of building. Rather than treat interim dependencies as part of the DAG, there's a hard-coded recipe of lifecycle steps. This is why I personally cringe at maven - it has nothing to do with the fact that it's declarative (virtually every build system is largely declarative). It has everything to do with hard-coding one particular set of build steps into a supposedly general build tool.
- he0001 9y agoI was under the impression that the build chain in maven is pretty defined and not arbitrary. It performs the same thing over and over again, being highly reliable. It’s pretty extensible since you can tweak your own build steps if you want. And in the general case you don’t need to define a thing?