| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#1
| |||
| |||
| I've been studying an article in Dr Dobbs on event based programming: http://www.ddj.com/architect/208801141 The article describes an event based architecture in which objects communicate primarily through events. The article goes into some detail as to what events actually are; it describes the difference between typed and untyped event notification, for example. However, my primary interest in the article has to do with what it calls binders. A binder is an object that connects other objects together so that they can communicate with each other through events. Typically, a binder would contain code like: widgetA.Attach(widgetB); From there, widgetA communicates to widgetB through some kind of event mechanism. This could be through virtual method calls or something fancier like what's provided with C# and its events. I like this approach to programming and have been using events for awhile. It provides a way to decouple classes. However, recently I'm having a hard time scaling this approach up. My latest project involves a large number of objects, and my binder classes are getting large as a result. Basically, I wind up writing a ton of configuration code just hooking everything together. How can I continue to use this approach without being overwhelmed writing configuration code? Refactoring comes to mind, i.e. refactor the binding code into several different places, but that's about it. |
|
#2
| |||
| |||
| "Leslie Sanford" <jabberdabber@bitemehotmail.com> wrote: > I've been studying an article in Dr Dobbs on event based programming: > > http://www.ddj.com/architect/208801141 > > The article describes an event based architecture in which objects > communicate primarily through events. The article goes into some detail as > to what events actually are; it describes the difference between typed and > untyped event notification, for example. However, my primary interest in the > article has to do with what it calls binders. A binder is an object that > connects other objects together so that they can communicate with each other > through events. Sounds a lot like communicating sequential processes and the Occam language. > Typically, a binder would contain code like: > > widgetA.Attach(widgetB); > > From there, widgetA communicates to widgetB through some kind of event > mechanism. This could be through virtual method calls or something fancier > like what's provided with C# and its events. > > I like this approach to programming and have been using events for awhile. > It provides a way to decouple classes. Does it really? I suspect that widgetA and widgetB still have to know quite a bit about each-other in order for this to work. |
|
#3
| |||
| |||
| "Daniel T." wrote: > "Leslie Sanford" wrote: <snip> >> Typically, a binder would contain code like: >> >> widgetA.Attach(widgetB); >> >> From there, widgetA communicates to widgetB through some kind of event >> mechanism. This could be through virtual method calls or something >> fancier >> like what's provided with C# and its events. >> >> I like this approach to programming and have been using events for >> awhile. >> It provides a way to decouple classes. > > Does it really? I suspect that widgetA and widgetB still have to know > quite a bit about each-other in order for this to work. Well, typically widgetB's class would implement an abstract base class. It's through the abtract base class's interface that widgetA sends notifications, so there's no direct knowledge between the classes. In C#, I could decouple things further by doing this: widgetA.SomethingHappened += widgetB.OnSomethingHappened; widgetB's OnSomethingHappened method has to agree with wedgetA's SomethingHappened event signature. That's about all the coupling involved. I'm assuming there are no cycles. If you were to draw out the objects and their connections, it would look like a DAG, i.e. no handshaking. What I'm finding challenging is that I have a lot of these relationships in my code, and I'm finding myself writing a ton of code just to connect the dots. Since in my current application the relationships are static for the lifetime of the app, one approach I'm considering is passing objects into the constructor of other objects thereby letting each object instantiate the relationship. So instead of: WidgetB widgetB; widgetA.Attach(widgetB); I have: WidgetB widgetB(widgetA); Where widgetB attaches itself to widgetA in its constructor. Again, I'd use an interfaces to decouple the two classes so that they do not directly know about each other. This approach seems especially helpful when more than one connection needs to be made for a single object. Say that I have a Service class that has several events of some sort. Then say that I have a Client class that needs to subscribe to several of these events. I pass the Service into the Client's constructor and allow the Client to make the connections. The coupling is a little greater than if I were to have a third party connect the Client to the Service because the Client knows about the Service, or at least the interfaces the Service implements, but I think that's manageable. One advangate is that's no danger of the third party forgetting to connect the Client to a specific event in the Service. |
|
#4
| |||
| |||
| Leslie Sanford wrote: > I've been studying an article in Dr Dobbs on event based programming: > > http://www.ddj.com/architect/208801141 > > The article describes an event based architecture in which objects > communicate primarily through events. The article goes into some detail as > to what events actually are; it describes the difference between typed and > untyped event notification, for example. However, my primary interest in the > article has to do with what it calls binders. A binder is an object that > connects other objects together so that they can communicate with each other > through events. Typically, a binder would contain code like: > > widgetA.Attach(widgetB); > > From there, widgetA communicates to widgetB through some kind of event > mechanism. This could be through virtual method calls or something fancier > like what's provided with C# and its events. > > I like this approach to programming and have been using events for awhile. > It provides a way to decouple classes. However, recently I'm having a hard > time scaling this approach up. My latest project involves a large number of > objects, and my binder classes are getting large as a result. Basically, I > wind up writing a ton of configuration code just hooking everything > together. > > How can I continue to use this approach without being overwhelmed writing > configuration code? > > Refactoring comes to mind, i.e. refactor the binding code into several > different places, but that's about it. I am a fan of databases. When you get enough bulk of instances of similar-looking things, its time to consider using a database or database-like tool to keep track of gobs of attributes and state. This was not an option in the 80's when GUI's came of age, but its more practical now, especially with open-source options of light-weight embeddable databases and libraries. -T- |
|
#5
| |||
| |||
| "Leslie Sanford" <jabberdabber@bitemehotmail.com> wrote in message news:g7vag3$vn8$1@registered.motzarella.org... > I like this approach to programming and have been using events for awhile. > It provides a way to decouple classes. However, recently I'm having a hard > time scaling this approach up. My latest project involves a large number > of objects, and my binder classes are getting large as a result. > Basically, I wind up writing a ton of configuration code just hooking > everything together. > How can I continue to use this approach without being overwhelmed writing > configuration code? > Refactoring comes to mind, i.e. refactor the binding code into several > different places, but that's about it. The mantra is : 1. convert to parametric form 2. automate 3. standardise So for #1, the issue is whether you can describe the connectivity patterns in an appropriate form (component "X" connects to the "service 1" interface of component "Y" etc) . If so, you can create infrastructure that when given the parameters ( "X" , "Y" , "service 1" etc) will map/retrieve the components and create the binders. For #2, take the parametric info defined for #1 and put it somewhere (file etc) . You can then automate (read the file, code generation etc) and use/incorporate with the infrastructure defined for #1. For #3, obviously do not re-invent the wheel. What you need to do is such a common thing, try to find someone who has done similar work before (OMG, Service Availability Forum etc) and take whatever #1/#2 that they have If you proceed as above, I've no doubt you will see templates that describe the connectivity patterns for the various types of component that you have in your system. Regards, Steven Perryman |
|
#6
| |||
| |||
| "Leslie Sanford" <jabberdabber@bitemehotmail.com> writes: [ . . . ] > However, my primary interest in the article has to do with what it > calls binders. A binder is an object that connects other objects > together so that they can communicate with each other through > events. Typically, a binder would contain code like: > > widgetA.Attach(widgetB); > > From there, widgetA communicates to widgetB through some kind of > event mechanism. This could be through virtual method calls or > something fancier like what's provided with C# and its events. > > I like this approach to programming and have been using events for > awhile. It provides a way to decouple classes. However, recently > I'm having a hard time scaling this approach up. My latest project > involves a large number of objects, and my binder classes are > getting large as a result. Basically, I wind up writing a ton of > configuration code just hooking everything together. You might want to look at some of the distributed event-driven architectures, like those based on message-oriented middleware (MOM). TIBCO Rendezvous, for example, allows you to completely decouple publishers and subscribers. You might find some ideas that could be applicable to your standalone application. If you're using Java, you could embed a JavaSpace for the communication mechanism. Regards, Patrick ------------------------------------------------------------------------ S P Engineering, Inc. | Large scale, mission-critical, distributed OO | systems design and implementation. pjm@spe.com | (C++, Java, Common Lisp, Jini, middleware, SOA) |
|
#7
| |||
| |||
| Responding to Sanford... > http://www.ddj.com/architect/208801141 My gut reaction to these sorts of infrastructures is: Why make things so complicated? IOW, the R-T/E people solved this problem in a pretty efficient manner several decades ago without a lot of custom infrastructure. At its heart event-based processing is just an asynchronous communication model. Everybody communicates with pure messages (events) and there can be an arbitrary delay between when the message is generated and when it is consumed. So responses need to be separated from triggers, which means one needs a handshaking protocol for collaborations. Handshaking protocols are best described with state machines. So for event-based processing all one needs is: (1) object state machines to describe behavior. (2) event messages. (3) an event queue When an event is generated, the message is pushed onto the event queue. The message consists of at a minimum {event ID, receiver address, [data packet]}. Eventually the event queue pops the event by forwarding it to the receiving object. The receiving object uses a jump table lookup of the method to execute in response indexed by [current state, event ID]. (The jump table is a static State Transition Table.) The method then updates the state machine's current state and does its thing. Any messages it needs to send are pushed onto the event queue. The object state machine simply enforces protocol rules about the sequencing of its behavior methods through transitions (e.g., if the current state is inconsistent with the event ID, an exception is raised). The state actions are just the object's normal behavior methods (Moore FSM model; mealy and Harel are trickier). The only other infrastructure is a currentState attribute for the object, a class STT jump table, and a static dispatch method called by the event queue. The event queue is just a queue. The primary rule is that only one event at a time is popped. (For concurrent processing one can use multiple instances of the event queue to which different objects are registered as a sort of poor man's threading.) The event queue usually has a few other rules to enforce, such as events between the same sender/receiver objects should be popped in the same order they were pushed (relevant to prioritizing in real-time) or that self-directed events should be processed for the responder prior to external events. The queue is clearly a reusable infrastructure. So the infrastructure is both simple and generic. So the closest thing to a binder object is the reusable event queue. [In fact, if one models event-based processing in an OOA/D model and then implements at OOP time is a synchronous environment, the code after optimization would probably be the same as if one had done a non-event-based solution in the OOA/D model. The event queue, STT jump table, and currentState attribute go away and event generation would be replaced by direct method calls.] The tricky part is methodological and lies in the handshaking. B-) -- There is nothing wrong with me that could not be cured by a capful of Drano. H. S. Lahman hsl@pathfindermda.com Pathfinder Solutions http://www.pathfindermda.com blog: http://pathfinderpeople.blogs.com/hslahman "Model-Based Translation: The Next Step in Agile Development". Email info@pathfindermda.com for your copy. Pathfinder is hiring: http://www.pathfindermda.com/about_us/careers_pos3.php. (888)OOA-PATH |
|
#8
| |||
| |||
| On Wed, 13 Aug 2008 13:50:59 -0500, "Leslie Sanford" <jabberdabber@bitemehotmail.com> wrote: >I've been studying an article in Dr Dobbs on event based programming: Have a look at SDL, commonly used in the telecomms industry. http://en.wikipedia.org/wiki/Specifi...ption_Language -- Regards, Paul Herber, Sandrila Ltd. http://www.sdl.sandrila.co.uk/ SDL/MSC//URN/UML2 for Visio |
|
#9
| |||
| |||
| "Leslie Sanford" <jabberdabber@bitemehotmail.com> writes: >article has to do with what it calls binders. A binder is an object that >connects other objects together so that they can communicate with each other >through events. Typically, a binder would contain code like: Remindes my of what I (not aware of »event based programming«) posted here on march 3, 2008: (The rest of this post is a re-post of this previous post.) A component here is an object controlling an area of a graphical user interface, like a command button or a window. (A degenerate component might also be an »invisible« component, i.e., a simple object.) MVC or model-view-separation deals with the internal structure of a single GUI component. An application usually has multiple components, often nested in the form of a tree. Therefore, I would like to plan the relationship between several components. I write down some ideas here. Possibly someone already has heard about similar schemas and can tell me if there already is a name for the following plan. A window (which is a component), for example, might have an upper part with a list (which is a component) and a lower part with a log console (which is a component). window component /\ / \ / \ / \ / \ table console component component .---------------------------------. | window component | | .-----------------------------. | | | table component | | | | | | | | | | | | | | | '-----------------------------' | | .-----------------------------. | | | console component | | | | | | | | | | | | | | | '-----------------------------' | '---------------------------------' How does the table component request some text to be logged? I do not want the table component to be aware of the console component. This would make it more difficult to reuse the table component in other contexts without a console component or to add or remove the table component or the console component independently of other components. (If you do not accept this reason, I also might refer to Demeter's law.) So, instead of directly accessing the console component, the table component "escalates" a log-report to the window component, which is its container. The window component then knows that it has a "log-report-handler" (i.e., the console component), and then delegates the log-request to the console component. Thus, the application component structure I made up recently is to build an application as a tree of components which obey Demeter's law and therefore only communicate via the /edges/ of this component tree, i.e., each component communicates only with its direct container or one of its direct containees. A common special case are several components sharing a single model. Then, I want a common container component of these two components to be (or hold) the model. For example, window (and model for "view 0" and "view 1") /\ / \ / \ / \ / \ view 0 view 1 .---------------------------------. | window | | .-----------------------------. | | | view 0 | | | | | | | | | | | | | | | '-----------------------------' | | .-----------------------------. | | | view 1 | | | | | | | | | | | | | | | '-----------------------------' | '---------------------------------' Here, the window doubles as the model for its subcomponents, when they both need to refer to common data. (The observer relation might hold between any two components of an application, but has to be initiated via the edges of the tree.) The layout of an application might be changed at runtime by adding components to a container component. When this happens, some requirements will be checked: A certain container might only accept components implementing certain operations and the components might require its container to implement certain models for it. The tree structure means that each component (except the root component) has a single container component that represents the rest of the application to the contained component. Whenever a component needs something it can not do itself, it will request this from its direct container. When a container receives a request from one of its directly contained subcomponents, it might handle it or it might delegate it to another of its subcomponents. When a container can not handle a request in one of these ways (for example, a request of an unknown type), it will escalated it to its own container. When the root component receives a request it can not handle, it might report this as an error or silently drop the request, depending on what is most useful or appropriate in this application. For example, a component deep down in the tree might need to know the »current directory« of the application, so it will ask its container: this.container.getEnv( "cd" ); If the container does not have an environment variable »cd«, it will escalate the request to its own container: Object getEnv( name ) { if( this.env.contains( name ))return this.env.get( name ); else return this.container.getEnv( name ); } Or, if a component does not have an own environment storage itself, it will immediatly escalate: Object getEnv( name ) { return this.container.getEnv( name ); } |
|
#10
| |||
| |||
| Leslie Sanford wrote: > > I like this approach to programming and have been using events for awhile. > It provides a way to decouple classes. However, recently I'm having a hard > time scaling this approach up. My latest project involves a large number of > objects, and my binder classes are getting large as a result. Basically, I > wind up writing a ton of configuration code just hooking everything > together. > > How can I continue to use this approach without being overwhelmed writing > configuration code? > Not that I am saying that it is the best or cheapest solution, but you can always generate the configuration code using a modeling tool. Model the structure and communication paths of your system graphically, and generate the "configuration code" that "hooks everything up" from it. The first that came to my mind was that you actually where describing UML-RT (based on ROOM, Real Time Object Oriented Modeling), a Real Time profile of UML 1.4 used in the tool Rational Rose RealTime (also known as Rational Rose Technical Developer). There you have Capsules with Ports specified by Protocols. Then you have Connectors binding Ports on different Capsules hooking all the communication paths up in your system. The Protocols specifies Messages (or events) which can be passed between the Capsules. You can always take a look at the following paper by Bran Selic and Jim Rumbaugh which describes UML-RT: http://www.ibm.com/developerworks/ra...brary/139.html Or this one by Garth Gullekson: http://www.ibm.com/developerworks/ra...brary/269.html Many of the concepts from ROOM and UML-RT have now made its way into UML 2.x. For example the composite structure diagram, which is all about modeling the communication paths and "hooking everything together". /Peter Cigéhn |
![]() |
| Thread Tools | |
| Display Modes | |
In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.