I have read several books and listen to lecture regarding software design. But I don't know how to resolve problems caused by following OO design priciples.
Here is some situation. I start to design simple single class (ClassA). After that, ClassA grows up with similar responsibilities. According to Single Responsibility Priciple, I extract some logic from ClassA to ClassB. ClassA becomes simple enough again. However, a responsibility of ClassA maybe similar with a responsibility of ClassB, so that ClassA and ClassB have references each other as member fields or properties to cooperate. In other words, seperation of classes make another complexity. That is a interaction between seperated classes. Fromafter, each of ClassA and ClassB may also grows up with more complex responsibilites, and some classes(ClassC or ClassD) may be seperated from ClassA or ClassB. Now, interactions between classes become much more complex. Each of classes may have references to other classes as memeber fields or method parameters.
As single class become simpler, number of classes increase, complexity of relationship and interaction between classes also increase.
In some fortunate case, it could be solved by design patterns. In many case, however, seperation of classes make relationship of classes more complex. and make tendency to generate classes having too many references to other classes as members. A class having too many references to other classes as members is hard to test.
I have read several OO design books. Most of them talk that simple class is good. None of them, however, focus on complexity of classes interaction caused by SRP.
Do I miss something? How can I resolve this problem?
The responsibility means one reason to change.
You may need to change the class A due to one reason, and you probably accidentally change the behavior of another responsibility in class A. Sometime you just need one of functionality of class A to use or to test, but you need to create a whole class A.
If you don't separate class A into class A, B, C, and D, the interactions between the responsibilities still exist but hidden in the class A.
To make classes more coherent and the interactions more explicit would let your code more maintainable.