News for hackers. Stuff that matters.
Re:Spring vs. Java EE by cle on Sunday April 09, 2017 @02:03PM (#14073510)
The Spring that I've used (the DI Framework, Spring Integration, Spring MVC) is mainly designed to simplify and standardize enterprise applications. Mostly this involves standard and automated ways to "wire" together applications. This includes DI, but also includes configuration (e.g. configuration to enable a deployment pipeline), communication between components/services (client and server mapping of messages in a message bus to their ser/de impl and schema definitions, database interfaces), service and UI implementations themselves (SpringMVC, Spring Boot), etc. The benefit is that Spring is a glue layer that integrates all these various pieces of "enterprise" systems with minimal boilerplate.

I don't have much experience with Java EE, so can't comment. My experience with Spring is not very positive--it enables and encourages applications and systems to have complex dependency graphs, and so often I've seen this result in giant balls of mud that, despite Spring's claim that it enables decoupled and modularized design, are rat's nests of unexpected coupling and hard-to-predict behavior.

Re:Spring vs. Java EE by ivan_gammel on Sunday April 09, 2017 @02:16PM (#14073578)
Spring (and latest JEE editions with better support of DI) no more encourages spaghetti designs than does manual wiring of objects, so usually these giant balls of mud are the result of project management and design mistakes, not the failure of the tool. In fact, properly designed system that uses DI is indeed decoupled (because you can limit the number of interfaces between components) and modularized (because you can wire dependency of one module on interface with implementation in another one). Moreover, it opens the way to plugin architecture, because application context definition can serve also as plugin definition and there exists discovery mechanism (e.g. classpath:/plugins/*.xml in plain DI or Spring Boot AutoConfiguration).
Re:Spring vs. Java EE by cle on Sunday April 09, 2017 @03:55PM (#14074060)
It enables such designs, by making it easy for someone to add more crap into your ball of mud. Not everyone on your team is as smart or experienced as you. When their back is against the wall with a deadline...just throw some more beans in there, who cares how they're wired together, it's all handled by Spring!

Well, you care when you have an unexpected complex circular dependency or you need to refactor and you suddenly discover how complex your dependency graph has unintentionally become.

By "decoupling" and "modularization", I'm not talking about at a code-level by using interfaces. In my opinion, that kind of decoupling and modularization isn't very important, especially when it comes to application glue--because the glue (Spring) is what decides the backing impl's of all those interfaces. That's where the important dependencies lie, and that's where your big ball of mud accretes.

Re:Spring vs. Java EE by kazagistar on Monday April 10, 2017 @01:52AM (#14076371)
> When their back is against the wall with a deadline...just throw some more beans in there, who cares how they're wired together, it's all handled by Spring!

I just came across a controller in our code that had over 50 spring injected services. Our entire code base is only like 5 years old.

The problem is that this is my first job out of college... even if I know things are messed up, I don't really have an example of an application like this that is actually done right.

Re:Spring vs. Java EE by qw on Monday April 10, 2017 @04:05AM (#14076802)
I prefer controllers to have only one service. A controller should do as little as possible. Its responsibility is just to pass data from the request to the service.

The same should apply to repositories unless it is absolutely necessary. It should ideally just know enough to manage itself

A service may reference other services if it needs to coordinate actions. We need to be careful not to make huge services that contains too much logic though

I have found that this pattern makes it not only easier to structure the application, but also much easier to make mocked tests.

Re:Spring vs. Java EE by ivan_gammel on Monday April 10, 2017 @01:47AM (#14076348)
It is not a tool problem. Programming tools always address two problems: coding performance and coding quality. But the design, the architecture is not something that could be fixed by a tool. Frameworks may add or remove some constraints, but there's always enough space for the side effects of human creativity. People always break or misuse the tools, creating the balls of mud. It's not a problem with these tools, it's a problem with organization of development process, with competencies of decision makers, with inadequate constraints and unclear requirements. It's easy to blame the tool, throw away the ball of mud and start from scratch with fancy new tech. But in the end you'll get the same ball of mud, because you have ignored the root causes.
Re:Spring vs. Java EE by jacques_chester on Sunday April 09, 2017 @02:31PM (#14073643)
I think maybe this comes down to the kind of injection. If you rely on variable or setter injection, you can easily create a kind of dark matter that invisibly warps the flexibility of the project.

I and others have generally found that using Constructor injection greatly decouples a design and simplifies testing.

And the Spring team have been saying so for at least as long as I've paid attention to the question[0]:

> Constructor-based or setter-based DI?

> ...

> The Spring team generally advocates constructor injection as it enables one to implement application components as immutable objects and to ensure that required dependencies are not null. Furthermore constructor-injected components are always returned to client (calling) code in a fully initialized state.

> ...

[0] https://docs.spring.io/spring/docs/current/spring-framework-...

Re:Spring vs. Java EE by tigershark on Sunday April 09, 2017 @08:37PM (#14075142)
They are two different tools needed for two different jobs. Constructor injection is for mandatory dependencies, setter injection is for optional dependencies. If you are writing a plugin application and some modules are optional then you cannot use constructor injection because when the optional module is not present you cannot start your whole application. In 99% of the cases obviously constructor injection is the way to go.
Re:Spring vs. Java EE by twic on Sunday April 09, 2017 @06:11PM (#14074608)
If you want to see big balls of mud created using setter injection, you're welcome to visit any of the projects i worked on when i was at Pivotal!
Re:Spring vs. Java EE by jacques_chester on Sunday April 09, 2017 @08:47PM (#14075190)
I am guilty of this too. It's why I'm a bit of a constructorist these days.
Re:Spring vs. Java EE by twic on Monday April 10, 2017 @04:54PM (#14082455)
Aargh. I meant using constructor injection. It didn't save us.
Re:Spring vs. Java EE by ivan_gammel on Sunday April 09, 2017 @03:37PM (#14073983)
Nope. There is no difference between injection types from the coupling perspective, simply because neither blocks anything bad from happening in your architecture. There are reasons to prefer constructor injection in many cases, but it has nothing to do with modularity or coupling.
Re:Spring vs. Java EE by spiralpolitik on Sunday April 09, 2017 @05:11PM (#14074390)
With Constructor based injection its easier to see layering and coupling issues as once your constructor gets more that 3-4 parameters then it starts becoming blindingly obvious that the class has too many dependencies and needs to be refactored. This helps keep the bad out of the architecture.

The main reason to favor constructor based injection is that it stops objects becoming 'live' in an inconsistent state. I've seen actual production issues with setter based injection that can only be explained by the object being available for use before all the setters have been called.

Re:Spring vs. Java EE by ivan_gammel on Monday April 10, 2017 @01:52AM (#14076373)
Your arguments are valid on why constructor injection should be preferred. However, what are you talking about is the human-made decision: "Stop adding more parameters to constructor". The tool does not force you to build high-quality architecture, it is your choice based on your experience and skills. Other people who are not yet aware about the consequences may still make wrong design decisions and they'll be ok with lots of parameters.
Re:Spring vs. Java EE by jacques_chester on Sunday April 09, 2017 @04:39PM (#14074250)
I disagree.

Constructor injection in Spring is more test-friendly; in turn that tends to allow us the liberty of more aggressively modularising the design. With other injection types either more bookkeeping is required to cleanly set up tests; or alternatively, "unit" testing becomes more integration-esque.

It's a second-order effect felt in the many small decisions that lead one to the mudpit.

That's why I used the analogy of dark matter. It's not directly observed, but it has gravity.

Re:Spring vs. Java EE by EdwardDiego on Sunday April 09, 2017 @08:06PM (#14075039)
> Constructor injection in Spring is more test-friendly

These are my thoughts too. No reflection or @MoreAnnotations to inject dependencies. I have an aversion to setter/field based injection because it allows you to instantiate an object in an incorrect state.

Re:Spring vs. Java EE by jacques_chester on Sunday April 09, 2017 @08:50PM (#14075206)
> I have an aversion to setter/field based injection because it allows you to instantiate an object in an incorrect state.

Oh yes. I recognise that JavaBeans had its reasons for being, but then you get to JPA and it's time for all the boggling.

Re:Spring vs. Java EE by lazulicurio on Monday April 10, 2017 @06:50AM (#14077386)
My personal pet peeve is bean validation. The goals of the API are laudable, but the fact that the implementation is annotation-driven drives me nuts.

Annotations are fine for intra-project code contracts, but using them for external validation means that if you, say, deploy on a application server with an older version of Jersey, you're suddenly SOL when none of your validation logic is executed.

Re:Spring vs. Java EE by twic on Sunday April 09, 2017 @06:15PM (#14074629)
> Constructor injection in Spring is more test-friendly

If you get in the habit of using the Spring test support, where classes under test get injected, then all kinds of injection are equally friendly, and the tests don't give you feedback on the weight of the dependencies because Spring does the heavy lifting.

And, in my experience, where you do inject dependencies by hand, the design pressure is actually towards coarser-grained objects. Why? Because you need to have enough functionality to test; with fine-grained objects, you have to construct and assemble an object graph in the test, whereas with coarse-grained objects, you just new up one thing.

Re:Spring vs. Java EE by EdwardDiego on Sunday April 09, 2017 @08:04PM (#14075033)
> If you get in the habit of using the Spring test support, where classes under test get injected, then all kinds of injection are equally friendly, and the tests don't give you feedback on the weight of the dependencies because Spring does the heavy lifting.

How do you handle the Spring context start-up time? In Spring projects I've worked on, across hundreds of unit tests it's non-trivial. But I don't make any claim to know if we were doing Spring right or not.

Re:Spring vs. Java EE by twic on Monday April 10, 2017 @04:53PM (#14082446)
The context can be reused between tests. If you're not storing data in beans (which you normally shouldn't), this works well. There is a bit of subtlety in that the framework might have to create multiple context for different configurations, but each of them is reusable.

Running a single test is a bit of pain, but running the whole suite is not a lot slower than if it didn't use Spring.

Re:Spring vs. Java EE by jacques_chester on Sunday April 09, 2017 @08:52PM (#14075221)
If you're firm on constructor injection, you can typically test the object in complete isolation without necessarily using mocks, without Spring having to be involved.

Or you can use mocks and Spring Boot's test annotations.

But with field/setter injection, that choice isn't as easy.

Re:Spring vs. Java EE by orless on Sunday April 09, 2017 @03:08PM (#14073822)
"... so usually these giant balls of mud are the result of project management and design mistakes, not the failure of the tool."

It is the failure of concepts so if the tool brings the right concepts, it helps avoid such design mistakes in the first place.

Re:Spring vs. Java EE by ivan_gammel on Sunday April 09, 2017 @03:42PM (#14074005)
That's too generic statement to be applied to anything. Some specific failures of tools (what exactly?) may be the cause of other issues, but it's not the law of nature. You can hit your finger by a hummer, but it's not because hummer brought the wrong concepts - it served millions of people to build their homes, their farms and fences, it's just because sometimes you miss the nail.
Re:Spring vs. Java EE by orless on Sunday April 09, 2017 @03:53PM (#14074044)
It is only generic if you completely drop the context of the discussion (Spring and dependency injection). My point is that Spring brings DI/IoC concepts which help build healthy projects.
Re:Spring vs. Java EE by ivan_gammel on Monday April 10, 2017 @01:57AM (#14076391)
There are so many counter-examples in the world of poorly built projects, that I don't really understand how did you came to this conclusion. DI/IoC is just a pattern, there's no way it could guide you to good architecture itself. Spring is just a tool, which adds some constraints, but which does not force you to make business decisions on scope of different domains or interaction between them that might lead to strong coupling and low modularity.
Re:Spring vs. Java EE by orless on Monday April 10, 2017 @08:16AM (#14077830)
I'm not sure where I stated that Spring forces "to make business decisions on scope of different domains or interaction between them that might lead to strong coupling and low modularity".
Re:Spring vs. Java EE by ivan_gammel on Monday April 10, 2017 @01:07PM (#14080389)
Let me explain in other words. You said: >It is the failure of concepts so if the tool brings the right concepts, it helps avoid such design mistakes in the first place. In the context of Spring/DI it does not make sense, because no matter what, some developers do and will be doing design mistakes related to coupling and modularity and some will write great code, but this is neither feature nor failure of the tool. DI/IoC is too low-level concept to influence application design, because in case of Spring it affects individual classes, not components, namespaces or subsystems. It is the responsibility of the developer to make decisions and create designs that make application modular, designs that restrict number of dependencies etc, and, in general, to do all the work required to avoid creating "giant ball of mud". The result of this work done with Spring or any other IoC/DI framework will not be very different from manual instantiation of objects and wiring.