spinettaro / delphi-event-bus

Delphi Event Bus (for short DEB) is an Event Bus framework for Delphi
Apache License 2.0
465 stars 108 forks source link

[Question] MVVM and DEB #39

Open sonjli opened 4 years ago

sonjli commented 4 years ago

Hi, I hope this is the right place to ask a question. Feel free to remove this false "issue". I used the deb protocol some years ago in java with a small "single" page application. I think it is an elegant solution to an hard architectural problem. I built an MVVM structure in Delphi with your deb pattern library. How would you solve this (the problem is simplified): Assumption: One ViewModel (called vmA) with three Views and One ViewModel (called vmB) with 2 views. The [Subscribe(...)] is positioned in a "master view" class of the framework and the five views inherits from it. The master view subscribe to "viewmodel.topic" an avent called "OnViewModelCalling". The ViewModels calls the post() to the "viewmodel.topic". How can I be notified who is the "Sender" ViewModel of the event? I mean vmA or vmB? Do I add these infos in the event object or are there any other solutions?

One solutions without object sender I am thinking: One "topic" per "sender" (viewmodel.topic.vmA and viewmodel.topic.vmB). But I have to move the [Subscribe(...)] to children and the responsibility of MVVM comunication system is passed to the concrete class. I don't like this.

Thanks Eddy

dkounal commented 4 years ago

I believe that when subscribing for channels, in parameters of RegisterSubscriberForChannels (except the sender that it is needed), the name of the channel should be defined and not with RTTI. In such a way, each object instance will subscribe more efficiently @spinettaro

sonjli commented 4 years ago

My problem is more simple, I guess: If I post an event from vmA then also the 2 views that don't refer to vmA receive the event, so I have to filter the event programmatically inside the subscription.

wxinix commented 4 years ago

When you post an interface-typed event, you can also specify a string-typed context as an additional argument of IEventBus.Post

Hence the string-typed Context argument of IEventBus.Post can be used as a “filter”.

sonjli commented 4 years ago

Yes @wxinix, you're right and this what I actually do. I am just saying that too much filters could a be a bit harmful overtime.

for example, in an app with hundreds of forms (views) one event is posted once by a viewmodel and broadcasted hundreds of time, and maybe it is useful to only 3 or 4 of those forms. The bug risk is behind the corner.

I must say that DEB is very good, no other words. I really like it. Just asking: Is there any other solution other than filtering the events?

wxinix commented 4 years ago

for example, in an app with hundreds of forms (views) one event is posted once by a viewmodel and broadcasted hundreds of time, and maybe it is useful to only 3 or 4 of those forms. The bug risk is behind the corner.

@sonjli - Understand. I guess that is unavoidable and the "karma" of this type of event bus, when it comes to large number of subscribers, e.g., "hundreds of forms (views)"? By all means, delphi_event_bus as a lightweight event bus implementation, is not intended as a very performant Message Queue (if you use it that way) for dispatching voluminous/high-frequency messages, mainly due to the heavy dependence on RTTI, and due to the simple loop to enumerate all subscribers synchronously inside IEventBus.Post.

sonjli commented 4 years ago

So @wxinix, you mean DEB is not good for MVVM?

wxinix commented 4 years ago

So @wxinix, you mean DEB is not good for MVVM?

That is not what I meant.

What I meant is that DEB is probably not good for use as a Message Queue (MQ) for high-frequency/voluminous message dispatching. To that end, an MQ implementation such as RabbitMQ probably is a better choice.

It would be your judgement call to see if your application fits DEB and vice versa. I use DEB for my MVVM purpose, and happy with it.

Coming back to your specific situation where you have "hundreds of views" subscribing to ONE global event bus, it seems to me more of a scaling problem. The potential solution would/might be:

  1. Make good/wise use of Context, or,
  2. Rather than using a GLOBAL singleton event bus, you might want to consider using multiple event buses. In other words, you can have your own event-bus factory, while having more than one event buses in your application. Each event bus is dedicated to a certain "domain" to "cross-cutting" your "hundreds of views".
  3. In the EventBus.Core.pas unit, there is a TEventBusFactoryclass, you might want to check it out.

Does this make sense to you?

spinettaro commented 4 years ago

@sonjli the main principle behind the publish/subscribe pattern is that the event consumer and the publisher are completely decoupled: the consumer knows nothing about the producer and the producer knows nothing about the consumer. What you are describing is against that principle so I would suggest to pay attention on that. If a view its interested to an event and it receives it, it seems ok from my eyes. As @wxinix suggested you can define a different context, but you can also decide to unregister the View and register it again in future. Unregistering it because it is not visible anymore, it is in pause or stuff like that...

sonjli commented 4 years ago

