This guide explains how to keep business logic out of the user interface by placing reusable logic in the model and context-specific transformation logic in a ViewModel.
Choose where the logic belongs
UI code may otherwise accumulate data transformation, conversion between presentation data and model-scope data, parameter checks, coordination of several operations, and validation. Keep the model as the home for logic that is not unique to one context. Use a ViewModel as the transformation layer for logic that is unique to a specific context or purpose.
| Situation | Recommended location | Rationale |
|---|---|---|
| The logic is needed in more than one context or use case. | The model. | Logic that is not unique should be placed in the model so that it is ready for reuse. |
| The logic transforms model information for one specific purpose or context. | A ViewModel. | A ViewModel transforms a piece of the model for a specific purpose and may contain business logic that is unique to that context. |
| A UI needs data in a rendering-oriented format. | A ViewModel. | The transformation layer can prepare model information as data suitable for rendering. |
Put reusable logic in the model
Use the model for logic that represents behavior or information needed outside one particular UI or use case. The sources identify methods, derived attributes, and derived associations as model mechanisms that can support a UI's needs.
- Identify whether the rule, calculation, or relationship is needed outside the current context.
- If it is not unique to the context, add it to the model using the mechanism appropriate to the need, such as a method, derived attribute, or derived association.
- Let ViewModels and UIs use that model behavior rather than reproducing the same logic.
- Test the logic separately from the UI where possible.
For example, if multiple use cases need the same calculated information, keep that calculation in the model rather than creating separate UI-specific versions.
Use a ViewModel for context-specific transformation
A ViewModel is a transformation layer between the UI and the model. It transforms a piece of the model for a specific purpose. That purpose is often preparation for interaction with a user in a specific use case, but it can also include preparing data-transfer objects for another application or system, or preparing information for reporting.
A ViewModel may contain business logic when that logic is unique to the context in which it operates. When the logic is no longer unique—for example, when another use case needs it—move the reusable part to the model.
- Define the specific purpose or use case.
- Add transformations needed to present model information in the form required by that context.
- Call model behavior for logic that is shared or represents reusable domain behavior.
For example, a ViewModel can prepare model information for a particular UI. If another use case needs the same calculation or rule, place that shared behavior in the model and let each context use it.
Keep logic out of the UI
The sources describe several ways business logic can enter a UI: transforming data for display, transforming selections back to model scope, checking parameters, combining multiple operations, and validating application rules.
Move such logic out of UI code where practical:
- Use a ViewModel for transformations that are specific to the UI's purpose.
- Use model behavior for logic that should be reused.
- Keep UI work focused on interaction and rendering rather than making the UI the sole location of important rules.
This separation supports testing logic apart from the UI and can allow reuse of a ViewModel across different UIs for the same use case.
Review checklist
Before finalizing a rule or transformation, ask:
- Is this logic unique to one context? If yes, a ViewModel may be appropriate.
- Could another use case need the same logic? If yes, place it in the model for reuse.
- Is the UI transforming information only because it needs a presentation-specific representation? Put that transformation in the ViewModel.
- Can the logic be tested separately from the UI?
- Would the logic remain available if this UI were removed or replaced? If not, reconsider whether it belongs in the model.
