Why I stopped using Spring
johannesbrodwall.com
johannesbrodwall.com
The task of dependency injection appears right after the decomposition of a problem: you cannot avoid it, so you either do it manually by constructing and wiring all necessary objects (self-managed singleton anti-pattern is quite common here, let his fathers burn in hell) or using a DI container. Unless you want to invent your own bicycle with poker and curvy girls (which may make sense in very specific cases, but not in general), you will use Spring, Guice or CDI.
How to choose the right solution? It always depends on requirements, not on generic concepts from theory of OOD. In small project you can follow KISS principle by sacrificing decoupling and wiring objects manually. In bigger one you always need to look at the other libraries and environment you are going to use. If it's a JEE container (a modern one, compatible with latest specs), your choice can be CDI. If you are going to work with GWT, it's Guice (it's the best for programmatic configuration, but lacks some features). In all other cases Spring 4 is the best option.
What's wrong with the talk about reuse vs decoupling? The author addresses the problem of sustainability of a system to changes by rejecting the core concept of OOD - the reuse - and avoiding the use of DI, just to avoid some hypothetic bug in implementation module. However, our industry developed a lot of tools and best practices to address such problems when writing reusable code: unit tests, SOLID (SRP is my favorite one), incremental compilers and smart IDEs. Avoiding reuse is like not using electricity if you afraid of fire.
I had an argument about DI with a friend months ago and it boiled down in his use (Guice) that it was only for testing components.
I think of DI as a big meta-constructor in the sky, it gives dynamic scope to a lexically scoped language. And the problem with it as we currently use it, is that it hides intent behind a config file so we can't read what the code is actually doing, only doing abstractly.
What if the tooling ghosted those abstract classes and put the concrete classes in their place with reading and navigating? It could effectively "statically link" in the IDE those dependencies.
As I already said, you always need to wire your objects. You do it, possibly, without realizing it, but you still do it. If you reject the idea of DI just because the code is bad and DI is "Not Invented Here", you will not do the wiring better. Writting custom DI is hard, and it's very likely that you will end with unmaintainable nightmare that needs to be rewritten completely. For 15 years I've seen this nightmare too much and never seen the successful projects with custom DI.
This is especially true with DI, which is a design principle and not a framework, countrary to popular belief.
I would also like to add that specific technologies such as xml are not inherently declarative. If some api or config is declarative it only means that it is well designed and that it's easy to express your intentions when using it. If you want counter-examples, look at imperative ant or declarative jmock.
I suspect this introduces extra complexity. I have not yet had the chance to try Guice (https://code.google.com/p/google-guice/) so I wonder if it solves many of Spring's problems (one of the top issues is verbosity of configuration files).
Also, don't forget that you can use @Resource (jsr250), not only @Autowired.
The author also says:
> So reuse and decoupling are opposing forces. I find myself siding with decoupling.
The developer has to make a balance between reuse and decoupling. In my opinion everything doesn't have to be 100% reused or decoupled.
But I don't like using auto wired in the main code because it means I am required to use that wiring for every use. I find that we want to use classes in a few different ways, and keeping the dependency definitions and configuration values in the XML decouples it from the code and increases both reusability as well as exposing the XML configurations after deployment so that a recompile isn't required in the field.
Taken to extremes I've also used Spring to configure a rudimentary ETL framework for example, where the entire pipeline could be (re-)configured post release.
Dependency glue (wiring) in runtime config helps keep objects decoupled, makes test writing easier, and eliminates any dependency on a specific IOC framework. Whether or not the wiring config comes boxed with the code or not is a completely different concern.
I'd be happy to see Spring config in a format other than XML (JSON, YAML, whatever), but even more than that, a complete elimination of any Spring config directly in Java files.
See here: http://docs.spring.io/spring/docs/3.2.7.BUILD-SNAPSHOT/sprin...
Money quotes:
>>>> In the end, creating a coherent, small system is to me of much higher value than to create one that is decoupled just for the sake of decoupling. Coherence and decoupling are opposing forces and I side with coherence.
>>>> So reuse and decoupling are opposing forces. I find myself siding with decoupling.
Pretty similar to Guice, but faster.
For small applications (both server-side and client-side) Spring 4 is as easy to use as Guice.
Cost-benefit uber alles! All of these things -- features, functions, frameworks, objects, patterns -- must pay rent!
And indeed, code without frameworks is so much smaller, cleaner and pleasant to work with!
I've done a medium sized spring project last year, and found the language quite good, but the framework itself and the general ecosystem really too cumbersome.
The only framework which I can recommend, is Dropwizard (http://dropwizard.codahale.com/), which tries not to be a framework, just a glue between some really nice libraries and tools.
I'll start with "raw" java next time i'll want to try playing with rest services.
If it isn't what you're looking for, I'd be curious to hear which of these qualifications it fails at.
Our product is a browser based web development tool that comes with its own middleware/framework with a UI built just for it. I think this approach while not as generic is superior because you get the benefit of real tooling not just a generic framework that you need to manually glue together.
Spring like many frameworks are designed to be generic and pluggable into other tools/IDEs, unfortunately once they become complex their benefit is greatly reduced for most projects.
Support us so we can continue to improve on the product, visual UI building and integration is on the horizon :)
For? If you are developing REST applications, the JAX-RS standard is great, lightweight, and mature. I have used both Jersey and RestEasy without any problems.
A simplistic example that comes to mind is a calculator module with a well-defined interface (interface in the Java sense of the term). Maybe there are a few different implementations of the interface available in the codebase.
Both implementations are reusable in the sense that I can plug one implementation in many places wherever the interface is supported. When I need something else, I plug in a different implementation. The module that has a dependency on the calculator module should be none the wiser since all it does is call out to a certain interface.
Am I missing something here? Maybe I didn't understand the OP's point well enough.
My understanding of reuse is when the same peace of code is used in different areas of the project. This could be different classes, different packages, different modules, etc. Now the more the code is reused, the more tight coupling between the two pieces of code i.e. change to the interface of the reused code 'could' mean change(s) to each and every place the reused code is being called.
Secondly, if you put reuse high up in the design requirement, what you sometimes end up with are very generic interfaces/classes that can be reused in lots of places as opposed to very specific interfaces/classes or unnecessary inheritence trees required to change the base class behaviour in those places where the required behaviour is 'slightly different'.
Lastly, not so long ago, DI containers did not support package private visibility. This means all injection (constructor, setter, etc.) required public visibility. This lead to a lot of developers also 'reusing' code even in places where they shouldn't just because they could i.e. it's right there!