@wxinix ;) I use rabbitmq too in my project for mq based microservices. I was thinking about the 2nd + 3rd solution you write, but after reading the "unsubscribe" suggestion by @spinettaro, I think this can be the right way. A small "traffic light" solution with event bus... I have to think.

wxinix commented 4 years ago

@wxinix ;) I use rabbitmq too in my project for mq based microservices. I was thinking about the 2nd + 3rd solution you write, but after reading the "unsubscribe" suggestion by @spinettaro, I think this can be the right way. A small "traffic light" solution with event bus... I have to think.

@sonjli Glad to here you find a solution that you feel right. I like the way you characterize the solution - "traffic light". It may add an extra layer of book-keeping efforts, while you turning ON/OFF that "traffic light".

Also I have a question for you - what do you think of the HashLoad/horse versus Delphi MVC framework? It seems HashLoad/horse has very clean code quality/style as my first impression, and a large user community.

sonjli commented 4 years ago

Well, DMVC is a long-time project and I used it for years and keep using. I think it is mature for production and very feature rich. There are some behaviour about the "orm" level (called activerecord) that are not so good, but it is a young feature so I can wait. IMHO Horse is "too simple" (sometimes this is a good thing... I know). Good implementation but poor in features. I see a big community, but the dmvc's one looks bigger to me... Dmvc has a good written manual behind and Daniele Teti is a big expert. Vinicius is a great developer, too. I love Boss. I tried some time ago Horse for simple "test cases" and nothing more. I know the good performance of dmvc but nothing about Horse. Anyway I would like to see in both dmvc and horse, a "disconnection" from TWebModule. Good 25 years ago, but now with some lacks that doesn't permit modern programming techniques like injiection, pub/sub, threading models, etc.

danieleteti commented 4 years ago

Hi @sonjli , thank you for your kind words about dmvcframework. I'm interested in your POV about ActiveRecord and TWebModule. I follow this repo because @spinettaro is a former colleague of mine, is a good friend, and I like DEB.

Specifically

  1. ActiveRecord is a well known design pattern, and is quite different to an ORM (which is variant of another design pattern called DataMapper). In which ways could be improved in your opinion? I'm creating the roadmap and I love to get feedback form the users.
  2. TWebModule is there for a reason, and this reason is called WebBroker. WebBroker allows to create apache modules and ISAPI. Removing WebBroker would be a big cut of features. DMVCFramework, as you told, is robust, fast and is used in very big systems (hundreds of thousands of connections per seconds) all over the world. Remove Apache support is not an option.
sonjli commented 4 years ago

I knew this was a trap... evil people! ;) (and I knew you and @spinettaro work toghether... I am from Treviso and we met in some Delphi conf in Milan years ago. I was a Borland Delphi 6 certified teacher at Consist, about 1000 year ago. Good times...).

  1. I perfectly know. In DMVC issues you can read my opinions and requests. I really love dmvc, and I can wait for new features. AR integrated in DMVC is an incredible time saving feature. With time I'll add other small things but it's midnight...
  2. I don't say TWebModule and WebBroker is trash, but Borlan... ehm, Embarcadero should give a general refactoring or someone (don't look at me :B ) should give an "option". Just that.
danieleteti commented 4 years ago

Great! :-) Good, keep in touch for any proposals you have. As you know dmvcframework is community driven, and a valuable and expert, opinion is gold. Maybe we'll see soon (??) at an event.

sonjli commented 4 years ago

Event? Yes, why not? When\Where next? Covid permitting... keep in mind I am a beer lover... (@spinettaro you are advised too) :D

danieleteti commented 4 years ago

The next event will be on-line, as usual these times... maybe next year, Covid permitting. P.S. Belgian beer for me, please... ;-)

wxinix commented 4 years ago

Dmvc has a good written manual behind and Daniele Teti is a big expert.

@sonjli Thank you for the insights and sharing your experience. I am preparing for a new project set up, and researching various options, including mORMot and DelphiMVC. Your input is greatly appreciated. Do you mind sharing your thoughts on mORMot?

It is also great to see @danieleteti around here. I hate you for keeping publishing Delphi Cook Book one after another. Every time a new edition becomes available, I have no choice but keep buying every one of them, simply because I don't want to miss any gems in the book(s)!

sonjli commented 4 years ago

I tried to learn mORMot years ago but I left it cause the complexity of the system. This is my opinion (just before the mormot community kill me...): mormot was written to avoid the use of the newest construct of ObjectPascal (attributes, generics, etc.) and keeping a high portability, which is a good thing for porting old projects or for FreePascal, but not a modern approach for a Delphi developer. Said that, I don't know any part of mORMot other than the "webservice" module.

danieleteti commented 4 years ago

@wxinix thanks for your kind words, really appreciated. :-)