Implicit Dependencies Are also Dependencies

From WikiContent

(Difference between revisions)
Jump to: navigation, search
Current revision (21:31, 7 August 2009) (edit) (undo)
 
(5 intermediate revisions not shown.)
Line 1: Line 1:
-
A fairy tale.
+
''Once upon a time there was a project was developed in two countries. It was a large project, its functionality sufficiently complex to justify multiple servers for different portions of the job. For convenience, the project was split along the computer boundaries. Each development site became responsible for the software running on one computer. Each site had to fulfill its share of requirements and do its share of testing. The communication protocol between the computers was specified according to the desired functionality.''
-
The not-so-fictituous project was developed in two countries. It was a large project, its functionality sufficiently complex to justify multiple processors / computers / servers for different portions of the job. For reasons of convenience, the project was split along the computer boundaries. Each development site became responsible for the software running on one computer. It had to fulfill their share of requirements, and to do their share of testing. As an interface between the computers, the communication protocol was specified according to the desired functionality.
+
-
A few months later, each site declared victory: the software was finished. The integration team took over and plugged the components, errrh, computers together. They started working. A bit. Not much though: as soon as the most common scenarios were covered and the more interesting scenarios were tested, the interaction between the computers became unreliable.
+
-
Confronted with this finding, both teams held up the interface specification and claimed their software would conform to it. Actually, this was found to be true. Both sides declared victory, again. No code was changed, and they developed happily ever after.
+
-
Who cares for dependency management?
+
''A few months later, each site declared victory: The software was finished! The integration team took over and plugged everything together. It seemed to work. A bit. Not much though: As soon as the most common scenarios were covered and the more interesting scenarios were tested, the interaction between the computers became unreliable.''
-
Ten years ago, few people in industry projects did. Since then it became a commodity, a commonplace that is familiar even to product owners. Yes, software components have dependencies, particularly in large projects, particularly when you strive to increase your code reuse.
+
''Confronted with this finding, both teams held up the interface specification and claimed their software conformed to it. This was found to be true. Both sides declared victory, again. No code was changed, and they developed happily ever after.''
-
So now you have your dependencies - but you do not like them.
+
The moral is that you have more dependencies than all your attempts for decoupling will let you assume you have.
-
Dependencies make it hard to change code. Whenever you would like to change some code that others depend upon, you will experience lots of talk and work, and possibly strong forces of inertia when other developers would have to invest their time. This force grows very strong when you happen to dwell in environments with a lengthy development micro cycle, like in C++ projects or in embedded systems.
+
Software components have dependencies, more so in large projects, even more when you strive to increase your code reuse. But that doesn't mean you have to like them: Dependencies make it hard to change code. Whenever you want to change code others depend on, you will encounter discussion and extra work, and resistance from other developers who would have to invest their time. The counterforces can become especially strong in environments with a lengthy development micro cycle, such as C++ projects or in embedded systems.
-
Many technical constructs have been invented to avoid dependencies. Parameters are passed in a string format, keeping the interface technically unchanged even when the string contents' interpretation changes. Component communication has replaced direct interface calls by a more anonymous bus where you do not need to contact your service yourself. It just needs to be out there somehow.
+
Many technical approaches have been adopted to avoid dependencies. Parameters are passed in a string format, keeping the interface technically unchanged, even though the interpretation of the string's contents changes. Code and definitions are left unchanged if some shift in meaning could be expressed in documentation, even though some clients may be confused or refuse to update. At a larger scale, component communication replaces direct interface calls by a more anonymous bus where you do not need to contact your service yourself. It just needs to be out there somehow.
-
So here is the first warning: Obfuscated dependencies are also dependencies.
+
Let's rephrase the moral a bit: Obfuscated dependencies are also dependencies.
-
All technical independence does not relieve you (your project team) from taking care of it all. Changing an interface parameter's meaning is the same as changing the interface. You might have removed the compiler step, but you have not removed the need for deployment. Plus, you've added plenty opportunity for confusion that will haunt your during development, test, integration, and in the field — when you least expect it.
+
Source-level or binary independence does not relieve you or your team from dependency management. Changing an interface parameter's meaning is the same as changing the interface. You may have removed a compilation step, but you have not removed the need for redeployment. Plus, you've added opportunities for confusion that will boomerang during development, test, integration, and in the field — returning when you least expect it.
-
Looking at sound advice from software experts, you hear Fred Brooks talking you into conceptual integrity and Kent Beck advising to DRY (don't repeat yourself). These concepts apparently increase your coupling, as you have to refer to one integer place from all other code.
+
Looking at sound advice from software experts, you hear Fred Brooks talking you into conceptual integrity, Kent Beck urging once and only once, and the Pragmatic Programmers advising you to keep it DRY (Don't Repeat Yourself). While these concepts increase the clarity of your code and work against obfuscation, they also increase your technical dependencies — those that you want to keep low.
 +
The moral really is about: Application dependencies are also dependencies.
 +
Regardless of all technical approaches, consider all parts of your software as dependent that you need to touch synchronously, in order to make the system run correctly. Architectural techniques to separate your concerns, all technical dependency management will not give you the whole picture. The implicit application dependencies are what you need to get right to make your software work.
-
Good development practices increases your dependencies, right?
 
 +
By [[Klaus Marquardt]]
-
(I'll be back in a minute)
+
This work is licensed under a [http://creativecommons.org/licenses/by/3.0/us/ Creative Commons Attribution 3]
-
One of the paradigms of extreme programming [Beck99] is to do things once, and only once. This is nowadays rephrased as "don't repeat yourself" (DRY) [ref]. If you do not repeat yourself, you code or define things only at one place in the code, and all users depend on that one location.
 
-
So maybe you should avoid referring to that code?
 
-
So maybe you should avoid referring to code, and rather find some way around such a dependency?
+
Back to [[97 Things Every Programmer Should Know]] home page
-
 
+
-
So maybe you want to obscure your existing dependency by using different tools and locations for all your information?
+
-
 
+
-
 
+
-
 
+
-
(from other article, needs to be fed into this)
+
-
 
+
-
Do not make your code depend on some file that is intended to change as the project progresses.
+
-
 
+
-
It is very convenient to have a global file that lists all error codes in the system. When starting the new component, you proudly add a handful: look, I am a part of this! Only to find your colleagues moan about the extra build time. How dare you change this file?
+
-
 
+
-
Couldn't you just do what everybody does:
+
-
* reuse some error codes that are already in there.
+
-
* when existing codes don't match the intended meaning, document their specific meaning in your component documentation.
+
-
 
+
-
The <code>error.h</code> file was intended to provide a great place to look for the meaning of codes. At the same time, it is a central component that is intended to change as the project proceeds. So it is your base, but it is quicksand.
+
-
 
+
-
How to get out? Consider this:
+
-
* real generic error messages (in the style of STL exceptions)
+
-
* a distinct <code>error.h</code> file per component
+

Current revision

Once upon a time there was a project was developed in two countries. It was a large project, its functionality sufficiently complex to justify multiple servers for different portions of the job. For convenience, the project was split along the computer boundaries. Each development site became responsible for the software running on one computer. Each site had to fulfill its share of requirements and do its share of testing. The communication protocol between the computers was specified according to the desired functionality.

A few months later, each site declared victory: The software was finished! The integration team took over and plugged everything together. It seemed to work. A bit. Not much though: As soon as the most common scenarios were covered and the more interesting scenarios were tested, the interaction between the computers became unreliable.

Confronted with this finding, both teams held up the interface specification and claimed their software conformed to it. This was found to be true. Both sides declared victory, again. No code was changed, and they developed happily ever after.

The moral is that you have more dependencies than all your attempts for decoupling will let you assume you have.

Software components have dependencies, more so in large projects, even more when you strive to increase your code reuse. But that doesn't mean you have to like them: Dependencies make it hard to change code. Whenever you want to change code others depend on, you will encounter discussion and extra work, and resistance from other developers who would have to invest their time. The counterforces can become especially strong in environments with a lengthy development micro cycle, such as C++ projects or in embedded systems.

Many technical approaches have been adopted to avoid dependencies. Parameters are passed in a string format, keeping the interface technically unchanged, even though the interpretation of the string's contents changes. Code and definitions are left unchanged if some shift in meaning could be expressed in documentation, even though some clients may be confused or refuse to update. At a larger scale, component communication replaces direct interface calls by a more anonymous bus where you do not need to contact your service yourself. It just needs to be out there somehow.

Let's rephrase the moral a bit: Obfuscated dependencies are also dependencies.

Source-level or binary independence does not relieve you or your team from dependency management. Changing an interface parameter's meaning is the same as changing the interface. You may have removed a compilation step, but you have not removed the need for redeployment. Plus, you've added opportunities for confusion that will boomerang during development, test, integration, and in the field — returning when you least expect it.

Looking at sound advice from software experts, you hear Fred Brooks talking you into conceptual integrity, Kent Beck urging once and only once, and the Pragmatic Programmers advising you to keep it DRY (Don't Repeat Yourself). While these concepts increase the clarity of your code and work against obfuscation, they also increase your technical dependencies — those that you want to keep low.

The moral really is about: Application dependencies are also dependencies.

Regardless of all technical approaches, consider all parts of your software as dependent that you need to touch synchronously, in order to make the system run correctly. Architectural techniques to separate your concerns, all technical dependency management will not give you the whole picture. The implicit application dependencies are what you need to get right to make your software work.


By Klaus Marquardt

This work is licensed under a Creative Commons Attribution 3


Back to 97 Things Every Programmer Should Know home page

Personal tools