SBT is easy to use at the beginning, simply because the build files are 1/10 the length of a Maven XML build description, the console output looks better, the build REPL has lots of commands that make things easier, and the simple projects just work fine.
Once you start to dig deeper, you find out that setting multimodule projects is still easier in SBT. And if you decide to dig deep and really learn the build tool, it doesn't really matter which one you choose. But devs that chose SBT as their Scala build tool will probably keep using it.
> SBT is easy to use at the beginning, simply because the build files are 1/10 the length of a Maven XML build description, the console output looks better, the build REPL has lots of commands that make things easier, and the simple projects just work fine.
The build REPL has lots of commands that aren't documented, and when you search for tutorials the commands have changed (e.g. runMain is apparently now run-main, and if you write runMain you get the wonderfully helpful error "Expected ';'"). There's nothing so simple as Maven's list of phases https://maven.apache.org/guides/introduction/introduction-to... ; instead each project has its own slightly different set of build commands.
> Once you start to dig deeper, you find out that setting multimodule projects is still easier in SBT. And if you decide to dig deep and really learn the build tool, it doesn't really matter which one you choose.
Disagree. Maven multimodule projects are very simple: you can have a module that contains a list of submodules to build and... that's it. Importantly, every submodule acts exactly like a normal top-level project, so if you only ever want to work on one module you don't have to understand anything about the bigger project. And moving between single-module and multi-module projects isn't a big conceptual leap.
SBT multimodule projects are not only their own unique thing, they make the above problem even more confusing, because each project has its own slightly different set of build commands, and each module has a slightly different subset of them that works.
"runMain" is still "runMain", I don't know where that comes from. There are lots of available commands indeed, due to the nature of SBT, but a basic workflow always uses the same commands: compile, test, run. Any extra tasks used usually come from plugins, just like in Maven. And reading documentation is needed for configuring and running those, just like in Maven. Projects should document why each plugin is included, and how to do things, because every project is indeed different. The difference is the extra configuration needed by each plugin is about 1/10 the size.
Maven multimodule projects are strange. Yes, modules can work without knowledge of what's above them, but that's not usually what we want to do, because it means lots of duplication (e.g. dependencies) which can then lead to inconsistencies. And if the common settings are defined within the parent project, it stops being self-contained. SBT accepts this reality and that's why multimodule projects are a thing. And having multiple subprojects in SBT doesn't mean that suddenly some of them work and some don't. By default, every project has the same settings (save for the obvious ones, like where the sources are). Any extra settings and task definitions just tell SBT to do extra things when certain tasks are run. One quick example: if you enable the integration test configuration just for some subprojects, the ones that don't have them don't start to fail. They correctly report a "successful, 0 tests run, 0 test failed". By the way: creating a separate integration test config in Maven is painful, up to the point that people recommend to just add a new subproject that contains them. Yay, more nesting!
Regarding SBT current shortcomings: that article correctly points out lots of issues, like the lack of tooling. To this day, IntelliJ still has issues downloading the correct SBT sources. And when they work, there's no easy way to find the actual code that does the work. That should be improved, because for lots of plugins, a quick look at the source is just what's needed when working on the build. Namespacing is a problem too. The internal complexity of the core SBT concepts is complained about too, but that's not as solvable as the other two things.
All in all, Maven and SBT are different tools that focus on different issues, and choose different sides in the consistency vs flexibility tradeoff.
> "runMain" is still "runMain", I don't know where that comes from.
Ah, I got it backwards: old tutorials say to use "run-main", and if you do run-main now you get "Expected ';'".
> There are lots of available commands indeed, due to the nature of SBT, but a basic workflow always uses the same commands: compile, test, run. Any extra tasks used usually come from plugins, just like in Maven. And reading documentation is needed for configuring and running those, just like in Maven.
But in Maven you don't need to read any documentation if you're just building the project, because every project has the exact same lifecycle. If you want to add or remove plugins to make the build do something different then you need to read the documentation of those plugins, sure, but you don't have to know anything about the plugins if you're just working on the code. E.g. if an SBT project is packaged for docker then you'll have to run some docker-plugin-specific command to do it (and you've got no way to discover which submodule you're supposed to run it in), whereas if a maven project is packaged for docker then you just run "mvn deploy" as usual.
> And if the common settings are defined within the parent project, it stops being self-contained. SBT accepts this reality and that's why multimodule projects are a thing.
Parent projects work consistently whether or not you're using a multimodule project, which is another problem with SBT - it's really confusing to share parts of a build definition between more than one project, to the point that most people copy/paste instead. With maven you can do a very natural, gradual progression from single module -> multi-module project -> multi-module project where the parent is its own module -> independent projects using a shared parent (e.g. an organisation-level parent). It's another case of a hierarchy working much better than a grid.
> By the way: creating a separate integration test config in Maven is painful, up to the point that people recommend to just add a new subproject that contains them. Yay, more nesting!
Think of the people who come to join your project! I've seen SBT modules with 5 different scala source directories and no obvious relationship between what depends on what, and good luck getting any IDE to understand whether test depends on integration-test or vice versa (most will give up and just build everything together, which is fine until you add something that works in the IDE and then errors when you build it with SBT).
A separate submodule is a much better approach - tools and people are much better at handling "module A depends on module B" than "this source folder depends on that source folder".
Although the silly "Expected ':'" is still there, the newer SBT versions show better output, there's even a "did you mean" feature.
Regarding "discovering which submodule you're supposed to run commands in": this is a non-issue. Commands are either run under the obvious subproject (e.g. "api/run", "business-logic/test"), or are run as top-level commands. This is true 99% of the time. I have a fairly complex project open right now, and I just run "docker:publishLocal" to create two separate Docker images, one for each subproject that includes the appropriate plugin. I think this is better than overloading a single command. SBT projects usually have a small readme describing what is the command for any specific task you're supposed to do. In Maven, you know the commands, but you need to read to ensure what they do (does "deploy" push to an artifact repository, does it create a container image, does it create a deb package, or does it create a standalone jar?).
The use case where a multimodule project becomes multiple projects is more gradual in Maven, I fully agree on this. The problem, as I said, lies in that child Maven projects are not self-contained. They usually depend on information declared in the parent builds. This breaks the assumption that people can work on a project without worrying about the parent project.
Finally, source dependencies are explicit in SBT save for the base case "test depends on main". Everything else must be specified, so it's either there in the build file, or added as part of a build plugin. It can also be checked from the REPL. And building from the IDE is a dumb mistake if the IDE doesn't use the correct build tool underneath: the build is there for a reason and the IDE shouldn't bypass it.
> does "deploy" push to an artifact repository, does it create a container image, does it create a deb package, or does it create a standalone jar?
"package" creates some kind of package, "deploy" pushes it to some kind of artifact repository. The details of what kind of package and what kind of repository will vary from project to project, but you don't need to know them to start work on the project. In theory there could be projects out there that do surprising things (after all, nothing actually stops you from configuring your build to push a container image to a repository when someone runs "mvn test"), but the overwhelming majority of projects find a way to fit themselves into the maven lifecycle, and it really reduces the "where do I start" effect when you check out a new project: I don't have to read the build file or hunt for documentation, I can run "mvn install" and see what it does, and be confident that that's "how you build this project".
> The problem, as I said, lies in that child Maven projects are not self-contained. They usually depend on information declared in the parent builds. This breaks the assumption that people can work on a project without worrying about the parent project.
Well, SBT projects also come with a bunch of default tasks that aren't defined explicitly in their project definition; some of them are defined by plugins and some of them are defined... somewhere (I genuinely don't know where the tasks that are available by default come from, or how to see a list of all of them except by using the interactive commands). So an SBT project is not self-contained in that sense either. In maven anything that's not explicitly defined in the project is coming from its parent pom, which is either the default parent pom or an explicitly specified one, and the default parent pom is a real pom that you can look at that follows the normal rules.
So you do have to understand the concept of a parent pom, but it's not an extra thing that you have to understand, because the default parent and any parent pom you're using in a multi-module project work exactly the same way.
> And building from the IDE is a dumb mistake if the IDE doesn't use the correct build tool underneath: the build is there for a reason and the IDE shouldn't bypass it.
Yes and no: the IDE has a bunch of knowledge of its own that the build tool doesn't, such as which files the user has changed, or which specific test the user has asked to run, or which import the user wants to add a dependency for. So I don't think the idea of the IDE dumbly invoking the build tool and letting it do its thing works (particularly in a language like Scala where you have to rely heavily on incremental compilation if you don't want enormous build times); instead there needs to be a deeper integration where the build tool and the IDE share a structured model of the project, and the IDE can perform a build via that model (effectively embedding part of the build tool as a library, if you like). Likewise I don't want to invoke a separate build REPL to understand the project definition, I want to be able to explore it within the IDE.
SBT's deeper problems are the 4-dimensional data model and the 3-layer meta-interpretation model. Probably not the best option for really complicated builds, but it's great for simple builds and I appreciate the tireless open source work the folks do to keep it maintained!
Once you start to dig deeper, you find out that setting multimodule projects is still easier in SBT. And if you decide to dig deep and really learn the build tool, it doesn't really matter which one you choose. But devs that chose SBT as their Scala build tool will probably keep using it.