2

So I'm using C# WPF and binding to a Model View to display states. The data that needs to be displayed is spread across a couple different classes. For instance I have a class that reads out digital IO values that need to be displayed on the main interface as red or green lights.

Is it better to simply pass the Model object to the classes have them update the properties directly? This seems easier in the short term but smells weird.

EDIT

I think a better word for what I'm asking about is encapsulation. Encapsulation seems to be an important concept in OOP.

In case 1 the model is "encapsulated" in the Main class. Other objects do not interact with the Model directly. delegate methods are used. This seems verbose and a bit messy, but this is the solution I'm looking at to keep the data encapsulated.

In case 2 the model is passed to a secondary object as an argument in the constructor, which is acting on the model concurrently with the original instantiater. Seems to break the encapsulation rule, and could be confusing in the shear number of places the model may be accessed. This will be especially true where various classes have data that needs to be viewed.

This could be entirely opinion based. I see benefits and pitfalls of both approaches. Case 2 doesn't lend itself to being reused. Whereas Case 1 could be implemented elsewhere.

In practice is one preferred over the other? How important is encapsulation? Should I maintain it at the expense of readability?

MSDN Implementing the MVVM Pattern

Well-designed view, view model, and model classes will not only encapsulate the correct type of code and behavior; they will also be designed so that they can easily interact with each other via data binding, commands, and data validation interfaces.

END EDIT

The solution I'm working on is using delegates. For instance:

Case 1

public delegate void PrependLog(string log);

public class MyDemoClass
{

   private void DoStuff(string str)
   {
     //Do stuff
     OnPrependLog("Did stuff");
   } 
   public PrependLog PrepLog
   public virtual void OnPrependLog(string str)
   {
      if(PrepLog != null)
         PrepLog(str);
   }

}

Then from the main:

public MainWindow()
{

   MyDemoClass objDem = new MyDemoClass;
  //Assign delegate
   objDem.PrepLog = (val) => {Model.LogText += val;}


}

But from a readibility standpoint, it seems like it would be easier to just pass the MyDemoClass the model and update the log text directly.

Case2

public class MyDemoClass
{
  MyModel Model;

  public MyDemoClass(MyModel model)
  {
    Model = model;

  }

  private void DoStuff(string str)
   {
     //Do stuff
     Model.LogText += "Did Stuff";
   } 

}

closed as unclear what you're asking by Scant Roger, Bart van Ingen Schenau, GlenH7 Dec 9 '15 at 22:29

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • The more separation, the better. I have used events (like via a messenger type class or hooked directly) to pass information across. – Branco Dec 9 '15 at 1:30
  • In fact, I don't understand a few points. I haven't read the code, perhaps the code would explain it, but from your text, I don't see what the issue is here. You said that data is spread over various classes, are you referring to various models or do you want to consume data from other view models (that already kinda processed the model data)? If you have a class that reads data, you put the data into your model. Then any view model that needs that data should/can access that model and process data according to the needs of the view. If a vm needs several models, that's fine. – Em1 Dec 9 '15 at 10:01
2

I hope you understand that there is no objective answer to your question, and as such it is liable to be closed as primarily opinion based. But funnily, the one close vote so far is for "unclear what you are asking", which simply means that someone did not understand what you are asking. So, here is an opinion.

Assuming that these "classes" of yours conceptually belong to the model, (otherwise, nothing makes sense and you have other, serious issues,) it is, in my opinion, perfectly okay to pass the model to them, so that they may use the services offered by the model.

Lately I have been successfully making use of this scheme that I have come up with, which I call Subject Oriented Design and Subject Oriented Programming. It is inspired from Domain Driven Design. It basically says that every single object which belongs to a domain (and models are virtually always domains) is owned by the domain, so it is a subject of the domain. (Think of domain as a kingdom, where inhabitants are subjects.)

Various rules apply, for example nobody is allowed to instantiate a subject except the domain itself, so domains act as factories for their subjects, but the rules which you might find to be of interest for your particular situation are that:

  • Every single subject receives as its first constructor parameter a reference to its own domain. Conceptually, this is related to how every single instance method of a class receives as its first parameter a (hidden) this pointer. Instance methods need the this pointer to access members of the object, subjects need the domain pointer to access services of the domain.

  • The domain makes various services available to its subjects, and since each subject has a reference to its own domain, it gets whatever service it needs from the domain and uses it. This way, inversion of control (dependency injection) is only necessary at the domain level, not at the individual subject level. And of course domains can be subjects of other domains, so dependency injection can be achieved very easily by passing services to domain constructors, without the need for magic dependency injection frameworks like Spring.

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