Topologies of action-oriented versus object-oriented applications.
Differences in application topologies.
It is very helpful to think of object-oriented software development as the next logical step in removing the details of the machine away from software developers. However, a learning curve is associated with this removal of details, due mostly to the different topology that the object-oriented paradigm enforces on the software development process. While action-oriented software development is involved with functional decomposition through a very centralized control mechanism, the object-orented paradigm focuses more on the decomposition of data with its corresponding functionality in a very decentralized setting. It is this decentralization of software that gives the object-oriented paradigm its ability to control essential complexity. It is also the cause for much of the learning curve. When the object-orented community talks about the need for designers to undergo a paradigm shift, it is this decentralization to which they refer.
In the following examples we will discuss the worst-case action-oriented topology contrasted with the best-case object-oriented topology. We will then examine what happens when the action-oriented paradigm goes right and when the object-oriented paradigm goes wrong.In any event, many developers believe that the average action-oreinted development leans toward the worst-case scenario while the average object-oriented development tends toward the best-case result (especailly in the presence of important design heuristics). Consider the symbolic functional decomposition displayed in Figure 3.1.
_ _____________ f2()
_______ X _
_ _____________ f3()
Note: This is not the whole diagram (I don't want to type it all)
As the figure shows, an application has been broken down into five (three) functions. As an afterthought, underlying data structures are created as part of the implementation of these functions. The developers of these data structures have realized that some functions can share parts of their underlying data (e.g., f1() and f2() are sharing parto f the data structure). In the action-oriented world, it is easy to find data dependencies simply by examining the implementation of functions. Given the union of the formal parameter types, local variable types, and any accessed global variable types, the developer knows exactly the data on which code is dependent. However, we have a problem if we wish to know the functional dependencies on a piece of data in the system. In the action-oriented paradigm, there is not an explicit relationship between data and functionality. Consider a change to the data structure marked X in the figure.
Based on the diagram, we can state that only the functions f1() and f2() will require modification if the data marked X is modified. However, last weekend another developer creaded f6() without your knowledge (see figure that I don't want to draw). It is also dependent on the data marked X. You make all of your changes to the data X and the fucntions F1() and f2(). You compile, link, and run the resultant executable, and things do not work properly. You spend the next n days trying to find out what went wrong. Anyone who has developed any application of reasonable size has undoubtedly run into this problem. Most action-oriented systems have these undocumented data/behaviou dependencies due to their unidirectional relationship between code and data. Most action-oreinted systems have a spaghetti-like underlying data structure on which all developers hang their code.
How does object-oriented programming control this complexity? Consider an object-oriented solution to the above problem.
- D1's data _ _ D2's data _
---------------- calls ----------------
_ f1() - <------- - f4() _
= f2() - __ _ f5() _
- f3() _ ---> - f6() -
Many developers correctly claim that tbe action-oriented paradigm focuses only on the functionality of the system and typically ignores the data until it is required. They then claim that the object-oriented paradigm focuses exclusively on the data, ignoring the functionality of the system until it is required. This is not possible because the behavior of a system often drives the decomposition of data. It is preferable to think of the object-oriented paradigm as keeping data in the front of a developer's mind while keeping functionality in the back of his or her mind. The result of this process is the decomposition of our system into a collection of decentralized clumps of data with well-defined public interfaces. The only dependencies of functionality on data are that the operations of the well-defined public interfaces are dependent on their associated data (ie implimentation). In the figure the classes D1 and D2 use one another to carry out the functionality. The action-oriented picture is not always so bleak, nor the object-oriented picture so rosy. (next read previous post which contains the next paragraph). I wanted to know how many C programmers deal with the separation of data and behavior by using files to tie them together.