For many years I have used object-oriented programming languages. For only a small fraction of that time have I considered the intersection of the language implementation, the conception of OOP, and the desired program behaviour. For an even smaller fraction have I attempted the implementation of programs according to the proper theory of OOP specifically, rather than producing a jumbled-up mess of bobs and switches that violated every rule in the book at some point or another.
It was these facts which I seriously considered for a long time without any clear answer as to why they obtained. Was it merely due to a lack of experience that I never approached the problems in those ways? Surely that played a part - after all, it took geniuses many years to come up with everything, and surely I would not have realized solutions to questions about architecture, design patterns, what sort of classes are appropriate, and so forth. Although educating myself about these things by informal study - through reading books, listening to lectures, studying others' productions, and so forth - solved that problem, it produced a new side effect which became more problematic.
In particular, the implementation of proper OOP and OOD did not, as I believed, readily improve the readability of my programs, nor did it straightforwardly solve all the questions about the design and implementation of them. Indeed, sometimes those things did occur; however oftentimes they did not. Fulfilling those best practices could result in the creation of needless classes, the elimination of classes and procedures which provide a coherent picture of the resulting behaviour, the destruction of simple data structures and their replacement with an ever-multiplying myriad of more and more abstract entities. Furthermore, the problem of implementing the design patterns (to give one example) pushed the difficulty to a deeper level. Should the architecture of the program be so designed to best implement the design patterns? Maybe so. However, there are certain times at which this seems far more like a wooden, almost zombified way of thinking, or at least, putting the cart before the horse.
Or let us consider another matter--the questions of the design of objects themselves, the hierarchy of classes, the delegation of responsibility, etc. Here everything becomes even more difficult. If we are to hold what I already described in the former paragraph, the problem becomes more difficult as with a greater number of classes, a more complex architecture, and the sequestering of information by the class hierarchy introduces new issues about actually understanding the code that comes out the other end. It becomes difficult to locate a behaviour because although it may seem a coherent effect on the part of the user, what would have been a procedure (or a conjunction of two or three) in a normal program can become something spread across a number of classes which eventually create a sort of emergent behaviour. Although the creation of classes, the minimization of state, etc. were initially created to reduce the difficulty in debugging these kinds of problems, the problems reintroduce themselves, albeit in a different manner.
Both of these questions, I think, serve as an example of what I wish to articulate. To be more explicit, the solutions to the problems did not make the problems go away. Rather, the problems themselves were also forced, in their own ways, upon us in new forms.
There are several things more I wish to say. However, I want to keep the post short in the hopes that people will respond. Frankly, I have only begun trying to "really" use OOP so I am sure there are plenty of problems with what I raised.