31

I've developed for several web application projects for the last 3 years, both personal and at work, and I can't seem to figure out whether it's possible for at least some business logic not ending up in the view layer of the application.

In most cases there will be problems like "If the user has selected option x then the application must enable him to supply info for y, if not then s/he should supply info z". Or do some AJAX operation which should apply some changes to the model but NOT commit them until the user has explicitly requested so. These are some of the simplest problems I've encountered and I can't figure out how it's possible to avoid complex logic in the view.

Most of the books I've read describing MVC usually showcase some very trivial examples, like CRUD operations that just update data on the server and display them, but CRUD is not the case on most rich applications.

Is it possible to achieve having a view with no business logic at all?

  • 2
    Have a look at the MVC derivations MVP and MVVM (see en.wikipedia.org/wiki/Model_View_Presenter and en.wikipedia.org/wiki/Model_View_ViewModel), they might be what you are looking for. – Doc Brown May 20 '14 at 11:16
  • related (possibly a duplicate): Decoupling classes from the user interface – gnat May 20 '14 at 12:17
  • 2
    The view is the external, visible manifestation of your data and logic. It is not possible for the view NOT to present business logic. Or are you saying that the view should not have any code in it? You can certainly create HTML-only views. – BobDalgleish May 20 '14 at 12:21
  • You might look into template animation; while this probably won't eradicate all logic from the view layer, it looks like it should lead to a bit better separation of things. – paul May 20 '14 at 16:27
  • I think a better question is whether it is better for view data to pollute the model or is it better for the view to contain view logic which is related to the business logic? That is the more real world scenario. Your question is essentially advocating pollution of the model to support views as that would be the only way to accomplish what you are asking. – Dunk May 20 '14 at 21:52
22

Is it possible to achieve having a view with no business logic at all?

I find this a deceptively hard question to answer. (Thought-provoking question!)

Theoretically, yes, depending on what we define as business logic. In practice, strict separation becomes a lot harder, and maybe even undesirable.

Separation of concerns is a great way to think about building software: it provides you with ideas about where to place code, and it gives maintainers a good idea about where to look for the code. I'll argue that it's basically impossible for humans to build working software without separation of concerns. We need this.

But, as with all things, there are trade-offs. The best conceptual location may not be the best location for other reasons. Maybe there's too much load on your web server, so you add some javascript to your web pages to catch easy input errors before they hit your server; now you have some business logic in your view.

The view itself, on its own, has no value without the business logic. And to be effective in use and display, implicitly or explicitly, the view will have some knowledge of the business processes going on behind it. We can limit that amount of knowledge, and we can cordon off parts of it, but practical considerations will often force us to 'break' separation of concerns.

  • 2
    The best conceptual location may not be the best location for other reasons : Bravo!! – Magno C May 23 '14 at 12:48
8

I usually do this: if the user has selected option x, the view calls

controller->OptionXChanged()

Then controller enable y on the view:

view->SetEnableInfoY(True) // suppose False=SetDisable

The view notifies the controller of what happens without deciding anything.

  • +1. OP's trivial problems would usually be handled like this in a nontrivial application – dev_feed May 21 '14 at 12:25
  • Putting this logic in the controller has two problems: 1) it complicates unit testing, and it is impossible to support multiple views of the same data. – kevin cline May 23 '14 at 20:48
4

I question whether the examples you describe are really business logic. The examples you describe are operations that can be performed on the system. It is how you chose to present the choices to the user that maybe gives the appearance that you are doing business logic in the view.

From the "View" vantage point it is only providing InfoY or InfoZ to the system. Just because your UI implementation is doing some dynamic updates based on an operator choice (ie. enabling InfoY or InfoZ) doesn't make the functionality business logic. It is really view implementation logic. You could very well have simply given the operator a choice to enter InfoY or InfoZ without the whole enabling thing. In that context, would you still consider it business logic? If not, then the same applies for dynamically enabling/disabling info fields.

Same goes for the commit example. These are 2 separate operations the system requires to work properly. Your View has to be able to initiate the proper actions to perform the desired functionality. Does knowing how to use your system mean that the business logic is leaking through? I can see how someone might say yes but if you believe that way then the reality is that there is no such thing as separation of business logic from anything. You have to know what the system is doing/working with to accomplish anything meaningful. Otherwise, it would be a breeze to create a single generic View and Controller that works with every conceivable MVC application. Which we know is impossible.

Bottom line, I think your definition of business logic is not the same as others definition.

1

I work this way (Struts2 + Hibernate):

My Struts Actions is only responsible for show informations on web browser. Not thinking.

User -> Action -> Service -> Repository -> Data Access

Or:

I Want See -> How to see -> What to Do -> How to Get -> Where to get

So, in first layer (the view) I have something like:

public String execute ()   {
    try {
        CourseService cs = new CourseService();
        Course course = cs.getCourse(idCourse);
    } catch (NotFoundException e) {
        setMessageText("Course not found.");
    } catch (Exception e) {

    }
    return "ok";
}

As you see, my "view" do not think. It's asking for a service (for manage courses) a specific course. That service can do many things more, like reports, seraches, and so on. The results is always a list or a specific object (like the example). The services are the real machine, apply rules and access the Repository (to manage the data).

So, if I put my Services, Repositories and DAOS in different libraries, I can use it even in a text-based program, or a Window based desktop system with changing nothing.

