1

Edit: There is no "right" or "wrong" answer here, I was merely trying to get people to share their dos and don'ts.

Behind this rather vague topic I would like to address a few problems I've been having in my last projects. As a general rule, I try to keep it simple, follow design patterns and the Single responsibility principle.But all those things leave certain questions unanswered, or at least unclear.

Let's consider this simplified example of a typical MVC WebApp from the Gui to the persistence layer (only snippets and pseudo code):

View.xhtml

<h:form>
    <p:inputText value="#{model.text}" />
    p:commandButton value="Save" actionListener="#{controller.saveToDb}" />
</h:form>

Model.java

String text;
String getText();
void setText(String text);

Controller.java

@Inject Model
@Inject Service
public void saveToDb(){
service.saveToDb(Model.getText());
}

Service.java

@Inject dao

public void saveToDb(String text){
Entity entity = new Entity(text);
dao.persist(entity);

This is just an illutration, but imagine several methods on every level, controllers calling services and services calling each other. (Some old schoolers may want to add a Facade between the controller and the service).

With this design in mind, here are a few questions:

  • What should methods return ? Void and Exceptions in case of errors ? Custom Result POJOs with values ?

  • How to implement error handling ? Checked or unchecked exceptions ? Do you handle a Service exception locally (if yes, what do you return ?), or do you throw it up to the caller ?

  • Is it OK for controllers to call other controllers ?

  • Do we really need a Value Object and Data Transfer Objects for every use case ? Why not send back entities ?

  • Should the Service check parameters, or should it just process data, assuming it has been checked before and it is correct ?

  • When checking data, is it OK to have several sequential checks, and return as soon as one fails ? (Bonus question: is is frowned upon to return in a void ?)

About single responsability: Imagine a scenario where you want to create a pojo, send it per http post and persist it. You would have:

  • A service to create the pojo
  • A service to send it via http post
  • A service to persist it
  • A controller reacting to a button clicked on the view

How and where do you combine the two ? Does the controller call the creation service method, then if successful the sending service method, and finally the persisting service method ?

Or is there one method in the controller called "createSendAndPersist()" that calls all 3 service methods in turn ? How do you handle errors in this case ?

I know, there are many ways to do this and there is no "right" answer. But what are best practices ? What did work best for you ?

1 Answer 1

2

Do we really need a Value Object and Data Transfer Objects for every use case? Why not send back entities?

OK, I'm only going to try to answer this one of your many questions.

Option 1: If your database exactly models your business, and there are no arcane business rules, then by all means use entity objects in your GUI layer. The programming will be simple and elegant, as your GUI is simply exposing your business model. Just keep in mind, that should your business model change, you will need to update the database schema to reflect the change, and update your GUI and possibly lots of reports to suit. In my opinion this is the way to go, especially for a greenfields project.

Option 2: Add a couple of layers of abstraction between the database and the GUI. Implement those increasingly arcane business rules in the "business" layer and seldom. if ever, change the database schema. In a few years you will have an unmaintainable mess. Every new feature will need to be tweaked to support work-arounds from previous feature additions.

I have worked with both, and Option 1 is certainly the future-proof way to go. Unfortunately you don't always have a choice.

1
  • Just as an addendum, there's nothing wrong with Keeping It Stupid Simple with Option 1 until you've proved a need for the extra layers of abstraction provided by option 2. Code is a living thing; it grows and evolves.
    – RubberDuck
    Commented Jul 25, 2016 at 11:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.