DEV Community

Discussion on: Java Enterprise 101

Collapse
 
antimon3 profile image
Flo Roform

Thanks a lot for taking the time to answer!

I am still not sure I agree :D Again, my point was that JEE simply makes no assumptions about how to model the domain. While I agree with many of the points in your post these have nothing to do with JEE in particular but with software architecture in general. So I think it is a bit misleading as people might connect these ideas to enterprise Java.

JEE doesn't force you to do anything like that; as long as whatever your method is going to do will not access services.

Uhm, JEE also does not force anything even if a rich model does reference a service. Again, I think you are mixing JEE and general advice about software architecture. As for the advice part: not so sure this statement holds in any case. For example, think about domain-driven design. There each layer explicitly makes space for own services and, of course, this can be modelled in JEE.

P.S. Uncle Bob’s talk indeed is great. You should also check out his blog post about Clean Architecture if you have not already read it anyway :-)

Thread Thread
 
martinhaeusler profile image
Martin Häusler

Thanks for the response. I think this discussion is important and quite interesting.

As you stated, domain model classes accessing or not accessing services isn't strictly about the JEE architecture anymore. Indeed, the JEE architecture is agnostic to this decision. However, if we look a bit deeper into the technical details, when you are dealing with a JEE-like architecture, you will likely also want some kind of dependency injection (DI) framework. Otherwise, you will end up with a lot of singletons and hard-wired dependencies which in turn make your code very difficult to handle in unit and integration tests (been there, done that, and lived to regret it).
So what you usually find is either some flavor of Google Guice, Spring's IoC Container or some other implementation of JSR 330. All of these containers help you to implement de-facto singletons without resorting to static variables in your code, such that you can easily interchange them (or even mock them) for testing. However, this technique only works for singletons (and a selected handful of other 'scopes'), but it will not work for domain model elements - which is: objects you pass around and you instantiate as required with new (or a factory) on the fly.
In such a scenario, any service you define becomes a "singleton-scoped bean" in the container. Every bean in the container can request the container to inject other container beans into itself, usually via the constructor, via annotated setters or directly in fields. Now, if you have a method in a domain model element, there are only two ways of how this method could ever gain access to a bean from the container: either by passing the bean directly as a parameter (which is ugly; who passes around singletons?) or by having some static reference to the application container itself. And no matter which JSR 330 implementation you choose, every single one of them will tell you on the first page of the instructions manual: making the application context publicly available in a static variable is an anti-pattern.
So how do we implement a method that requires access to a service method then? Well, that method becomes a service method of its own. Does it contradict the principles of OOP? Yes, it certainly does. But it helps a lot in keeping your call hierarchies clean. Some junior programmer next door might otherwise come up with the glorious idea of sending an HTTP request (and blocking the thread while waiting for the response, because why not!) in a regular bean setter. Limiting the capabilities of the domain model a bit helps programmers to estimate the impact of their method calls. What I would not want to have is that a regular setter method internally calls X, X calls Y, Y calls Z, and Z withdraws money from my bank account ;-) Trust me, I've had it all. I've seen people implementing hibernate entities as observables.

I guess this will become a bit more clear when we talk about actual implementations. I've got the feeling that we are actually aiming for similar things but express them in a different vocabulary.

Regarding Uncle Bob: I really enjoy his talks and books (I'm currently reading "Clean Architecture", his latest book). I am usually very much in agreement with what he says (except for his strange love for "write the test first" practices). However, even though in contrast to other "architecture gurus" he tries to keep his arguments close to reality and make them actionable, he remains quite abstract in his conclusions all too often. He tells people what to avoid, but rarely what to go for. At the end of the day, we have to put it into code, not lawsuits. My personal position is usually somewhere in the middle between Uncle Bob, Martin Fowler and Bertrand Mayer.

Thread Thread
 
antimon3 profile image
Flo Roform

Hi Martin,

this is a great answer and I especially like that it now draws a clear line between JEE and architectural best practices. You should consider writing another blog post about this!

It's funny that we are both interested in similar philosophies about programming. I have read Clean Architecture as well (even pre-ordered :D) and I can also agree with the majority of things that Uncle Bob suggest (yep, even the TDD part; although I as well do not practice it constantly but this is more of an organizational problem in the company I work for). Anyway, if you’d like to talk about actual implementations feel free to send a link to a GitHub repository (or something) that reflects your approach. Although by now, I am quite confident that we probably won’t find much to discuss ;-)

Thread Thread
 
martinhaeusler profile image
Martin Häusler

The next article I have planned is a follow up on this one on how to actually implement this architecture with spring-boot. Time is a bit short at the moment though. I'm looking forward to your comments!