The service knows what to do, but does not know how to show. The view knows how to show, but does not know what to do. The same with Service / Repository: The service send and request for the data, but does not knows where the data is and how to take it. The repository "make up" the raw data to buisines objects so the Service can work with.

But the Repository does not know anything about the database. The database kind (MySQL, PostgreSQL, ... ) concerns to DAO.

You can change the DAO if you want to change the database and it must not affect the upper layers. You can change the Repository if you want to update your data management, but this must not affect the DAO and upper layers. You can change the Services if you want to change your logic, but this must not mess with layers above nor below.

And you can change anything in view, even the technology (web, desktop, text) but this must not implies in touch anything below.

The business logic is Service. But how to interact with this is to view. What button to show now? Can the user see this link? Think your system is a console-based program: you must deny if the wrong user choose #> myprogram -CourseService -option=getCourse -idCourse=234 or stop him to press the keys to write this command?

Talking in web-based systems (Struts+JavaEE) I have a separate GUI controller package. In view Action I give the logged user and the class gives me the buttons (or any interface element I want).

                <div id="userDetailSubBox">
                    <c:forEach var="actionButton" items="${actionButtons}" varStatus="id">
                        ${actionButton.buttonCode}
                    </c:forEach>
                </div>

And

private List<ActionButton> actionButtons;

Remember to keep this out from the services. This is VIEW stuff. Keep it in the Struts Actions. Any interface interactions must be fully separate from the real business code, so if you port your system, will be easy to cut what you won't need anymore.

1

In most cases there will be problems like "If the user has selected option x then the application must enable him to supply info for y, if not then s/he should supply info z"

That is logic for the model, not the view. It may be a "view-model", created specifically to support the UI, but it is still model logic. The control sequence is:

  • Controller attaches a handler for view events
  • View attaches a handler for model events
  • The user selects option X.
  • The view raises an event "Option X Selected"
  • Controller receives the event and calls model.selectOptionX()
  • The model raises an event "Model state changed"
  • The view receives the model changed event and updates the view to match the new state: inputY.enable(model.yAllowed()); inputZ.enable(model.zAllowed());

UI View Controller Model |.checkbox X checked.> | | | | | .. X selected ...>| | | | |-----> set X ------->| | | | | | |< .............state changed ............| | | | | | |-------------- Get state --------------->| | | | | | |<----------- new state ------------------| | <-- UI updates ------| This is the classic MVC pattern. It is possible to completely test the model logic separate from the UI. The controller and view are very thin and easy to test.

=== In response to Dunk ===

The Model in a UI MVC pattern is (usually) not a business object model. It is just the model for the UI state. In a desktop application, it may hold references to multiple business models. In a Web 2.0 application, it is a Javascript class that holds the UI state, and communicates via AJAX to the server. It is very important to be able to write hands-off unit tests of the UI state model, as that is where most UI bugs are found. The view and controller should be very thin connectors.

  • 1
    I guess it all boils down to what you believe the definition of MVC is. This version definitely adheres to a very, very strict interpretation of MVC. The problem is that this strict interpretation seldom provides a useful or maintainable system in real life. Reason being that just about every time you come up with a new UI element/way of doing something you have to change the model. The model then becomes cluttered with useless properties only relevant to the UI. These have nothing to do with the application you are trying to build but only to how you want to present data to operator. BAD! – Dunk May 20 '14 at 21:16
  • kevin please put your responses here in comments box, so it's easy for us to reply you. I agree with you. It's not possible to maintain interface (UI) information without any kind of structure, but the "MODEL" nomenclature may be confusing. I prefer to manage UI stuff in a different interchangeable package to be easy to do what @Dunk is talking about. See my answer. – Magno C May 23 '14 at 12:37
  • @MagnoC: I edited he answer in response to Dunk because I thought the added text improved the answer. That's what the site is about: questions and answers. Model is a pretty general term, and in the MVC pattern, it means "UI state model". – kevin cline May 23 '14 at 20:44
0

A business logic is more like If X then return InfoType.Y, then the UI will display fields based on result returned by the domain.

// Controller method pseudocode
option changed routine

    get selected option

    get required info type from domain routine based on selected option

    display fields based on required info type

If the UI requires a business logic, then delegate the choice to the domain. The UI will simply act upon the decision.

0

If the user has selected option x then the application must enable him to supply info for y, if not then s/he should supply info z".

There are inputs that have conditionally based required values. In most GUI environments, there are a lot of choices on how to handle inputs especially the timing. The selected option (in this case x) needs to be processed, so send it to the controller. Send it when the users leaves the input field. Wait until they click on another object or hit save. Doesn't matter to the business logic. One way or another, the controller will make a decision and needs to tell the view, "y is required".

How the view interprets or implements this doesn't really matter from a business logic standpoint. Make y a required field. Have a pop-up or shoot off a cannon and tell the user to enter y or just be stubborn and don't let the poor user do anything until she figures this out.

And just think, all of this may have occurred because the controller tried to save and didn't put in a value for a required field in the database and was purely responding to a database error. It doesn't matter as far as the view is concerned.

Something like a required or limited value for an input can be handled in many places. If you "only" address it in the view, many developers would see this as a problem when there can be multiple user interfaces. This is why business logic can be created and tested without much of a user interface or even a database. You don't even have to have a website.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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