🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
The ViewModel
This page was created by Alexandra on 2018-10-24. Last edited by Wikiadmin on 2026-07-29.

A ViewModel lets you prepare a focused part of your model for a specific use case without putting business rules in the UI; use it when you build UIs, reports, or integrations that need data in a purpose-specific shape.

Why use a ViewModel?

A user interface often needs more than a direct view of domain objects. It may need to:

  • show a calculated value in a particular format;
  • offer a filtered list of valid choices;
  • collect input for an action;
  • coordinate several domain operations for one use case; or
  • expose only the information that a particular user interaction requires.

For example, a screen for setting up a hockey game needs a selected game type, a date, and lists of valid home and away teams. The valid teams depend on the selected game type. That is use-case-specific data preparation. It belongs in the ViewModel, not in UI bindings or event handlers.

Without a ViewModel, this logic tends to move into UI code. The UI then becomes responsible for transforming values, filtering choices, validating inputs, and coordinating operations. That makes the logic harder to find, test, reuse, and change.

What a ViewModel is

A ViewModel is a transformation layer between the domain model and a consumer such as a UI, report, or external application. It transforms a selected piece of the model into data and operations suitable for one purpose.

In MDriven, you define a ViewModel in MDriven Designer. A ViewModel can expose named values, lists, nested data, actions, and validation-related behavior for its use case. OCL expressions define the data made available by the ViewModel.

The most common consumer is a UI, but the same approach also applies when you prepare data transfer objects for another system or data for reporting.

Put logic in the right layer

Use the domain model for rules that describe the business and must remain true regardless of how the system is presented. Use the ViewModel for transformations and coordination that are unique to a particular use case. Keep the UI focused on rendering the ViewModel and collecting user interaction.

Layer Responsibility Example
Domain model Reusable business rules and domain behavior. A game can only be ended when its state allows it.
ViewModel Use-case-specific transformation, available values, and coordination. For the Set up game use case, show only teams valid for the selected game type.
UI Render available ViewModel data and send user interaction to the ViewModel. Display a team picker bound to the ViewModel's list of valid teams.

A practical decision rule

Ask this question before adding logic:

Would this rule still be needed if this UI, report, or integration disappeared?

  • If yes, put the rule in the domain model so that other use cases can reuse it.
  • If no, and it exists to prepare or coordinate this particular use case, put it in the ViewModel.
  • Do not put either kind of rule in UI code or UI binding expressions.

For example, checking whether a selected team is allowed for a game type is a business rule that the model should be able to enforce. Providing a pick list containing the teams allowed by the currently selected game type is ViewModel responsibility. Rendering that pick list as a dropdown is UI responsibility.

What problems this avoids

Keeping use-case logic out of the UI gives you clear operational benefits:

  • Reuse: Multiple UIs can use the same ViewModel for the same use case, such as a basic UI and an advanced UI.
  • Testability: You can inspect and test the ViewModel logic without reading results back from UI controls.
  • Type checking: A ViewModel provides a typed, named contract instead of relying only on string-based UI bindings that fail at runtime.
  • Safe UI work: A UI designer can change layout and styling without changing domain or use-case logic.
  • Independent change: Presentation and business behavior change for different reasons. Keeping them separate makes each change easier to understand.
  • Controlled exposure: The ViewModel defines the data available for the use case, rather than allowing a UI to reach arbitrarily into the domain model.
  • Deployment flexibility: A UI can be separated from the domain layer by a network or physical tier while still using the prepared ViewModel contract.

Avoid moving every UI concern into the domain model

It is possible to keep adding derived attributes, derived associations, and methods directly to the domain model until every UI requirement is met. This causes a different maintenance problem: a large application can accumulate UI-specific model members for every screen.

When a UI is removed, its UI-specific derived members may remain in the model. Over time, it becomes difficult to identify which model members represent durable business concepts and which exist only for a former screen.

A ViewModel prevents that accumulation by making the use-case transformation explicit and local to the use case.

Example: prepare a game setup use case

Suppose the domain model contains Game, GameType, TeamType, and Team. A user must select a game type and then select teams compatible with that type.

Create a ViewModel named GameSetup for the setup use case. It can provide named OCL expressions for:

  • the game being set up;
  • the selected game type;
  • the scheduled date;
  • a home-team pick list filtered by the selected game type; and
  • an away-team pick list filtered by the selected game type.

The UI binds to these named ViewModel values. It does not need its own filtering code to determine which teams are valid after the user picks a game type. If the compatibility rule is reused elsewhere, keep that rule in the domain model and let the ViewModel use it.

For the complete declarative example, including nested list definitions such as a team pick list that depends on the selected game type, continue with Training:The declarative ViewModel.

Design a ViewModel from the use case

Use this workflow when you create a ViewModel in MDriven Designer:

  1. Describe the use case and identify its root object. For example: set up a new game with a Game as the root.
  2. Sketch the information and interactions the consumer needs. Include values to display, values to edit, lists of valid selections, and actions.
  3. Identify reusable rules. Add or use domain-model behavior for rules that must apply beyond this use case.
  4. Create the ViewModel and add named columns and nested data needed by the use case.
  5. Define each value with an OCL expression. Give every column a stable, meaningful name because consumers bind to that name.
  6. Add only use-case-specific calculations, filtering, and coordination to the ViewModel.
  7. Bind the UI to the ViewModel. Keep UI code limited to presentation and interaction.
  8. Test a changed selection and confirm that dependent values and pick lists reflect the ViewModel definitions.

Training:Bootcamp:Chapter 3 shows practical ViewModel editing tasks, including adding columns, working with names and presentation text, and adding a nested ViewModel class.

Keep presentation separate from the ViewModel contract

A ViewModel describes available data, valid values, selection lists, and behavior for a use case. It is not the UI design.

MDriven can also use optional placing hints such as presentation, row, column, and span to give an automatic renderer clues about relative control placement. These are hints, not a replacement for UI design. External styles can still control how the rendered controls look.

Use placing hints when an automatically generated administrative UI is appropriate. Build or refine dedicated presentation for signature screens where the user experience requires it. See Training:Taking It Further Still and Training:Bootcamp:Chapter 8 for placing containers, responsive layout work, and related ViewModel layout behavior.

Maintain a clear ViewModel boundary

A ViewModel is a contract for one use case. Keep that contract understandable:

  • Name ViewModels after their purpose, such as GameSetup.
  • Name columns after what they provide, not after a specific UI control.
  • Keep a derived value in the ViewModel when it is only meaningful to that use case.
  • Move a rule to the domain model when a second use case needs the same rule.
  • Remove or update the ViewModel when its use case is removed or changed.
  • Treat generated AutoForms separately from ViewModels you own. An adopted AutoForm becomes your own ViewModel and is not replaced when AutoForms are regenerated; see Training:Bootcamp:Chapter 3.

Next step

This page introduces the reason for the ViewModel layer. Next, learn how to express a ViewModel declaratively with named OCL expressions and nested definitions in Training:The declarative ViewModel.

See also