Advantages of Minimizing Dependencies (or Coupling) Between the  Parts

The main objectives of software design and development paradigm are:

1.

Most experts agree the reusable components are essential. The premise is: if we (i.e. application developers) write less code, it costs less and would have fewer bugs.

2.

But many experts argue a system that can be easily adoptable to evolving needs is more important than reusability.

We believe both are very important. Although the first has obvious and many well documented advantages, the second is also extremely important. Our personal experience shows that, most of us (software developers with pure software background with little experience in problem domain) develop software applications for specialized areas, such as bio-tech, semiconductors, finance or banking would face daunting task of what user wants. They give us a spec and we spend some time discussing over it. Then we pretend (most of us believe) we understand what they want, only to learn after implementing that we miss understand many things.

It is practically impossible for developers to get the big picture by just reviewing the requirements and sitting in many requirements meetings (brainstorming sessions). We would form better comprehension and insights on the requirements and overall system, as we implement one subsystem at a time. The time we spend in coding/tinkering allow us to gain insights into that subsystem (its dependencies or relationships with others) and slowly get clearer and clearer view on the big picture. The prolonged process of pondering over design, coding and then debugging implants deeper understanding and knowledge over different aspects of the system and the application domain. (As soon as you get sufficient knowledge, you boss assigns you to new domain and a new recruit end up responsible for the half backed code).

Not only this, even by chance we satisfy all the user requirements, then it’s turn for the users to learn that it is not what they really want. Usually users don’t even know what exactly they want. As a user, I was in that position few times. Also, user needs usually change, for example, new technologies, innovations or change in competitive landscape. Hence, an ideal development paradigm must accommodate this imperfect system (e.g. constantly moving target and the gap of communication or domain knowledge), so that, we can incrementally refine the parts to reach and maintain the perfection. If I were a user, I would prefer to build a working system first and iteratively improve it, one part at a time.

Observations on the practice of Software Engineering
(From: CBSE-2003; Slide#9; M.R.V.Chaudron; University Eindhoven)

About 80% of software engineering deals with changing existing software 

It is not the strongest of the species that survive, nor the most intelligent, but the ones most responsive to change  --  Charles Darwin 

Time to market is an important competitive advantage: incorporate successful innovations quickly

  • Systems should be built to facilitate change

    • easy removal and addition of functionality

An ideal component based systems must comprise of many “loosely coupled” subsystems, which would allow us to refine each subsystem mostly independently. This substantial reduces the cost and complexity to evolve the system. As we know, in most systems, the components collaborate with each other. This forces us to create coupling (or dependency) between them, so that, they can collaborate with each other. For example, in an automobile, the CD-player needs power, which is a real dependency. We resolve that dependency by connecting the CD-player to the 12V DC car battery. Here the 12V DC is a predefined standardized interface, which is an artificial dependency.

For example, in a shopping cart application there are two types of components: A shopping cart (e.g. Invoice/Table -- a mini-spreadsheet) and shopping items (GUI components that present the items for sale). When user drag-n-drops an item on the shopping-cart, the shopping cart need information about the item to add at to the Invoice. This information exchange is real dependency between the two components. To properly exchange and interpret the information, they may use predefine XML-schema to communicate various pieces of data (e.g. price, discounts, inventory and model etc.). This format of the data is minimum required artificial dependency. However, if you look at the code, there will be only one service-function call. The dependency constitutes the function-call and the format of the parameters.

The CBSDF needs only resolve this kind of minimal rational dependencies to remove or replace any component. On the other hand, the traditional programming paradigm, forces the developers to create numerous irrational dependencies. This results in tangled web of harmful dependencies between the Objects as shown in the CF-LC-Figures, even for three components. A large software would have hundreds of such irrational harmful dependencies, which increases the cost of even small changes by about 10 times in the large applications.

We cannot eliminate the rational dependencies (i.e. real and artificial dependencies). But an Ideal “loosely coupled” component based systems could eliminate the “irrational dependencies”. Therefore, an ideal “loosely coupled” component based system must minimize and well-document the high-level rational dependencies of each component, such that, developer only need to know and resolve those simplified dependencies to replace each of the “loosely coupled” components. (e.g. only plug-in CD-player that can operate on 12V DC).

In a complex system, the OOP or Object oriented approach forces us to create large number of complex irrational dependencies between the objects. The OOP has no mechanism to encapsulate the object-level dependencies, so introduces costly irrational dependence. It would make hard to make any changes to any object. It is hard to predict what kind of effect a small change might have on the overall system.

We must create the system or application, such that, the subsystems have minimal dependency (i.e. highly loosely coupled) between sub-systems (e.g. Fig#8). For example, in the automobile or in computers, the interfaces between the parts are well defined, which allow the manufacturer to independently refine the design of each part (e.g. engine, battery, CD-Player or CPU). Furthermore, preferable to have automated mechanisms to detect any bracken interfaces between them. (i.e. automated software tools and processes to maintain and resolve the dependencies).

Usually the reusable components (e.g. Java classes for pie or bar-chart) require to be designed to accommodate wide range of needs. So these classes require lot of code to customize. For example, input data and style information, such as, 2D/3D, fonts and colors etc. On the other hand, the resultant component, after all the data is initialized would require very little code to collaborate with other such components.

Besides, the resultant component (generated by the CF) is custom designed to satisfy specific need of the application. Hence certainly possible to design, so that, it needs simple minimum high-level couplings (may be 1 or 2 service functions and about 5 lines of coupling code). Hence it would have very little dependency on rest of the application. This would allow us to refine or replace this component very easily to satisfy evolving needs. Most importantly, the high-level service-interfaces or dependencies reflect the design intent of the component.

CBSDF accommodates this through “Component Factories” (or “CF”). The well-designed supply chain of the CF (see Fig#4 & #5) would allow us to constantly refine or replace each part (e.g. each node in the supply chain or tree), with less effort. If any interface is broken inadvertently, automated software tools should detect the broken interface-contract for the developer to take necessary action.

Two very useful basic characteristics of “loosely coupled” components for computers are: Each component physically encapsulates all its subcomponents and offers simplest possible interfaces to access its services (in order to minimize dependencies). For example, plug-in parts such as graphics card and hard drive. Without this ability to build the component-hierarchies, the computer-makers also forced to create complex irrational dependencies, similar to the irrational dependencies, we found in the software applications today.

In the software application, it is desirable to have such encapsulation and simpler service oriented interfaces, for example, to replace them with little effort or to constantly refine the component (such changes would have no effect as long as the service interfaces are not changed). However if the interfaces or services are upgraded or changed, it would be much simpler to understand the impact on the other parts.

The flaw in the OOP paradigm is that it is not able to control the unstructured explosion of irrational harmful dependencies between objects. How can you remove any one of the three components in FIG#15? The scattered objects and random distributions of tangled spaghetti code in the source files, make it impossible to preserve the plug-n-play type independence for the components. The software code in itself in each component is not so complex; however, system complexity explodes if you cannot determine what kind of effect a small change in it may have on the other parts of the system. It is impossible to control the complexity of large systems, if we cannot determine the dependencies accurately & quickly for each component.

Miscellaneous Documents Privacy Policy | Site Map | Services
Designed By SINDHU SYNERGY
Copy Right © 2006 Pioneer Soft, LLC. All Rights Reserved.