4

I have many classes in my application responsible for behaviour- views, controllers, models, network- often the state of one class or system depends on another and I'm finding that classes that are primarily responsible for the behaviour for one system inevitably become dependees or dependers of other systems or classes. I've tried passing in interfaces of dependencies from the constructor of the system all the way to the class the depends on it and registering for events on it but this gets extremely complex and crazy and definitely violates OCP and SRP at least.

I'm considering making an event system that all event dispatching and listening classes would be coupled to, providing a layer of indirection for classes that require interaction with classes from other systems however in the worst case behavioural classes could be responsible for the behaviour of a class, handling events, and dispatching events- so that definitely also violates the SRP even though I'm pretty sure it would follow the OCP.

Is there a better solution out there? Am I applying these principles correctly? I'm very hesitant to use an event system as it will require most classes to be extremely tightly coupled with it.

3
  • I'm not sure this fits well to a single-question/definite-answer type format, but I'm very interested to see the discussion as well.
    – hometoast
    Jul 18, 2012 at 13:55
  • If by "behavior classes" you mean "verb" named classes then you are certainly doing OO wrong. Your alternative suggestion is also wrong. It sounds like you need a higher level class that can perform the connections between classes for you while keeping the listening/reporting classes unaware of eachother. Events work great for doing things like that. C# makes this very easy, the listening/reporting classes need never know about the other. The event just sends the necessary data, not instances of classes themselves.
    – Dunk
    Jul 18, 2012 at 14:56
  • By behavior classes I mean state machines that intercept calls or events on a class and act based on the current state- so for example if I have a class responsible for network messages any events or calls sent to it while it is in any state but "connected" get bounced off or queued. As a result the states themselves become very tightly coupled to the interface of the class they are controlling. Is this a bad approach?
    – fordeka
    Jul 23, 2012 at 12:15

2 Answers 2

0

This is a tough question to answer. A specific example of the problem you are experiencing would help to give better guidance. It sounds like you aren't splitting the responsibilities of your classes correctly so that a given class doesn't have too many dependencies. As a general rule, I try to avoid a single class having more than 3-4 dependencies. If you have classes that need a half dozen dependencies or more, I would try to split that class up.

I do agree with you that you should avoid eventing patterns unless you have a really good reason to use them. Using eventing to get around coupling and SRP issues doesn't seem like a good approach to me.

6
  • For example, I have a view system, controller system (as in MVC) and networking system, which all use state machines and have associated states for behavior (in the controller system a controller is just a specialized state) and some of the controller states themselves have state machines, because the behavior is pretty complex at times. Now if I want my controller state to be an observer of the view state I can just pass in that system, but what if I want my controller system to change state based on the state of the networking system (don't act on input when in a not-connected state)?
    – fordeka
    Jul 19, 2012 at 12:41
  • Continued- In that case I have to make sure the controller system now gets references to two systems, passes those references to its controller state machine, and then into its own state machine if it has one. If I want to add more systems to this I have to change all this stuff every time, and have to be careful to manage registering and unregistering of observers properly. Then what if I want the controller to get information from the networking system for display on the view? I would have to add callbacks. It gets extremely complicated at this point.
    – fordeka
    Jul 19, 2012 at 12:46
  • Even continued more- If I use an event system all I have to worry about is passing in a reference to it and registering/sending events. In that way classes with complex behavior are only responsible for sending/receiving events.
    – fordeka
    Jul 19, 2012 at 12:50
  • It seems like you have your behavior organized in the wrong manner. Why would the controller depend on the state of the view? This is generally a code smell if you are trying to do MVC correctly. It sounds like you are not encapsulating behavior enough, and that every class needs to know "the business" of every other class. Jul 19, 2012 at 19:11
  • As an example, consider a kiln which has a heater and a temperature sensor; heater supports a property MaxPower which says how many watts of heat it can generate, and method SetHeaterOutput which accepts the number of watts the heater should generate. The temperature sensor has a GetTemperature method which returns a temperature in Celcius. I would suggest that an ITemperatureControlledDevice interface should incorporate both functions, and a Kiln class should implement that. The Kiln class probably shouldn't do much beyond delegating the tasks to other objects, but...
    – supercat
    Oct 11, 2014 at 17:19
1

If by 'responsibility' we equate 'reason to change' it depends on the granularity of the abstraction. Taking it to a ridiculous level, one might consider that because every method has its own responsibility there should only ever be one method per class but that's just crazy. I think that you're on the right lines with your Interface approach, but instead of injecting the dependencies into constructors you could see if DI/IoC framework or Service Locator pattern works in your scenario.

2
  • I've never used DI/IoC or the Service Locator pattern- do you think it would provide the layer of indirection I need? (see comments on the other answer)
    – fordeka
    Jul 19, 2012 at 12:51
  • Potentially yes, but now after reading your comments I think perhaps the Mediator pattern is a better fit (google it). Be careful though, as jkohlhepp says, it sounds like your MVC implementation is a bit messed up - perhaps it shouldn't be MVC at all. Jul 19, 2012 at 20:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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