Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I applied principles of the GRASP and ended up having a class called Environment. This class's responsibilities are to:

  • Keep information about services in the environment,i.e. environment definition (Service is another class)
  • Start/stop services meeting some criteria
  • Apply configuration changes to different service and keep list of updated services
  • Restart services with configuration change
  • Revert configuration changes at the end of session
  • Search/Give Service class based on criteria (name etc.)

According to OOD, this is not a problem: very cohesive responsibility is assigned to this class.
But on the other hand it's a problem since the class is too big, even though all responsibility assigned to it makes sense. If I want to divide this responsibility to between separate classes, then all these classes need to know about "environment definition", which makes coupling worse and those classes will have "feature envy".

What design patterns are applicable for such situation? Or what other principals can be applied to have cohesive, less coupled classes?

Thanks in advance.

share|improve this question

migrated from stackoverflow.com Aug 16 '12 at 13:35

This question came from our site for professional and enthusiast programmers.

    
At least right off, it sounds like you could use a Configuration class to handle configuration for a service, and probably a front-end for that to automate reverting a configurations after a session. –  Jerry Coffin Aug 16 '12 at 1:06
    
Actually my Service class has generic update config function, that uses external library to apply config change (xml file, db table, registry setting etc) It seems Environment is good candidate for keeping the old config values and associated services. I'm not fully sure, if I understood your suggestion and how it can ease the problem of having big class. Thanks –  Azho KG Aug 16 '12 at 1:37

3 Answers 3

up vote 6 down vote accepted

You probably meant to have Environment as a Facade (facade pattern) and not to implement every detail in it.

Break out all functionality into other classes. Imho each of the responsibilities below should be handled by a separate class that the Environment class uses internally.

  1. Keep information about services in the environment,i.e. environment definition (Service is another class)
  2. Start/stop services meeting some criteria
  3. Apply configuration changes to different service and keep list of updated services
  4. Restart services with configuration change
  5. Revert configuration changes at the end of session
  6. Search/Give Service class based on criteria (name etc.)

Those should give you six new classes. It will probably lead to some other classes too so that you for instance can manage configuration from different classes.

share|improve this answer
    
Thanks for your answer. Related thoughts: As I pointed out in the original question, if I create several classes then all of them need to know about environment definition (i.e. list of services and their roles), will have "feature envy" problem and will be strongly coupled. In any way, I somehow have to elegantly divide responsibility between several classes. But above suggested division seems to be a little problematic, "class responsible for stopping/starting services" (each service implements its own start/stop). –  Azho KG Aug 16 '12 at 17:32
    
Each service can start and stop. But they are not aware of when and how (which order etc). That's what the new class is responsible of. Give the class a list of all services (IServiceCollection or similar) and the service configuration. Again, I'm just guessing since I got no idea about your application architecture. –  jgauffin Aug 17 '12 at 5:33
    
Thanks for answer. Based on these suggestions, I ended up with following classes: Configuration(stores a config change), ConfigurationManager, ServiceControl (start,stop etc.) and Environment. But small problem here, Environment is acting as Facade, but at the same time doing some operation (searching/filtering services). –  Azho KG Aug 18 '12 at 0:20

I'm not sure what design-pattern this is (if any), but in this particular case (if I understand this correctly) I would go for several classes, each for its own set of responsibilities plus front-end class which would serve as a proxy to those who responsible for a particular action.

Yes, the functionality is cohesive, but that does not mean you cannot decompose it to several cohesive and less complex classes, does it?

share|improve this answer
    
+1, Yes, thinking along SRP. –  Emmad Kareem Aug 16 '12 at 13:46
    
As I pointed out in the original question, if I create several classes then all of them need to know about environment definition (i.e. list of services and their roles), will have "feature envy" problem and will be strongly coupled. In any way, I somehow have to elegantly divide responsibility between several classes. So I guess the question is "How to divide elegantly?" –  Azho KG Aug 16 '12 at 18:00
    
They don't have to unless you make them to do so. Of course, I don't know all the details of your particular case, but from my experience specialized class don't have to know everything about calling class. If this is not the case, then you probably do something wrong. –  akond Aug 17 '12 at 9:02

For one, keep in mind that classes do not do things to other classes as in "Apply configuration changes to different service".

I would see the above as a ConfigurationChange class with potentially several derived types such as DbChange, PropertyFileChange, etc. Service would be a class with an applyConfigurationChange(ConfigurationChange) method. The environment would mostly be a coordinator, sensing when a ConfigurationChange has occurred, creating the appropriate ConfigurationChange instance and passing it to the effected services.

It also sounds like each Service would "have a" configuration stack which would support a pushConfiguration() and a popConfiguration() methods in order to support numbers 4 and 5 above.

The important thing is to keep your classes singularly focused - if they are performing more than one overall behavior, you should consider breaking each type of behavior out into a specific class - either to encapsulate complexity or for re-use. I like to think of it like this - code embedded in a class that performs some functionality may work great, but you can't use it anywhere else and you can't relocate it easily when something changes. Code in a well designed class that performs as advertised (i.e. each function does what it says it does), is easily moved around and can be trusted. By making behaviors a separate class, you are giving the behavior an API that separates it from the client class, providing your desired decoupling.

Finally, avoid any class that looks like or operate like a Manager class. In almost all instances I have seen, these classes become huge, bloated monsters. Rather than have a class that manages a set of classes, design each class to manage itself. Their typically is no class that knows more about itself than itself, so it should be the one managing itself. This is especially true of classes that are Threaded.

Another technique which can break up huge monolithic classes is to consider the individual activities that the class performs as unique classes - classes that are instantiated to handle a specific activity, gathering in the required instances, performing the work and then dissolving away - sort of like a dispatch pattern.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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