Matt and Rich get round the fireside to talk about anemic domain models, and discuss the news of a proposal to include data classes in Java.
In this episode Richard attempts to break the world record for the uses of the word "exactly" within an hour. He won't be saying it again next time around.
Hacker News discussion: news.ycombinator.com/item?id=15606250
Martin Fowler's Paper: www.martinfowler.com/bliki/AnemicDomainModel.html
Richard :Hello and welcome to podcast number ten for All Things Java. I'm Richard Chesterwood with ...
Matt:Matt Greencroft. Nice to see you again, Richard.
Richard :And good to see you. I understand you have an apology, too.
Matt:I do have an apology. I should explain that one of the things I do after each podcast is we get it transcribed by a very, very good third party company. But there's always the odd word, so I read the transcript as I listen to the podcast-
Richard :You've listened to the podcast?
Matt:I've listened to the podcast.
Richard :Oh my word.
Matt:We have at least one listener, that's great news. I was sat in my kitchen listening to the podcast and every time I said a female name that triggers off a certain Amazon device to listen to you, my Amazon device went bonkers.
Richard :Andrea is it?
Matt:I didn't want to say it, Alexa. You made me say it. I want to apologise for anybody out there who's listening to this who has an Amazon Echo and is listening to it on speakers, not on headphones so it's picking up every time. In that last episode I said, "Play the whatever podcast." Because it can't find it. It never works and she kept starting to say, well she started at one point playing some comedy thing from the 1960s. It was all a bit bizarre.
Richard :I had an Echo Dot. I nearly said the female name there. I had an Echo Dot for a while. I hated it so much I got rid of it, I passed it onto some schmuck. That was you, wasn't it? Often the Amazon adverts would come on the TV and they don't care about saying ... They will actually say, "Alexa, book me a taxi, please." My echo's firing up, awful piece of technology. I absolutely hated it. How are you getting on with it.
Matt:I haven't used it very much. The main thing I use it for is to tell it to add things to my shopping list. Because I've got it in the kitchen it's quite convenient so I realise I need more eggs, I'll just ... Because I use a shopping list on the Todoist app it can connect to that so it adds things to my app. That's ideal, that's the big use I found for it. It is easier than getting your phone out of your pocket and typing, "Eggs" in.
Richard :I found no use for it apart from playing podcasts. I wanted it to be able to play this podcast. I'm sorry, I've digressed a little bit. There is no Java in that although you can write skills for Alexa I guess. Can you do that in Java?
Matt:I think so. I've not even looked. I would assume so.
Richard :Integrates with AWS Lambda so I would assume. I hope we don't get asked for that. I don't want to do a course on that.
Matt:Well no, and of course Amazon is not the only company producing these kinds of devices. Google have got one, there's others coming out, loads of these smart home devices, they're called. Just because you can write a skill for one of them that is not obviously going to translate is it? At this stage I think it's too early to know, which is going to be the dominant player if any. This could be one of those things that actually-
Richard :Solution in search of a problem.
Matt:Like the Smart Watch, you know? The Smart Watch. Okay, the Apple device is still out there but it's not had the sales they expected. All the others are falling by the wayside now. You can still get the Android Wear watches but they aren't having the take up that I think anyone really thought they might. Because, again it's limited use. Do you really want emails flashing up on your wrist every five seconds?
Richard :Definitely not, definitely not. I digressed a little bit there but we have a general plan to cover. We're going to talk about anaemic domain models and Java beans and all that kind of thing. The idea for this podcast was triggered by a news article this week on Hacker News, which as usual we'll put in a link to the show notes. I thought it was a very interesting discussion. I think the discussion on Hacker News is more interesting than the original news article really. I would recommend any of our listeners to go to Hacker News and have a look at this. The title of the article is Data Classes for Java and what triggered this news article was Brian Goetz, who is one of the architects of Java-
Matt:He's the guy who wrote the Java Concurrency in Practise I think. Is that-
Richard :You've always got your nose in that book haven't you? You're never away from it.
Matt:I think that's certainly when I first came across the name. He's worked for Oracle for years hasn't he? He's probably chief architect for Java or Language.
Richard :I'm not sure if he's the chief, but, certainly one the big architects. So he's done a proposal for what ... it doesn't seem to have any fancy name other than just Data Classes for Java.
Matt:Actually I've got the article in front of me he's saying that this is an exploratory documentary. It's not a proposal at this stage, he's saying, is he asking for comments, is he asking for feedback, or, is he just saying this is where our thinking is right now or ...
Richard :I guess this is part of the new six month rolling release type thing. It looks like, things like this which, this isn't going to be this week's rant, this is going to be a mini rant.
Richard :It does strike me as ridiculous, with we’re 20 odd years into java. We're up to version 10 and we're still discussing these really, what to many eyes and a lot of the comments on Hacker News reflect this, you know. I can't believe we're discussing this after so long. It should be fundamental, it should probably be in the language.
Matt:So let's summarise. What is the, what is he sort of suggesting? What is the news?
Richard :So let's talk about the problem first of all.
Richard :Any Java developer must be well aware of this problem. Boiler plate code, given any class, say you got ten attributes in a class.
Richard :Ten private member variables wherever you want to call them. What you're going to end up with in that class, very quickly. We all know it, we all generate the code using your IDE, you're going to end up with get/set pairs for each of the private attributes. You're going to have to write a toString, it's a little bit different, because you generally put your own custom stuff in toString. You'll also need a hashCode and an equals. We generally generate them these days.
Richard :Which is, that is a big topic as well that we should touch on in this discussion.
Matt:When you say generally generate them, well yes when we remember tom so some of us don't always generate them when we should and ...
Richard :So you mean ...
Matt:We've not generated them and ...
Richard :So you mean the equals and the hashCodes?
Richard :Yeah and more than that it's, in fact the talk we awere at last week someone mentioned that you add a new attribute and you forget to update them so ... the equals ends up being broken possibly.
Richard :So we all know that we do that in Java and I think we almost do it mindlessly without thinking and the discussion on Hacker News, bear in mind Hacker News is not a Java site. It's a general hacker site and software developers, geeks in general.
Richard :Frequent Hacker News and a lot of the comments on here, the time of recording this, the number one comment is why on earth would you do this? What do you need getters and setters for? This is crazy. You know, this guy doesn't come from Java and is a bit baffled about what is this strange culture in Java that you all generate gets and sets?
Matt:So what’s the alternative? If you've never been a Java programmer, if only ever done and I can't even name a language, probably Sclala I suppose where this would be a foreign concept. What would be the norm in other people's worlds?
Richard :C# was probably the first ones to do and visualbasic.net was the first ones who do a good. I think they were. No they wouldn't be the first, but, certainly they had a good solution to this, which you ... well proxies, which is what we're really talking about here so you've written a class ... we're going to have talk in detail about anaemic domain models in the middle of this podcast. So we're just circling around the edges of the discussion right now. Forgive me if I'm being a little bit basic at this part of the discussion. You've written a class, you've got three attributes in there, an I.D., a name and an address, keep it simple.
Richard :We will talk about whether you should have gets and sets and whether they are an anti-pattern or not. I promise we will, but for now, let's say that you wanted to display the details of that object on a screen.
Richard :Dead simple. You're going to have to somehow extract the data out of that class.
Richard :Sort of two obvious ways of doing that in an object oriented language like Java, you could make the field public.
Richard :Or, you could provide a method that somehow returns the value of that field.
Richard :So I don't think we have time on a podcast to ramble on about encapsulation.
Matt:I was waiting for that word. Absolutely.
Richard :So encapsulation, one of, well the, I would say fundamental principle of object orientation and I would just, yeah it's difficult to do on a podcast, but, if any listeners are interested in this have a look at the Hacker News piece and a lot will say just make field's public. Just make them public. What's difficult about that?
Matt:Yes and I guess my reaction to that is that in a typical class, you'll have ten attributes of which nine, the gets and sets are absolutely standard, not doing any kind of logic, no kind of validation, they’re literally just updating or retrieving the value of an attribute. I there will be one where you need to do something slightly different.
Richard :Let's do a concrete example then. Again we'll try to keep it simple as possible. I think I was heading toward maybe a customer class.
Richard :How boring these things are.
Matt:At least everyone can understand it.
Richard :We can't do a nuclear science example. So we got customer class, a couple of boring fields, name and address, there's also a status, I'm doing quote marks with my fingers here. There's a “status” associated with a customer.
Richard :On version one of the system, it's just a field. It was just a string.
Richard :Then on version two of the system, the business requirements got really complicated, the status of the customer is determined by some nasty process.
Matt:It could be some very simple logic, right? It could be, if a customer is never bought anything and their pending, if they've bought they're active and haven’t bought in five years they're inactive. You can have a really basic logic that's really simple to work out.
Matt:But the point comes at what I want to think of as a calculated value.
Richard :Absolutely. So, it's not a field anymore, it's not a private ... it is, I'm going to use the term, this is a term not defined in Java.
Richard :We can think of that instead of being, it's a property of that class.
Richard :External viewers of that class, such as our user interface would think of it as property of a customer.
Richard :We know internally in our class, we calculate it.
Richard :By the way, before I go on there might be some object oriented experts listening just going, "no, it wouldn't be part of the customer class, it would be in a class of its own", you're probably right, we're keeping it simple just for ...
Matt:We might be talking about that in a little while anyway, because of what we're going on to. The point of it is that it's a read only value. So you can't obviously set a status, because it's calculated based on other attributes here. That's the principle here.
Richard :So in Java we don't have the concept of a property, but we do have the concepts of methods, so you just write a method to return it.
Richard :If you’d made it public in version one of the system, then you'd have the potential for other parts of the code being able to just change that value at will. We know now that shouldn't be possible. As you've said you want it to be read only, you want to control it.
Richard :So that's why we work with methods. Now that is, I would recommend anyone follows your Java Fundamentals course, if you want to learn about encapsulation and all that kind of thing. I think we can take it as read that our listeners will understand that and be familiar with it. So why is this a big discussion point in Java?, what's the ...
Matt:We were at a talk where they were discussing the various merits of Java versus Scala in particular use cases. One of the arguments the Scala guy was saying is you don't spend, you don't waste all this time writing this sort of boiler plate code. You don't have the issue of forgetting to update your equals method. Really a modern language should be doing these really boiler plate activities for you. In a way Java does, the IDEs generate it for you.
Richard :It's all very well when you generate code and you think well that's easy. You touched on it earlier, what you forget is that code has to be maintained, it has to be maintained forever and it's the cost of maintaining that code, which is a burden. You could also add other arguments in which is if you generated 150 lines of boiler plate code, that's completely, not completely, but, I want to say obviscating, it's hiding, yet the valuable method, the one that you're talking about the calculated status of the customer, you can't see that in amongst all of this generated stuff that you just start tuning out and you kind ...
Matt:You're right, but, a lot of the time that we in Java we are writing stuff that, I mean I'll give you a good example, what I think of as a sort of example is that say you're working with a JPA repository type class. You've created this interface and you're adding in interface methods like findById, or findByStatus, where you are, you're having to write this ... you're not generating the underlying code, that's happening for you and yet you're having to write a method that really ... why should you even have to write that method, right? Can't it just do it? So a lot of Java is, it feels like it is that, you're writing things that are boiler plate code even if it's in a different context.
Richard :Yeah. Definitely. So this Brian's proposal, it's really to bring Java in line with languages like Scala or Groovy and visual basic, C# and basically to have the concept of a property. I'm less interested in equals and hash code. I'm not really thinking about that in this discussion. I'm thinking about the get and set methods. So basically it will be a class, which has an automatic get and set method.
Matt:What's the difference between that and making the attribute public in the first place then?
Richard :Well if an attribute is public then it can be written and read.
Richard :Written is probably the important one - by any code anywhere in your system. You don't as the owner of that class, a maintainer of that class you've got no control of what the clients of that class do with your ... with objects of that class.
Richard :So the status we’ve been talking about there could be arbitrarily changed by some client, breaking all the business logic that we once wrapped around that.
Richard :By making them private you then you're forced to use methods, which in general could have rich logic inside them.
Matt:Yes, but, what Brian is proposing this having, I'm sorry what was the word attributes or no, properties.
Matt:What would a property of a class look like then, it would be ...
Richard :Well it has a ... again we'll put a link in the show notes, it's of course linked from the Hacker News article anyway, but, it is a long piece and I must confess I haven't actually read it all. He has a general proposal, it looks very similar to how you do things in Scala and so I'm looking halfway down the article he says, "let's go for something like" and it's being used all the way through the example a class called Point, which is just an XY coordinate.
Richard :So he does it before, how you would do things in Java today would be class Point, blah, blah, a couple of private attributes, an X and Y and then you'd have a constructor, you'd have a get and a set, each of them, and you would have an equals and hash codes.
Richard :You're talking about 50 lines of code there? Just to do this Point. So he says in this new modern proposal the way it would be done would be underscore, underscore, data. Interesting. That’s a new keyword in Java, __data.
Richard :__data (Class Point, int X, int Y).
Matt:Okay, so that would be exactly the same in terms of output or when it's compiled into bytecode, as you writing that existing Java class with getters and setters, equals, hash code. So what it's saying is it's not changing any kind of data type, it's just generating the code, but, you never even see it.
Richard :You never see it, you never feel it. You don't maintain it.
Matt:Okay, so that's only possible if your class is a ... I want to say POJO, I'm not sure if that's quite right, but, if it is simply a class containing variables with gets and sets and nothing else. There's no concept of read-only’s in here or validation, or anything like that...
Richard :I assumed the case is, I'm working from knowledge of similar languages. I assume that the case is if then you wish to customise any of that you can, you can privatise the setters if you want to make it read only, and most importantly of all you will be able to, if you decide that your setter method needs some logic.
Richard :Say you’re doing some validation, or something, then you can override that setter.
Matt:Okay, what about constructors? I'm thinking back to the Groovy ... in Groovy you can instantiate a class, providing values for any of its attributes in a constructor by doing variable_name:value.
Richard :As I said, I haven't read it, I doubt that they'll be going that far with it.
Richard :I assume you've got to be getting, again sorry assuming here. I assume you will get a default no arg constructor and a constructor with all of the arguments... looking at his example here. It looks like you will get an X and a Y in that example.
Richard :So great it's not actually that interesting as it should have been in at the start.
Matt:Or that big a deal really. It doesn't sound like it.
Richard :Definitely not and do a little digression again some useful information for anyone who is working in Java. There has been a third party library for us available for some time now that will do all of that. It's already been done, it's called Project Lombok.
Matt:Do people, well presumably people are using this?
Richard :Oh very much yes.
Matt:It did get a bit of mixed reaction didn't it.
Richard :It's a love or hate thing, Lombok, but, just to cut to the chase. If you're using Project Lombok, then you would have your class, you would annotate it, I think the annotation is @data and all that stuff is generated.
Matt:So the ...
Richard :I should say not generated in the IDE, you don't see it, that's the important thing. It's done behind the scenes.
Matt:Right. So effectively it's generated at run time, or, generated at compile time, or ...
Richard :Okay, now this is key, it actually adds a compile step to your build process.
Matt:Ah, that's what they were talking about, yes.
Richard :That's the ... so I looked at this, I can't remember now, it might be a year ago, times going at such a strange rate these days. It might have been a year ago I looked at it. I have a rule of thumb that anything where you're generating or you're adding compile steps, I avoid it like the plague.
Richard :It always causes you technical debt at some point down the line. Which is why I was delighted when we were at that talk, and it was a Leeds speaker wasn't it? Said I hate Lombok. We've used it on our project and I hated it. It screwed everything up. Brilliant.
Matt:I hadn't heard of it before, but, I'm thinking when you're going to do, if you're doing test driven development, you're writing new unit tests. In order to run the tests you've got to do an extra compile step every time. Is that how it works?
Richard :I haven't touched it with a long stick, I'm not going to either, so any customers who want the course on Project Lombok, go somewhere else. I'm not doing it. I think it's important to be clear about what we don't like.
Matt:Okay, so getting back to where we were then. So, there's this general idea of having effectively you can write one line of code and that's the equivalent of writing a whole class now with loads of attributes in. So why is it contentious? Why is there lots of discussion done on this?
Richard :Excellent. Can I just scan down a few of them. Why would ... why are you doing this? Why are you ... gets and sets?, this is ridiculous and it all goes back to a very fortuitously we've been having a conversation, the both of us, with one of our customers who wanted to talk about the concept of an anaemic domain model. That should actually be the core of this podcast, the anaemic domain model.
Matt:So, I'm just conscious that everybody listening to this will necessarily have English as their first language so, it might just be worth saying. The word anaemic ...
Richard :It is quite ...
Matt:Well it's a medical word isn't it?
Richard :Regardless of where you come from, unless you've suffered from anaemia you might not care what anaemic means.
Matt:I'm hoping that I'm going to get this right. My understanding of anaemia is that anaemia is an illness where you're basically weak because you're lacking in blood.
Matt:So, to describe a domain model as anaemic is quite an interesting description anyway.
Richard :Which comes from Martin Fowler and I remain convinced and I mean I love Martin Fowler, I would never negatively criticise him for one reason he's an avid listener of this podcast. I have no evidence to suggest that he isn’t an avid listener of this podcast.
Matt:If you're not listening ... sorry.
Richard :We're finishing each other's gags. I like that. I mean he's a great thinker and software developer, etc., but, his real talent is naming things brilliantly and I guess people discussing them.
Richard :When you come up with a name like anaemic domain model, I don't know about you, but, I want to know about it. I want to learn about this nice term.
Matt:Absolutely, yes. It is. It's one of those things that you sound like a real professional when you're talking about, oh you've got an anaemic domain model there, that’s where you’ve gone wrong. It's an ant-pattern.
Richard :If you get questioned on it you can always say, well haven't you read Martin Fowler's seminal paper? In this occasion you genuinely will have read them, because they are very readable papers.
Richard :This one goes all the way back to 2003-ish I think.
Matt:We'll stick a link to the article in the show notes?
Richard :Definitely, it's an absolute must read.
Matt:So, an anaemic domain model is really what we've just been talking about, where your domain objects, so your classes that are representing the real world objects, so your customer, or, your book, or whatever it is in your system are just a collection of attributes with gets and sets. No logic at all.
Richard :Exactly. Before we go into detail here, I'm just putting caveats around this, which I think is really important. I'm finding myself saying this more and more to customers, there is no one way of doing software.
Richard :You should, you really shouldn't fall into the trap of thinking this is a must do, this is a must not do. We must always do, etc., there’s lots of different models, there's lots of different ways of thinking. I realise our customers are kind of looking for clarity, they want a “just tell us what to do things”.
Richard :I think as trainers, we learn to fall into that trap of do this, do this, do this, don't that's a bad one, you know we have to be quite clear and precise.
Richard :Yet in the real world there's so many shades of grey and I'm saying that particularly because if for example you are currently into a functional model, so Java 8, Lambdas, that kind of things. Then a lot of what we're talking about here is redundant. There is no one right and wrong way of doing things. My caveat here is everything we're about to discuss is supposing you are doing an object oriented design. An object oriented model.
Richard :I don't want to hear, I don't want comments saying oh yeah well if you did it using functions then you wouldn't have this system. No you wouldn't, because you’re doing it differently.
Matt:Okay, absolutely, let's be honest, lots of our customers we know are building Spring Boot applications where they are going to have a domain layer, they are going to have some kind of presentation layer. They are thinking in that way, it is a core of what a lot of our customers are doing, so ...
Richard :I still, there's still a lot to like in functional programming, we do a lot of it ourselves and we are doing more and more of it, especially when you're doing highly concurrent throughput type systems.
Richard :Where object orientation I think is very valuable, and I realise this is contentious, but, for me the value I've got out of it is when you are working in a complex domain and you've got lots of different types of objects in that real world domain and lots of different classes of data. I still think a domain model is a very powerful way of expressing real world problems.
Matt:I agree, I'm aware of the business logic around some of that stuff is complicated. We know, I mean just talking about our own website. Who can and can't watch a video? Yes, you can obviously do it through functional programming, but, it's easier to understand because you are writing code that completely reflects in English the real world. You're using nouns that makes sense. You can look at the code and see straight away what it's doing.
Matt:Whereas the bits of our code that's analysing usage and creating reports absolutely looking at huge amounts of data ...
Richard :Real world streaming data, yes, functional is perfect doing aggregations and ... beautiful.
Richard :I realise that we're in a strange time in software development that there’s a major shift in the models we're using. I'm still a passionate advocate of domain modelling. Have you said what an anemic domain model is?
Matt:So we've said yes, it's just gets and sets...
Matt:No business logic.
Richard :So where is the business logic then?
Matt:So that sits I think, Martin Fowler describes in a service layer, I think some people call it an application layer.
Richard :Yeah, this is where I got ... can do a little bit of ranting here. I would strongly advise anybody who's wanting to get into design or architecture whatever. This actually came from a discussion with a customer as well. They said something like, you know I've got my service layer, they actually called it the business logic layer.
Richard :That is a ... I think a massive anti-pattern, so what we're talking about then is you've got a data class. Just with data in it. Gets and sets. Just allows you to access that data. Then you got a separate layer where the logic resides.
Richard :Now that ain't object orientation. That's procedural, that's how things were done before, which is where you have your logic, an algorythm, it's just reading and writing data.
Matt:So I think a common scenario though where you see that is, say you're using an MVC application. So, you know, everyone knows “don't put business logic in your controller”. It's when you're writing your controllers that you suddenly find the need for the business logic. So your domain model you've written first, that sat there, that's static, that's representing the real world. You're coming up with these new ideas of business logic, which you need for your controller and there's that sense I think, that some developers get of well it wouldn't be right to go and edit the domain model.
Matt:We'll put it in this service package, which is really ...
Richard :We'll come back to that, if we can ...
Richard :Can we come back to that? That's a really important point. We've missed a couple of steps along the way. Even if you're not doing MVC, which I understand it's a little layer of complexity, I think it's so ... one of the comments, very intelligent comment actually on the Hacker News page, say something along the lines of, all that's happening the reason the people are doing this forget about controls and service and all that. Even if there was none of that needed, the reason people are doing it is, people in general don't get object orientation, but, they want to do object orientation.
Richard :So they work in a language like Java, which is object oriented, so therefore, I'm doing object orientation, but, then they start building a class for the business logic and the class for the data. Now the fundamental of object orientation, yeah we always use that buzz word encapsulation, but the real fundamental of object orientation is the data and the behaviour are combined in the same modules. The data is as close as possible to where it's actually going to be used.
Matt:Yes. So is part of the issue that when you're using somethings like hibernate, so your domain model is also containing the instructions as to how it is to be persisted to a database. There's a fear of confusing what's going into a database, what isn't, by adding extra things into ... what could be a class that simply representing the actual data, rather than the behaviour of that data.
Richard :That's a huge problem I think. Again, I'm might say, so let's come back to that.
Richard :Well you're quite rightly wanted to talk about real world problems, about implementing this and I'm still trying to keep on the kind of theoretical, the purest approach. You're absolutely right once you actually start implementing an object oriented system, of course your data classes generally, we're just talking classically, you might need to persist them in a database. How do you do that? You start putting database stuff in those classes.
Richard :Today, JPA or hibernate is one of the cleanest ways of doing that, which basically puts all of that code upon a layer that you can't really see and your data classes remain sort of ... fewer annotations maybe.
Richard :Yeah, I don't even want to go there, just yet.
Richard :It's just that, with an anaemic domain model, you're not doing object orientation. It's just as simple as that. You're doing a procedural system. I love the way Martin Fowler says, I've lost Martin Fowler's post. I'm going to quote from Martin Fowler, "Object oriented purism, is all very well, but, we need more fundamental arguments against anaemia". So, I hope we've made it clear, that he's stating an anaemic domain model is a really bad thing. And we agree ...
Richard :I love what he says here, "the problem with an anaemic domain model is that they incur all of the costs of the domain model without yielding any of the benefits". That's absolutely gorgeous. If you read around what he's saying there, I'm sort of, I could paraphrase what he's saying, he's saying if you don't want to do object orientation, fill your boots, go away and build a procedural system. Go away and do functional or whatever.
Richard :But don't say you're doing object orientation. If you're going to build a domain model, which is hard work, it's a hard effort. I think it's valuable, because it keeps your design aligned with the real world problem. I realise that's a controversial thing, a lot of people think it's nonsense. I like it. If you want to go to that expense and that cost, don't go then implement it as an anaemic domain model with a layer of procedural code on top of it. You've got to maintain that domain model. For all time. A lot of hard work and yet you haven't got any of the benefits of OO.
Richard :I love the way he's saying that. I think it's buried in the middle of the piece and I think it's a very important point. If you're going to do it, if, that's the key word, if you're going to do a domain model, then do a proper one. If you don't think domain modelling is valuable, then don't do it.
Matt:Do it in a different way.
Richard :A proper domain model is one where a single class contains the attributes of that class and the business logic relating to those attributes.
Richard :Exactly, so any talk of a business logic layer is not object oriented. You shouldn't have a business layer. Now we often talk about a service layer and as Martin Fowler correctly identifies this here, the service layer tends to be a bucket or a bin where people throw their business logic in. Again, because it feels easier. So you end up with lots of get/set pairs and then a massive service class actually doing all of the work. So what's wrong with that then? Apart from what he said there, I mean he said if you've got a domain model, but you've got to maintain, and yet it's not doing anything. The other reason I think would be unit testing. Much hard to unit test, a large algorithm in a service class.
Richard :Then it would be to take a domain class, which has no ... domain classes don't have any coupling to web tiers or databases even. A domain class should be one that you can instantiate and you can poke some data into it and then you can call some business methods and see what its state is. Perfect for unit testing. Service layers are always harder to test.
Matt:So absolutely you always end up having to mock stuff to test the service layer.
Richard :Exactly, which is why yeah we've had some criticism about our test driven development course. You know we've got a chapter or two on mocking. We need more on mocking. How do you mock the database? My answer to that is actually, you know, forget it don't.
Matt:You should never find yourself in a position where you've got to do that.
Richard :Well you should and that would be integration testing.
Richard :You can do it, absolutely do it and it has value, but, we don't think it's where the real value is. 90% of your value is from plain Java testing.
Matt:So, but, a service layer is still going to be needed. If you for example have got some business logic to determine some value based on two different objects, which don't necessarily have a relation. So, just thinking back to Java fundamentals, we had a use case about a library, where people can go and borrow books. So, if you want to know if you want a piece of business logic and says is this book on loan to this customer. That isn't necessarily going to sit well in either the customer or the book class.
Richard :Exactly. That's exactly what service layer should be. A service layer is for coordination. I'll expand on that a little bit more but, that's all it's doing is coordinating. There's actually not, there's nothing to test there particularly, other than as has it done step one, has it done step two and then combines the results or whatever. Service layers should be really thin, as thin as possible.
Richard :You shouldn't find yourself with business logic in there, and so that will lead us on to, it might be a bit early, but, a common question at this point is what's the difference between that and a controller? So we'll come back to that.
Matt:Okay, come back to it, because I'd like to just then say one of the applications I've written is an application, which is actually has to do with reconciling financial information. So it's got a domain model, which effectively, let's just say to keep things simple is reflecting a bank account. So you've got the idea of accounts, transactions, those kinds of things. Real world concepts and then there is a process to import data and convert it into instances of those objects. Which I call it the file import service, I think of it as a service. So a service can generate instances of objects. That would be a valid thing to do in a service?
Richard :Sounds right. You wouldn't call it business logic though would you actually generating the objects from a file, is not what you know ...
Matt:So maybe I should go a step further, part of that process of generating is actually looking at the state of data in that file to determine what kind of object to generate, but also how, what the property setting should be based on ... so for example it might be that the raw data comes in CSV format with a code that says USA and we are saying create an object with a country of United States of America. That's fine to sit in a service there.
Richard :Yeah, it's a factory I suppose. It's creating objects based on similar ... so I guess not business logic, in that it's not a rule of the business, this is a bit of behind the scenes machination that's needed to ...
Matt:So that's interesting there, you used the word factories, so a factory class is, you would class those as like a service?
Richard :I'm on very thin ice there. I never thought of it like that. Let me waffle and dig myself out of this hole, because just talking of patterns and pattern names, I think one of the patents that's often the gang of four patents back on podcast number eight, no, on an earlier podcast we talked about design patterns. Strangely the one pattern that we never mentioned. Well podcast seven I'm told.
Richard :Yeah, podcast seven, we never mentioned the façade pattern. Never once mentioned it and it's probably the easiest pattern and the idea of façade is, if you have a complex “system”, it can be anything, but, for this discussion that means the domain model.
Matt:Domain model's pretty complicated. I hope it's not anaemic.
Richard :Yes. Lots of little classes. Now, a client, let's say that's the user interface, but, it could be anything, it could be a rest interface or whatever. Wants to get some work done, so what do we do? Does that interface call the domain model? Now there's something really wrong about that, because the domain model's complicated and quite low level. Hundreds of classes in there and the user interface might have to call one class to do something, and another class, and then another class and the user interface will get horribly bloated and complicated. So answer – dead simple you put façade class in the middle and I can't remember what the one sentence description of façade is, but, it's something like provide a unified simplified interface to clients, so that the client can do what they want to do with a single method call.
Matt:Yes, you're hiding some of the complexity of what's hidden underneath it ...
Richard :Exactly, so what is a service class, it's a façade to a domain model.
Richard :As long as you keep that clear then everybody's happy. So just going back, I was waffling filibusting there to avoid, so you're saying is a factory a service? I never really thought about it like that, but, certainly a service could call a factory and ... absolutely yeah.
Richard :That's what a service layer should be. That gives you the ability to do things like you can easily convert using modern frameworks, you can easily convert service into a rest interface for example. You certainly do not want to be converting your domain model into a rest interface.
Richard :I had a few requests from customers to cover Spring Data JPA. Sorry I forgot what it was called now, Spring data Rest, something like that. Spring Rest is beautiful, it's actually just Spring MVC, nothing clever about that. There is a separate project in Spring Boot, not Spring Boot actually, but, Spring generally. It will take a domain model and generate a cred interface, create read, update and delete in rest around every object. I can't stand that, so I'm not going to touch that, because of what we're talking about.
Richard :We should be working in rest, up at the façade layer. We mentioned before, what's the difference ... I think that would be a common question now. What's the difference between a controller and a service.
Matt:Going back to ... so in the MVC world ...
Matt:So, which, having done recently we ... re-recording this chapter or two about MVC as an architecture type, you know I very much think of it as controller is about flow of your application. So it's about getting, retrieving a response from the client, calling the business logic that needs to happen, which is the model in MVC and then based on the results of that working out where is the right place for that client to be. What's the next page for that client. So it's about, process flow.
Richard :In context of this discussion though that business logic that you worrying refer to there, that would be the service, the controller will call service, I don't like the term model. It's a term stolen from a completely different way of thinking actually. Yeah, the controller would call a service class.
Richard :It wouldn't care about low level domain.
Matt:The service is the interface between the domain classes and the controller.
Richard :Yes. If you're building a web app, of course. The only thing I would add to that is a controller in the context of what we're describing controller is always coupled to the web tier. So in the controller you will see things like httpRequest, httpSession, cookies maybe, if you're going down that line. You'll see all those kinds of things there, that are specific to the web.
Richard :In a service you would see none of that, so you could reuse a service class and the domain model if you were building an app where you needed an Android interface and a Rest interface and a web interface.
Richard :You could use that service and domain in all of those contexts perfectly happily. It's the controller that would be totally different in those three different models. So that's the difference, their intention, their purpose. A controller and a service is kind of the same thing, it's providing an interface between two separate concerns. The specific implementations are different.
Matt:The amount of times we see examples of work people have done, whether it's life projects their working on or, you go in and see a customer and their looking at their controllers and their riddled with business logic.
Richard :Exactly, so we're back to anaemic ... so it ties back to the discussion beautifully. We're back to anaemic domain models, so everything in a controller, domain model get/set pairs everywhere, absolute rubbish, an expensive domain model they have to maintain.
Matt:I wonder if it's going back to the old end, three tier development, where you thought about your database, which is what their making their domain classes effectively, as a tier of your application. I wonder if that is where it sort of stems from as people's way of thinking.
Richard :It does. People don't, they didn't get object orientation or at least got it on an academic level and then when they start implementing it all kind of goes all out the window and you go back to ... it's also the other topic, I saw quite a lot of these out in the field, of what I would just call they are crud applications. There is no business logic, all you're doing in your system is you're creating records.
Richard :So, in that case do you need a domain model? No. Why would you go to all that expense? I'd knock that up in ... I don't know, I'd use the database like Access or Oracle and whack some forms on top of it and your job’s done. I would step back and question what kind of a business do you have? If you have no business logic, but, I guess there are many businesses that are just record keepers.
Matt:Well, you also get the kind of thing that happens all the time where your business is complex. You're doing lots of different things and all of a sudden you get this right we need the ability to create a custom invoice where I can just put in, here's the customer's name, here's their address, here's the amount of the product line, and it will generate it in a nice way we can email as a PDF. Just knock me up that quickly, it doesn't have to interface with anything else we do. That's the kind of thing that, you know, as a programmer, I’ll say right… I'll do that in Spring boot, because I can do the interface very nicely in thymeleaf. It doesn't take me anytime at all and yes, I'm creating a whole domain model, simply because it's the quickest way to do it.
Matt:I think happens an awful lot. It's what everyone used to do with spreadsheets. The old knock me up a quick VBA macro in a spreadsheet to do this little job. This expense form claim, you know. Expense claim form, every company I have worked has had those and ...
Richard :The problem with that is that, then becomes that spreadsheet, becomes… you start tacking other things on and it grows. So that, I suppose is the idea of a rich domain model. It's sort of upfront thinking about the whole business, rather than one little bit I guess.
Matt:You know most businesses are built on lots of different systems. They aren't built on one big system that manages everything. Of course, that's also the way forward. Using microservices to build things in lots of little systems that ...
Richard :Indeed. Yes. If you're doing microservices, is there a place for the domain model? Very good point.
Matt:I think I see people using it all the time. Simply because it's the quickest way to build something. If you need to get a crud application, up and running very, very quickly and there's no ... maybe minor validation if any, it's just in case it being able to input the data into a system. Why not ... it's a quick way to do it.
Richard :These anaemic classes are really just becoming representations of database tables.
Richard :It's fascinating, I think the longer I work on this, the longer I think about this, the more I realise everything depends, I started this discussion by saying this a hundred ways of thinking about this.
Matt:Yes. Taking it back to Brian's article, his keyword, his new keyword ...
Richard :I glad you mentioned that. Yeah.
Matt:Is __data, right? So he is saying, this ... it is implicitly this is a class that is representing data and nothing else. It is a database table, really? Yeah. That's what he's saying. This is a data only class.
Richard :Oh well, my thinking while I was assuming they were doing the same thing as Groovy and that you can then add logic if you want. I don't know if that's the case, because I haven't tried it yet, but, it's an interesting keyword. I thought you were going to complain about the underscore, underscore.
Matt:I wasn't actually.
Richard :It's disgusting.
Matt:It is. I've just got to a random a bit of the article and he's showing that you would potentially build a regular class that can extend the data class. So you might define a data class and then you could build your ... so he call’s his data class C and then says that class D extends C. That's where then you can put in your logic. Now, I'm not reading it fully, so maybe that's not what he is suggesting as a good idea.
Richard :I think what you're saying can kind of makes sense, there has always this problem that, and I think we might have touched on it before. You've got a business class with rich domain, blah, blah, blah, blah, blah, but, practically you've always got to map it to a database table. So you end up with all of these annotations that are only relevant to the database, and you've violated a cohesion principle there. It's doing two, at least two things.
Richard :You've mixed it together and it's harder to maintain. The answer to that is you would have a just, we're back to it again, just the data class ... There used to be a patent for this called, I've forgotten now, data transfer object. That's it, DTO. So, yeah you had your rich business object and then a sort of anaemic counterpoint class. That’s something I avoided like the plague, because then you end up with a dual hierarchy of classes. We've tried in the past to do things like what you're describing, you have one extending the other and ...
Richard :There's ways to make your ... I never found a satisfactory solution for that frankly. It's an interesting area, there's a suggestion that, I mean I take umbridge that, if we're really going to have new keywords in Java that begin with underscores, the reason he's doing that presumably is to avoid any clashes with if you've got code that uses a variable called data, which is quite common.
Richard :That would break the Java.
Matt:Why would you not just do this with an annotation on the existing class name, because he's put in __data class, so underscore, underscore data is like the equivalent of public or private. It's sitting at that level of your code. I'm thinking why not just have it as an attribute, if that's how they’re going to do it.
Richard :Well somebody suggested that perhaps what he is doing there is bike shedding, if you're familiar with that term bike shedding.
Matt:I'm not, no.
Richard :Every time I come across that term, I have to google it and remind myself what it is. It's ... I think it's a corollary which is one of Parkinson's laws, which is that the example that the guy who invented that term came up with was, imagine you're building a nuclear power plant and you're doing the proposals for a nuclear power plant. When that goes to a committee, they'll sign off those proposals within half an hour, because, nobody really understands how to build a nuclear power plant. So absolutely nobody's going to criticise any aspects of it, it'll just get signed through. Whereas, when it comes to building the bike sheds, around the back of the nuclear power plant, well everybody can understand the bike sheds, everybody is going to have a very strong opinion of what the size and shape of the bike sheds should be, how many positions they should be in the bike shed, whether we should allow smoking around the bike shed, etc., etc., etc., the bike shed takes two years to get signed off. The nuclear power plant a half an hour. So, there's quite a common thing that people do when putting a proposal together.
Richard :They will deliberately put some nonsense in, knowing that, that's what everybody is going to discuss. Well should we have double underscores, or should we have one underscore, or should it be a new keyword, and all of the important stuff around it, everyone will ignore and just say that's fine. We'll just sign off. One of the commenters said it, I think he's probably bike shedding. I'm thinking he probably is, so I mean it was a bit of a ramble and it's been nice to talk about it, but, I think it's just one of those cases where several topics have all come together at the same time. It's worth just reviewing really. A lot of people have said, you know in Java we mindlessly create get/set methods. Maybe that's the outcome of this. Just think about what you're doing when you create get/set methods. Trouble is all the frameworks insist you do it anyway.
Matt:Yes, but, I think it's hopefully been helpful for people, especially if you're working in isolation on projects. You're developing your own little world, it's helpful to just get that reminder of think about where is the right place your business logic to be, to be cautious about the service layer and there needs to be a reason for a method to be in that service layer. And rich domain classes, unless you got a reason not to, as you said there's multiple ways of doing things, but, there's all these advantages of that. Particularly the unit testing. It just jumps out at me.
Matt:Yeah, I feel it may have been useful to some of the people listening out there. Certainly for the people who we've been talking to and wanted to raise the discussion points.
Richard :Yeah. I suspect that the people we will be discussing this with a looking for a right and wrong answer in a very concrete way of thinking. With classic trainers, it depends.
Richard :It depends what your requirements are.
Matt:Although it does, there is that feeling of, well normally I would try and always have a richer domain model, try and minimise the service layer. The other thing, we haven't mentioned this, then again if you're doing MVC application, this is the kind of thing I come up with time and time again. You're writing the view part and you need to display, let's go back to that idea of the customer and their status. You wanted to spare the customer's status on the view, but, the status isn't part of the customer's domain model.
Matt:Now you've got to do work in your controller to retrieve the status and bring it through to the view. If it's in the domain model, it's just there and it's easier. I've seen people writing tag-libs, to be able to get this data at the view level.
Matt:... which is horrible. Obviously you wouldn't do that, you'd write ...
Richard :You should be right ... it's like in your controller ...I bet that’s me that’s done that isn’t it?
Matt:It wasn't in Java so, let's be fair.
Richard :It was me.
Matt:I'm thinking of some Groovy code that somebody, Grails code that somebody wrote once. You know, in an ideal world, if you're doing it today you're not going to do that, you're going to write code in your controller to evaluate the status. If you've got a list of customers and you're having to get every status to pass it through to the view, it's bonkers.
Matt:Another good reason for richer domain models is, it makes your views easier, if that's the kind of environment you're working in.
Richard :That's absolutely what you want, it's not over engineering, so don't think ... views change. You want to move from ... you want to build an app on android, whatever, or IOS and your views are a very ephemeral, brittle thing that often change. So definitely. I’m conscious we've been talking quite ... talking design and pondering design, so I think on the next podcast we might get down to some nitty gritty Java. We've been talking about doing the top five, or top ten tips that we would give people in Java the next time around.
Matt:Okay, sounds good.
Richard :On a future podcast we're going to do full critique of one of your systems, after you've just criticised my use of the tag-lib there, by the sounds of it.
Richard :Then again, your back for that.
Matt:We did say that's the code behind the All Things Java website. We would actually make that public on github. So maybe, and that's quite a simple, now that we’ve been talking about this, most of that is a credit application, so let's maybe do that and we can talk through some of that maybe? If you want to critique?
Richard :Good idea I think. At some point in the future. Just one parting shot on this, so I realise we have not talked about microservices, and that could certainly blow all of this out of the water, but, I don't think it's unreasonable microservice can have a domain model. It would just be a small one. That's all. It won't be 50 classes.
Matt:It should be the ... I mean we were talking earlier before this podcast about updating our reporting suite. If that becomes a standalone service, it will have solely the bit of data it needs to do it's work. It won't have any more data than it needs. It's going to need some form of domain model. Optimised for the domain that we're working in and reporting. Absolutely.
Richard :It could be very small and something one person can understand within five minutes.
Richard :The domain model and it's not going to be anaemic.
Matt:It certainly won't be anaemic, no. It's going to be an awful lot of business logic in there.
Richard :Good stuff. So, it will be about two weeks I think, for the next one… two, three weeks.
Richard :This has been All Things Java, we'll see you next time.
Matt:Thank you for listening.