Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

When using reusable business objects, what is considered best practice when building view models?

We use an object we call Builder to build our view models. One builder for each logical unit of views (orders, users etc), where each unit can contain a number of different view models (orders contains summary, order lines etc).

A builder may pull data through one or more standard business objects in order to build a view model.

What is considered the better practice when it comes to using business objects/models in view models?

Approach 1

Allow the use of business objects in the view model?

//Business object in some library
public class Order
{
    public int OrderNum;
    public int NumOrderLines;
    //...
}

//Order builder in website
public class OrderBuilder
{
    public OrderSummary BuildSummaryForOrder(int OrderNum)
    {
        Some.Business.Logic.Order obOrder = Some.Business.Logic.GetOrder(OrderNum);
        //Any exception handling, additional logic, or whatever

        OrderSummary obModel = new OrderSummary();
        obModel.Order = obOrder;

        return obModel;
    }
}

//View model
public class OrderSummary
{
    public Some.Business.Logic.Order Order;
    //Other methods for additional logic based on the order
    //and other properties
}

Approach 2

Take only the necessary data from the business objects

//Business object in some library
public class Order
{
    public int OrderNum;
    public int NumOrderLines;
    //...
}

//Order builder in website
public class OrderBuilder
{
    public OrderSummary BuildSummaryForOrder(int OrderNum)
    {
        Some.Business.Logic.Order obOrder = Some.Business.Logic.GetOrder(OrderNum);
        //Any exception handling, additional logic, or whatever

        OrderSummary obModel = new OrderSummary()
        {
            OrderNum = obOrder.OrderNum,
            NumOrderLnes = obOrder.NumOrderLines,
        }

        return obModel;
    }
}

//View model
public class OrderSummary
{
    public int OrderNum;
    public int NumOrderLines
    //Other methods for additional logic based on the order
    //and other properties
}

I can see the benefits and drawbacks to both, but I wonder if there's an accepted approach? In approach 1, there's no duplication of code around the models, but it creates a dependency on the business logic. In approach 2, you take only the data needed for the view, but you duplicate code around models.

share|improve this question
add comment

3 Answers

Option 1 creates a tight-coupling between the domain model and the view. This contravenes the very problem view models are designed to solve.

A view models "reason to change" is if the view itself changes. By putting a domain model object in the view model, you're introducing another reason to change (eg the domain changed). This is a clear indication of a violation of the single responsibility principle. Having two or more reasons to change leads to view models which require a lot of maintenance - probably more so than the perceived maintenance cost of duplication across domain/view models.

I would always advocate approach 2. It's often the case that view models might look very similar, even identical to domain model objects, but the distinction as I mentioned is their differing reasons for change.

share|improve this answer
    
Am I correct in thinking that by "reason to change" you mean change in a maintenance sense, not change in an updating (eg ui event) sense? –  AndyBursh Aug 2 '12 at 15:38
    
@AndyBursh yep that's correct - see this article, particularly the line "Robert C. Martin defines a responsibility as a reason to change, and concludes that a class or module should have one, and only one, reason to change." –  MattDavey Aug 2 '12 at 15:44
    
I like your answer but some thoughts... The view model doesn't necessarily change just because the model changes. Only if you were binding or using a specific property that changed would this be an issue since your reference is to the entire object. Having a reference to the domain object makes it easier to make changes and save it again. Your save methods are also dependent on the domain object so you then have to convert the view model back or have your business method setup to accept view models which isn't good either. I still think #2 makes most sense, but just by two cents. –  KingOfHypocrites Dec 8 '13 at 7:27
add comment

Option 1 is preferable as it avoids code duplication. That's it.

If the domain model changes significantly , it's almost certain that the view will have to change anyway. With option 2, then you have to change the view model AND the builder as well as the view itself. That kind of thing is absolute poison for maintinability. YAGNI.

The point of having a separate view model is to keep state that is meaningful only for the view (e.g. what tab is currently selected) separate from the business model. But the business data itself should be reused rather than duplicated.

share|improve this answer
    
YAGNI - the secret assassin of solving most software design problems. –  Martin Blore Aug 2 '12 at 15:56
4  
I'm sorry but this is horrible advice for all but the most trivial of applications. View models don't have state. They are data transfer objects. What tab is selected is part of the STRUCTURE of the view and has NOTHING to do with the DATA in the view model what so ever. Maintenance isn't a nightmare if you structure your program properly and use something like Automapper to hydrate your view models. –  Lucifer Sam Aug 2 '12 at 16:22
    
"If the domain model changes significantly , it's almost certain that the view will have to change anyway." - Agreed. But what about when you have a small change to the domain? With option one, every little change to the domain (even just renaming a property) requires a corresponding change to the view. This is also absolute poison for maintainability. –  MattDavey Aug 2 '12 at 17:02
    
@MattDavey: if you rename a property then with a separate view model you have to change the view as well (or whatever maps between domain and view model) and now have two different names for the same thing, which is certain to cause confusion. –  Michael Borgwardt Aug 2 '12 at 20:43
    
@Lucifer Sam: obviously we have very different concepts of what a view model is. Yours sounds very, very weird to me, like you're describing mainframe apps for dumb terminals, but certainly not modern web or fat client apps. –  Michael Borgwardt Aug 2 '12 at 20:48
add comment

Principles and mantras are sometimes valuable for guiding design... but here's my practical answer:

Imagine your view models being serialized into JSON or XML. If you try and serialize your domain models you're going to end up with a hideous mess of text and most likely run into issues with circular references and other issues.

The purpose of a view model is not to group domain models together so that the view can consume them. Instead the view model should be a completely flat model of the view... the actual thing you're looking at on the screen. Your view logic should only be concerned with structuring the data that is present in the view model.

Ideally your view model should be composed almost entirely of pre-formatted strings. Think about it... you don't even want a DateTime or decimal in your view model because then you're stuck doing formatting logic in C#, Javascript, Objective-C, etc.

share|improve this answer
2  
I've never had any problems with serializing domain models. And converting everything to strings in a model? Seriously? –  Michael Borgwardt Aug 2 '12 at 15:59
3  
@MichaelBorgwardt Yes, this is what a view model SHOULD be. You don't want to be serializing your domain models and sending them all over the place. All business logic should stay safely at home in one place. The views however should be flexible and able to be rendered on any device which is why you want to completely separate your STRUCTURE, DATA and STYLE. –  Lucifer Sam Aug 2 '12 at 16:07
    
Sorry, but THAT is horrible advice for any application, period. It leads to overengineered applications full of duplicate code that are the exact opposite of flexible. –  Michael Borgwardt Aug 2 '12 at 20:40
1  
@MichaelBorgwardt it sounds like you're used to working with anemic domain models where the entities are little more than property bags with little or no behaviour. In that case yes, a DTO/View-model would basically be a duplicate. However if you have a rich domain model with complex relationships, a layer of DTOs/View-models becomes necessary, and they will not be so similar to the domain entities. –  MattDavey Aug 2 '12 at 22:15
    
@MattDavey: It sounds like the domain models you're used to working with are not just rich but veritable kleptocrats. I don't like anemic models either, but they're still models, and their behaviour should be confined to representing the domain. Single responsibility principle and all that... –  Michael Borgwardt Aug 3 '12 at 10:01
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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