Curious about the future of data-driven systems? Join our Data Engineering roundtable and learn how to build scalable data platforms.
Data Engineering: The industry has come a long way from organizing unstructured data to adopting today's modern data pipelines. See how.
Stats
| Reputation: | 1193 |
| Pageviews: | 872.4K |
| Articles: | 13 |
| Comments: | 30 |
Comments
Sep 25, 2019 · James Sugrue
Or you could have realized that it's actually Groovy code?
You might want to take a more polite approach instead of assuming people don't know what they are writing about. Mind you, this is code I wrote 5 years ago and I'd probably replace Hystrix with Resilience4j if I had the choice today.
Dec 07, 2017 · Theodore Ravindranath
This means you have to separate your datastructures as well. If you have infrastructure concerns (like JSON) seeping into your application or domain logic, you're setting yourself up for a world of trouble. Even with Spring REST I'd advise to split them up, otherwise you'll end up with a @JsonFormat in your domain code because you wanted that date displayed differently in your JSON (and that's one of the more clean approaches...)
Sep 04, 2017 · Mike Gates
I'm not really sure about that because each and every example in this article contains RuntimeException subtypes. You don't declare these in a throws clause or catch them, unless there's something meaningful you can do with them. Exception handling is something that shouldn't be done directly, expecially RuntimeException types. You let them bubble up to the surface and handle them there.
The core of the article is correct, but the implementation is very misleading.
Perhaps a mistake nr. 8 can be added: Catching RuntimeException or its subtypes. But then he'd need to rewrite his entire article.
Sep 01, 2017 · Mike Gates
Interesting, but I don't see the point in declaring RuntimeException classes (like IllegalArgumentException) in the method signature. Say your method is using a third party framework, are you going to declare all their RuntimeException types if you use one of their APIs?
The gist of RuntimeExceptions is that there's no point in catching them, as there is nothing as a coder you can meaningfully do with that exception, except for maybe logging and rethrowing it (and there are better ways to do that).
Aug 24, 2017 · Michael Tharrington
In any case, making a rule to create default constructors because some frameworks can't handle non-default constructors or immutable objects isn't the best way forward. If a framework requires a default constructor, you should create a specific wrapper class for that framework so that the concern of the default constructor is isolated and can be removed easily later. Modelling your domain through framework constraints is not good design.
Aug 24, 2017 · Michael Tharrington
JPA can handle package private default constructors, as of Java 8 using Jackson with non-default constructors is a breeze... In most cases all frameworks have a way to handle non-default constructors. My point is: if you can avoid public default constructors, you should do so.
Aug 22, 2017 · Michael Tharrington
The problem with your approach is that it encourages POOP programming and moves away from domain classes that enforce invariants. For example. one should never be able to change the ISBN of a book. But due to your default constructor rule, you're effectively forcing people to write a setter. If you want to mutate a field in your example, it needs to be prefixed with set. To get the value, it's get. So basically you've exposed a private field publicly, breaking encapsulation and tell-don't-ask principles. I thought our ecosystem had finally moved away from the JavaBeans specification.
Aug 22, 2017 · Michael Tharrington
Correct, but immutable object don't have default constructors nor setters, which violates your rules... But declaring method parameters as final is always a good idea, if not for avoiding bad habits... For example, it's impossible in Kotlin to reassign parameter references (final forced).
May 23, 2017 · Mahan Hashemizadeh
Nice article, although I do have some concerns regarding dependency inversion. At the moment, your perifery can perfectly inject domain services because of the transitive dependencies. You should separate your boundaries from your use cases on a module level in order to make sure architectural boundaries are enforced. I.e. CustomerAdaper should have an interface that makes it possible to decouple the domain from the rest of your system. Especially when using Spring Boot you want to do this just because it's so easy to inject stuff.
Mar 08, 2017 · Grzegorz Ziemoński
Well, actually you can do this, but you can't use @Component. You can use the more standard @Named annotation when enables you to defer the choice of framework (Java EE or Spring). Same thing with @Transactional, you need to use the javax one and on the Spring one. If an annotation forces you to choose a framework on the application or domain layer, it's either a smell or a conscious decision to accept technical debt in your architectural design.
Mar 08, 2017 · Grzegorz Ziemoński
I'm fairly certain something is missing there. The use case is getting the details of a codecast by its permalink and the response model is actually missing the codecast :). But you *could* have a use-case called 'CheckExistenceOfCodecastUseCase' that actually does that and that would be perfectly acceptable. It takes a bit of time to get your head around the fact that you actually don't have any boundary services: it's a single use case per class instead of having all the use cases as methods on a service.
Mar 08, 2017 · Grzegorz Ziemoński
Nice write up. It's fairly easy to defer any framework choice to the edge of your system. It's perfectly possible to have your domain and application layer completely devoid of any large framework like Spring. Given the fact that large systems tend to outlive major releases, I can't say I agree with your second consideration when to use clean architecture. I've demonstrated this in a small example: https://github.com/lievendoclo/cleanarch and discussed some findings in an article (https://www.insaneprogramming.be/article/2017/02/14/thoughts-on-clean-architecture/).
Feb 28, 2017 · Grzegorz Ziemoński
Well, you can actually create an persistence gateway interface that is able to persist your domain. In the implementation of that interface you can map your domain onto another class that can then be annotated with JPA annotations. Okay, you'll add a mapping to your architecture, but it'll keep your domain clean.
That being said, adding JPA annotations to your domain can be a possibility if you accept the technical debt there (there is a thing as acceptable techical debt on a design level) and as long as the existence of those JPA annotations do not interfere in how you would model your domain model. If you need to change you domain model because otherwise a certain JPA construct wouldn't work, I'd be very careful and even hesitant to apply such changes,
Feb 27, 2017 · Grzegorz Ziemoński
Good article, not so sure whether I'd agree that the UI would be able to directly communicate with the domain. Too many possibilities for abuse. So in other words, I'd prefer the call stack can go outside-in, but only the adjacent layer.
I wonder whether your next article is going to be on Clean Architecture :).
Oct 05, 2016 · Nikhil Wanpal
While interesting, I fail to see any real value in such benchmarks. As far as I can tell, any DI container starts up under 10ms and all fetches are in the microsecond and nanosecond range. If a one-off startup of 10ms is bothering you, you really have some serious issues. Using a 5 million multiplier you can prove just about everything, but the business value or practicality of such a multiplier is zip, because you'll never ever see such behavior.
Oct 04, 2016 · Nikhil Wanpal
This article points out a lot of differences, but it's all but opinionless. It's clear the author has a preference for Guice, but it's only halfway through that this leaks into the article. Too bad, but I was probably expecting too much when hoping to read an objective comparison between 2 DI frameworks...
Jan 07, 2015 · grspain
Christ... what a piece of FUD! Clearly a case of 'I don't get it, so I'm against it'.
If you really want you objects to be able to be self-persisting, take a look at GORM. A small issue might be... that it's using an ORM (Hibernate) in the background, but in most cases you won't even notice it's there.
And on writing your own transaction wrappers using SQL statements: have fun in a distributed environment using JMS or AMQP, or just 2 databases at the same time.
And if you're not using an ORM, then at least use something like Spring's JdbcTemplate, which handles those nasty things like transactions for you. Oh, and you don't need to write your own rowmapping system.
To finish: it's not because you CAN use an ORM, you need to use it for everything! Read up on things like CQRS and polyglot persistence to see what I'm talking about.
Oct 03, 2014 · Alla Redko
I updated the source post, the plugin has now been published to my bintray account (see source post for more details) and will be synced to jcenter shortly.
Aug 30, 2014 · james anderson
Ron,
Thanks for your reply. It's great to hear that the issues I pointed out are being addressed. However, I still don't see how you can use swagger in a distributed microservice environment: you'll still have a single swagger spec file per deployment. What would really help is to have an aggregator that merges multiple swagger files into a single one (something like what Netflix does with Turbine for real-time streams like Hystrix).
That being said, I also wrote a follow-up on the article describing possible alternatives to Swagger. Swagger, as it currently stands, is a top down approach. This sort of limits the use of Swagger to documentation only (like Javadoc). Frameworks like RAML work bottom up, enabling you to specify the API first and write the implementation afterwards (unit testing as you go against the specification). With 2.0, it looks like you're going the same way. In fact, reading your site you're almost copying what RAML does already, except for some (albeit cool) minor additions. So why would I choose Swagger 2.0 over RAML (which actually has none of the Swagger's current annoyances)? It's also dead-easy to use with Spring MVC. On that subject, I still baffles me you don't include support for Spring MVC out of the box! You support Play, Dropwizard, CXF, Resteasy, ... but you don't support the most popular web framework (I'm not saying that, the statistics do) and leave it up to an external library to do the integration. Again, another dependency and another possibility on unwanted transitive dependencies.
In any case, I'll join the Google group :).
Aug 30, 2014 · james anderson
Ron,
Thanks for your reply. It's great to hear that the issues I pointed out are being addressed. However, I still don't see how you can use swagger in a distributed microservice environment: you'll still have a single swagger spec file per deployment. What would really help is to have an aggregator that merges multiple swagger files into a single one (something like what Netflix does with Turbine for real-time streams like Hystrix).
That being said, I also wrote a follow-up on the article describing possible alternatives to Swagger. Swagger, as it currently stands, is a top down approach. This sort of limits the use of Swagger to documentation only (like Javadoc). Frameworks like RAML work bottom up, enabling you to specify the API first and write the implementation afterwards (unit testing as you go against the specification). With 2.0, it looks like you're going the same way. In fact, reading your site you're almost copying what RAML does already, except for some (albeit cool) minor additions. So why would I choose Swagger 2.0 over RAML (which actually has none of the Swagger's current annoyances)? It's also dead-easy to use with Spring MVC. On that subject, I still baffles me you don't include support for Spring MVC out of the box! You support Play, Dropwizard, CXF, Resteasy, ... but you don't support the most popular web framework (I'm not saying that, the statistics do) and leave it up to an external library to do the integration. Again, another dependency and another possibility on unwanted transitive dependencies.
In any case, I'll join the Google group :).
Aug 30, 2014 · james anderson
Ron,
Thanks for your reply. It's great to hear that the issues I pointed out are being addressed. However, I still don't see how you can use swagger in a distributed microservice environment: you'll still have a single swagger spec file per deployment. What would really help is to have an aggregator that merges multiple swagger files into a single one (something like what Netflix does with Turbine for real-time streams like Hystrix).
That being said, I also wrote a follow-up on the article describing possible alternatives to Swagger. Swagger, as it currently stands, is a top down approach. This sort of limits the use of Swagger to documentation only (like Javadoc). Frameworks like RAML work bottom up, enabling you to specify the API first and write the implementation afterwards (unit testing as you go against the specification). With 2.0, it looks like you're going the same way. In fact, reading your site you're almost copying what RAML does already, except for some (albeit cool) minor additions. So why would I choose Swagger 2.0 over RAML (which actually has none of the Swagger's current annoyances)? It's also dead-easy to use with Spring MVC. On that subject, I still baffles me you don't include support for Spring MVC out of the box! You support Play, Dropwizard, CXF, Resteasy, ... but you don't support the most popular web framework (I'm not saying that, the statistics do) and leave it up to an external library to do the integration. Again, another dependency and another possibility on unwanted transitive dependencies.
In any case, I'll join the Google group :).
Dec 29, 2013 · Rich LaMarche
Indeed, I don't see the added value over QueryDSL or even the JPA2 metamodel criteria queries and it doesn't support things like aggregation. It's a nice idea, but they've reinvented the wheel and it's an incomplete reinvention at that.
Jul 28, 2013 · Mr B Loid
Really? I have yet to see a project or a client where they are using both Ant and Maven at the same time, except maybe in a transitioning phase. What sense would maintaining 2 build systems within the same company make?
The polarization is continuing today (this post is based on quite an old post from me), only now it's Gradle vs Maven. And the rants and discussion haven't gotten smaller, that's for sure. I can easily dig up numerous Maven vs Ant rants, so it's really not a load of crock, it's the reality of clashing egos in IT.
My point was: religious wars like Maven vs Ant or now Maven vs Gradle are disrupting the one thing that actually counts: productivity. If you're happy with Ant (whoever you are), great. If you're fine with Maven, fantastic. Like Gradle? Super! Just stop writing 'X sucks, Y is a lot better'. It all depends on the context. Use whatever makes you the most productive and if you're passionate about your chosen techonology, stop ranting about the competing techs. You'll probably won't be convinced anyhow, so: live with the fact that other people have other choices. Chances are their context is a lot different from yours.
Jul 28, 2013 · Mr B Loid
Really? I have yet to see a project or a client where they are using both Ant and Maven at the same time, except maybe in a transitioning phase. What sense would maintaining 2 build systems within the same company make?
The polarization is continuing today (this post is based on quite an old post from me), only now it's Gradle vs Maven. And the rants and discussion haven't gotten smaller, that's for sure. I can easily dig up numerous Maven vs Ant rants, so it's really not a load of crock, it's the reality of clashing egos in IT.
My point was: religious wars like Maven vs Ant or now Maven vs Gradle are disrupting the one thing that actually counts: productivity. If you're happy with Ant (whoever you are), great. If you're fine with Maven, fantastic. Like Gradle? Super! Just stop writing 'X sucks, Y is a lot better'. It all depends on the context. Use whatever makes you the most productive and if you're passionate about your chosen techonology, stop ranting about the competing techs. You'll probably won't be convinced anyhow, so: live with the fact that other people have other choices. Chances are their context is a lot different from yours.
Jul 28, 2013 · Mr B Loid
Really? I have yet to see a project or a client where they are using both Ant and Maven at the same time, except maybe in a transitioning phase. What sense would maintaining 2 build systems within the same company make?
The polarization is continuing today (this post is based on quite an old post from me), only now it's Gradle vs Maven. And the rants and discussion haven't gotten smaller, that's for sure. I can easily dig up numerous Maven vs Ant rants, so it's really not a load of crock, it's the reality of clashing egos in IT.
My point was: religious wars like Maven vs Ant or now Maven vs Gradle are disrupting the one thing that actually counts: productivity. If you're happy with Ant (whoever you are), great. If you're fine with Maven, fantastic. Like Gradle? Super! Just stop writing 'X sucks, Y is a lot better'. It all depends on the context. Use whatever makes you the most productive and if you're passionate about your chosen techonology, stop ranting about the competing techs. You'll probably won't be convinced anyhow, so: live with the fact that other people have other choices. Chances are their context is a lot different from yours.
Jul 17, 2013 · Lieven Doclo
Apr 07, 2010 · Mr B Loid
Apr 06, 2010 · Peterson Mark
@Nicolas
I agree that the best decoupling is done through XML, but then again, how many project go down the Spring or EJB path and change their mind after a while? Bigger projects won't.
While I use @Inject as much as I can, the new annotations of Spring 3.0 are too good not to be used and when you already made the choice to go with Spring, you might as wel go all the way. If you don't want to be coupled to any framework, your development options will be severely limited. You'll be completely standards-compliant, but at what cost?
I think the main point of this article is that when you're using Spring, you're better off using annotations (and some XML for the corner cases).
Apr 06, 2010 · Mr B Loid
Although you bring up some really interesting ideas, what you are suggesting is impossible in real software development. Unless you're simply porting an old application to a new platform without adding functionality (why such projects exist is another discussion), you won't be able to find out all the behavior your userbase needs. You might be able to get about 30 to 40 percent, maybe.
Remember, software users are a special breed of humans. As programmers, it's hard to find out the specifics of a business, just because we're not confronted with its quirks every day. As users, it's hard to understand the complexity that goes into a software application. To this day this mismatch, I believe, has caused the most project failures.
Your statement 'software projects should start with design, not programming', therefore, is incorrect. I believe that the best way to find out user needs is to use prototyping until the sun explodes. How do find out what a user wants? By quickly showing him what you think he wants. You'll know quickly enough whether your assumptions were right. User interface design is not the responsibilty of a developer. It's the responsibility of your key users. After all, they're the one who'll end up working with the damn thing. We're only there to materialize their needs and provide guidance when their needs are technically impossible.
While I applaud any programmer that takes up usability study (every front-end developer should have read Designing Interfaces), what we really need are middlemen. People that can transfer knowledge between the business end and the technical user interface. Unfortunately, there aren't many of those around who excel at this.
Jan 02, 2010 · Joseph Bradington