MVVM and MenialTasks : Why did I use TEnumerableBindSourceAdapter instead of TListBindSourceAdapter?

In the comments over on my old MVVM Resource List post Peter Rosario asked a great question. A question I thought I’d covered in my video but I suspect I might have edited it out in an attempt to fit into the CodeRage time limits. So I thought I’d answer it here.

The question was about my MenialTasks sample app, and why I’d used TEnumerableBindSourceAdapter to bind my collection of TTasks to the UI, rather than the more common TListBindSourceAdapter.

TListBindSourceAdapter has a lot going for it. It comes “in the box”, would certainly have been easier, and would work just fine. Given that, why didn’t I use it?

The sticking point I had with TListBindSourceAdapter is because it expects to be bound to a TList<T>, and my TTaskList is not a TList<TTask>. Rather, it is a domain wrapper around TList<TTask> (actually a TObjectList<TTask>, but that’s beside the point).

My TTaskList controls access to the underlying TList<TTask>, providing methods like AddNewTask, AddTask(Task : TTask), etc. These functions make sure that any View or ViewModel code that wants to mess with the contents of my TTaskList has to go through my validation logic (or any other code I want).

Using TListBindSourceAdapter would require exposing my underlying TList<TTask> to client code, allowing them to Add, Delete and Insert as much as they like, and I’d be left having to try and react after the fact.

On the other hand, using TEnumerableBindSourceAdapter meant I just had to expose a TEnumerable<TTask>, providing a much more limited set of capabilities to the client, and leaving my TTaskList in control of its contents.

The follow-on question is: was this the right decision?

If this were one of my own projects it would be an easy answer: Yes, totally. My own convictions on how I design my code, and the relative values I place on expediency vs purity mean I would (and do) use TEnumerableBindSourceAdapter in this situation.

However this wasn’t strictly “my” code. Yes, I wrote it, but it’s for public consumption. Further, the aim of this code wasn’t to show someone how I like to design applications, but rather to serve as a minimal example of MVVM. Given that, maybe I was over-complicating things, or putting the emphasis on the wrong areas? Which option served the educational purposes better?

This is what I went backwards and forwards on many times. The code actually existed both ways at various stages. In the end I decided the additional complexity introduced by TEnumerableBindSourceAdapter stank less than exposing my TList<TTask> in my domain object.

Someone much smarter than me once said “Design is Compromise”, and this is the key here. This decision may not be right for you, or even right for me in every situation. We develop in an imperfect world and often you are left having to balance two imperfect options.

That balancing act is the source of some of the most educational parts of the job, in my view.

Anyway, thank you Peter for the question. I hope that answered it ok.

3 Comments

  • Hi Malcom.
    I found that the TEnumerableBindSourceAdapter is a key part of your MVVM example. Because it makes clear that MVVM should expose to the view only the methods that the view can directly call (ISP from the SOLID principles). That’s it, MVVM is the “ViewModel”, not the “Model”! IMHO a similar bind source should be the built-in version for the Delphi RTL. It is more general the the current built-in version tied to the TList and is more “correct”. In my projects, where the livebindings are applicable, I use only my version of the “enumerable build source” (the real problem of the livebindings is the lack of incremental loading, but this is another story…)
    Usually, some samples are over simplified compared to the real world necessities. Your example shows the correct way to do things, or better, the correct approach… then everyone can decide how much want to diverge from the “best practice”. Keep going with your not-oversimplified examples. Have fun!

  • The EnumerableAdaptor screams “interface”.
    It would be cool to have it implement an interface, so that in my consuming code I don’t have to know what kind of adaptor it is. (Or am I missing something?)

  • Malcolm,
    I think you made the right decision, without any doubt. Do it “right” always serves educational purposes better, especially when that comes with an explanation.

    There is nothing more frustrating to people trying to learn, than examples that are suffixed by “of course you’ve never do it this way in production code”, but never elaborate why (as though it must be obvious).

    Not exposing the internals of the implementation, and thus preserving encapsulation, is unquestionably more “right” than exposing the internal list directly. By doing this you are teaching much more than just the details of the specific case. You are teaching good practise.

    Thank you for bringing this level of sophistication to your examples, and thank you even more for explaining the reasoning. I really hope others follow the example you have set.

    Neville

Join the Discussion

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>