1

i'm wondering if there is a pattern how to separate the domain logic of a class from the ui responsibilities of the objects in the domain layer.

Example:

// Domain classes
interface MachinePart
{
    CalculateX(in, out)
    // Where do we put these:
    // Draw(Screen)  ??
    // ShowProperties(View)  ??
    // ...
}

class Assembly : MachinePart
{
    CalculateX(in, out)
    subParts
}

class Pipe : MachinePart
{
    CalculateX(in, out)
    length, diamater...
}

There is an application that calculates the value X for machines assembled from many machine parts. The assembly is loaded from a file representation and is designed as a composite. Each concrete part class stores some data to implement the CalculateX(in,out) method to simulate behaviour of the whole assembly. The application runs well but without GUI. To increase the usability a GUi should be developed on top of the existing implementation (changes to the existing code are allowed). The GUI should show a schematic graphical representation of the assembly and provide part specific dialogs to edit several parameters.

To achieve these goals the application needs new functionality for each machine part to draw a schematic representation on the screen, show a property dialog and other things not related to the domain of machine simulation. I can think of some different solutions to implement a Draw(Screen) functionality for each part but i am not happy with each of them.

First i could add a Draw(Screen) method to the MachinePart interface but this would mix-up domain code with ui code and i had to add a lot of functionality to each machine part class what makes my domain model hard to read and hard to understand.

Another "simple" solution is to make all parts visitable and implement ui code in visitors but Visitor does not belong to my favorite patterns.

I could derive UI variants from each machine part class to add the UI implementation there but i had to check if each part class is suited for inheritance and had to be careful on changes to the base classes.

My currently favorite design is to create a parallel composite hierarchy where each component stores data to define a machine part, has implementation for UI methods and a factory method which creates instances of the corresponding domain classes, so that i can "convert" a UI assembly to a domain assembly. But there are problems to go back from the created domain hierarchy to the UI hierarchy for showing calculation results in the drawing for example (imagine some parts store some values during the calculation i want to show in the schematic representation after the simluation).

Maybe there are some proven patterns for such problems?

hansmaad
  • 18,417
  • 9
  • 53
  • 94

3 Answers3

0

You can take a look at the model-view-presenter (mvp) and model-view-viewmodel (mvvm) patterns.

Fowler's presentation model includes two sample applications; it also might be of interest to you.

I think that investigating these patterns will give you some ideas on how to continue. Mvvm looks a lot like your current solution; so i'd start there if I were you.

Marijn
  • 10,367
  • 5
  • 59
  • 80
  • I read a lot of MVC, MVP, MVXYZ, Passive view... articles and all tell me to separate the busines logic from ui code but not how to do the separation in a real world example. I follow the guidelines in all gui projects but get into troubles when it's not as simple as `DrawText(mymodel.GiveMeText)`. mvvm seems to be a ms specific pattern (this is not a .NET project). I can find only C# / WPF articles that are very technical. I need a more general pattern. – hansmaad Jan 04 '11 at 11:59
  • MVVM is discussed a lot in MS .net context but is not totally "MS specific". MVVM in Java was discsussed on SO before [link 1](http://stackoverflow.com/questions/2984828/is-there-anything-similar-to-wpf-and-mvvm-in-java-world) | [link 2](http://stackoverflow.com/questions/2105121/what-to-use-mvc-mvp-or-mvvm-or) – Marijn Jan 04 '11 at 21:46
0

Agree with @Marjin, and to generalise his answer. What you need is Model-View-Controller of which MVP and MVVM are variants. From your comments I think you understand that, but need to understand how to implement the pattern. Without knowing your language & target architecture it's hard to give absolute specifics. Notwithstanding, I'd start with the Observer pattern (link has sample code).

The problem you're dealing with is how to provide observable access from the domain to the UI - without encumbering the domain with UI-specific code. Observer provides a means to do that. It does require domain changes, in particular to enable registration of observers and notification of changes. However there's nothing GUI-specific in that so it stays well encapsulated.

hth.

PS: If your app is a typical thin-client web app you'll need to modify the approach. And beware: lots of web app frameworks are advertised as "MVC", but the implementation is architecturally quite different to the Observer pattern.

sfinnie
  • 9,854
  • 1
  • 38
  • 44
  • You're right that observer registration in the domain classes doesn't add ui code to the domain. But my main problem is not when to draw the domain object but how. The client code of the MachinePart composite knows only the abstraction of the domain "Calculate" and doesn't know the concrete assembly and so it doesn't know how to draw it. Each MachinePart could say "Draw a red circle in a green rect" but thats not part of the domain and i don't want to burden my domain code with this knowledge. – hansmaad Jan 04 '11 at 13:57
  • Per OP you'll need two hierarchies, one for domain classes and one for UI classes. Simplistically, each domain class has a corresponding UI class that knows how to draw that part type. The domain class and its corresponding UI class are connected using Observer (I wouldn't have UI classes inherit from domain counterpart). Each UI subclass would have a `draw()` method which would render the appropriate shape(s) for its counterpart domain class. Traversing the structure would fall to the UI counterpart for `Assembly` for which `draw()` would iterate over `Assembly.subParts`. – sfinnie Jan 04 '11 at 15:11
0

Maybe a View Helper can help. It's not a C++, but a Java EE pattern, but in your case it will definitely separate your domain objects from their presentation details...

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
yegor256
  • 102,010
  • 123
  • 446
  • 597