Just because a system is [complex doesn't mean that you have to make it complicated][1]. If you have a class that has too many dependencies (or Collaborators) like this:
public class MyAwesomeClass {
public class MyAwesomeClass(IDependency1 _d1, IDependency2 _d2, ... , IDependency20 _d20) {
// Assign it all
}
}
...then it got way too complicated and you're not really following [SRP][2], are you? I'd bet if you wrote down what `MyAwesomeClass` does on a [CRC card][3] it wouldn't fit on an index card or you have to write in really tiny illegible letters.
What you have here is that your guys only followed the [Interface Segregation Principle][4] instead and may have taken it to an extreme but that is a whole other story. You could argue that the dependencies are domain objects (which happens) however having a class that handles 20 domain objects at the same time is stretching it a bit too far.
TDD will provide you a good indicator of how much a class does. Bluntly put; if a test method has setup code that takes forever to write (even if you refactor the tests) then your `MyAwesomeClass`probably has too much things to do.
So how do you solve this conundrum? **You move the responsibilities to other classes.** There are some steps you can take on a class that has this problem:
0. Identify all the actions (or responsibilities) that your class does with it's dependencies.
1. Group the actions according to closely related dependencies.
2. **Redelegate!** I.e. refactor each of the identified actions to either new or (more importantly) other classes.
### An abstract example on refactoring responsibilities
Let `C` be a class that has several dependencies `D1`, `D2`, `D3`, `D4` that you need to refactor to use less. When we identify what methods that `C` calls on the dependencies we can make a simple list of it:
* `D1` - `performA(D2)`, `performB()`
* `D2` - `performD(D1)`
* `D3` - `performE()`
* `D4` - `performF(D3)`
Looking at the list we can see that `D1` and `D2` are related to each other as the class need them together somehow. We can also see that `D4` needs `D3`. So we have two groupings:
* `Group 1` - `D1` <-> `D2`
* `Group 2` - `D4` -> `D3`
The groupings are an indicator that the class now has two responsibilities.
1. `Group 1` - One for handling the calling two objects that need each other. Maybe you can let your class `C` eliminate the need of handling both dependencies and leave one of them handling those calls instead. In this grouping, it is obvious that `D1` could have a reference to `D2`.
2. `Group 2` - The other responsibility needs one object to call another. Can't `D4` handle `D3` instead of your class? Then we probably can eliminate `D3` from the class `C` by letting `D4` do the calls instead.
Don't take my answer as set in stone as the example is very abstract and makes a lot of assumptions. I'm pretty sure there are more ways to refactor this, but at least the steps might help you get some kind of a process to move responsibilities around instead of splitting classes up.
---
###Edit:
Among the comments [@Emmad Karem][5] says:
> "If your class has 20 parameters in the constructor, it doesn't sound like your team quite knows what SRP is. If you have a class that does only one thing, how does it have 20 dependencies? " - I think that If you have a Customer class, it is not strange to have 20 parameters in the constructor.
It is true that DAO objects tend to have a lot of parameters, which you have to set in your constructor, and the parameters are usually are simple types such as string. However in the example of a `Customer` class, you can still group it's properties inside other classes to make things simpler. Such as having an `Address` class with streets and a `Zipcode` class that contains the zipcode and will handle business logic such as data validation as well:
public class Address {
private String street1;
//...
private Zipcode zipcode;
// easy to extend
public bool isValid() {
return zipcode.isValid();
}
}
public class Zipcode {
private string zipcode;
public bool isValid() {
// return regex match that zipcode contains numbers
}
}
This thing is discussed further in the blog post ["Never, never, never use String in Java (or atleast often)"][6]. As an alternative of using constructors or static methods to make the sub objects easier to create you could use a [fluid builder pattern][7].
[1]: https://softwareengineering.stackexchange.com/a/53527/1683
[2]: http://en.wikipedia.org/wiki/Single_responsibility_principle
[3]: http://en.wikipedia.org/wiki/Class-responsibility-collaboration_card
[4]: http://en.wikipedia.org/wiki/Interface_segregation_principle
[5]: https://softwareengineering.stackexchange.com/users/34148/emmad-kareem
[6]: http://codemonkeyism.com/never-never-never-use-string-in-java-or-at-least-less-often/
[7]: https://softwareengineering.stackexchange.com/a/150168/1683