I would like to debunk preemptively one statement that I often hear go unchallenged in meetings: "We have to pick one way of solving this problem. We cannot afford to divide our efforts with two different approaches." This is often a unsupported assertion that there is only one problem to be solved. If two groups are approaching a problem in substantially different ways, then perhaps they do not see the problem the same way. If they do not see the same problem, then they are not working on the same problem. Compelling one group to drop their approach will not unify efforts. You can only forbid one group of minds from thinking very hard. Instead of arguing about which approach is better, one should uncover the different issues that need to be addressed. Make sure that both groups understand each other, but do not force them to agree and approve. Assume that no one wants to waste time on a bad idea. Consider the possibility of hedging your bets. Competition is supposed to be good for quality. Identify the different priorities of each group and see how they proceed. There's a chance that you'll decide both solutions are needed. Anyway, you'll be ensuring that progress is highly visible, with short iterations, right?
I once heard Kent Beck say "Fatigue is the drug of choice in the software industry." Fatigue is a drug that helps people avoid seeing the consequences of what they do. They find it easier to focus on details because they are bothered by the assumptions or implications of their work.
Sleep is evidently necessary to form long, deep connections between neurons. During the day, we create many shallow temporary connections. During sleep, our brains look for larger patterns and reorganize our experience into more coherent forms. Without these simplifications, our experience becomes a confusion of unrelated details. Why would someone want to avoid organizing their perception of the world? Maybe they are afraid of the conclusions. Maybe they don't want to know that they are wasting their time on the wrong problem or following a doomed strategy.
Too often software becomes monolithic, with all components requiring the pre-existence of other components. One excuse could be that integration is more important than maintainability. Maybe we can have both. Perhaps our interfaces are too large, or our components do not separate functionality cleanly.
The most successful story of software integration must be the Internet, where independent development is unavoidable. How was it done? By the simplest of all possible interfaces. All information passes through two-way socket connections with simple protocols defined in public RFC documents. Thus we have FTP, telnet, email (SMTP), SNMP, HTTP, NFS, chat, and even networked games. None depend on specific languages or operating systems. Any piece can be rewritten without affecting the rest. The simplicity of the interface allows easy testing. The thin channel encourages a good separation of functionality.
"I use only one operating system. Why do I need portable software?"
Do you never plan never to upgrade? Software that runs on only one platform is tied to the operating system. Operating systems evolve and will eventually require you to change your API's anyway. Scientific software preserves knowledge and should last longer than one release of an operating system.
First of all, a "component" is a buzzword. A precise definition is probably impossible. Here are some alternatives.
Overloaded operators just make code harder to read. Complex
arithmetic is one obvious exception that should look just like
ordinary arithmetic. Most operators have poor analogies with
arithmetic. The usual order of operator precedence no longer
makes sense. In combination with conversion operators, a
single overloaded operation can take minutes to decipher.
x+y mean if
y are not of the same
type?) Overloaded brackets and parentheses make objects look
like ordinary arrays and global functions, and a casual reader
may think they are. Overloaded operators also tend to generate
unnecessary copies of their arguments. Instead use methods
with names that explain the operation. Verbosity adds little
effort to typing but saves much trouble for reading.
Templates make great sense for containers, but they are often used when a polymorphism would be preferable.
Templates amount to cut and paste duplication of code, albeit by automatic means. Instantiation exposes the fact that you are using the compiler as a wizard to write code.
Decide what properties the class should have (sortable, iterator, indexed, etc) and put appropriate functionality in an abstract base class (interface). Algorithms can manipulate this functionality through the base type. Use the derived type elsewhere.
If you are using a template so that you can use primitive types and classes interchangeably, then your main motivation is probably performance. As usual, sacrifice good style only when poor performance makes it unavoidable.
Return to parent directory.