The year is almost over, and I’ve been searching through the usual office supply stores for a type of calendar. I saw a vertical year planner, similar to this during my last trip to Germany. I thought that something like this could be found easily at my local store, but neither officedepot.com nor staples.com seem to carry it. It looks like a good tool for planning to me.
Lately, I have been working as a lead developer on a software module for a reasonably sized project. What seemed to be a task that appeared to require no more than three weeks has turned into something that has spanned four months and may include an additional two months for the provision of integration support. There is a notable difference between a software project that can be completed by an individual and one that requires multiple teams that are spread across the world.
Getting a feel for the project was a major factor in increasing the likelihood of delivering my modules on time. I was able to observe the development of other software modules for the current project, before I was assigned to work on my own. The tool set was noticeably unstable. Not only were the tools not functioning as expected, the tools that were available changed as updates to the tools were required and additional tools were introduced. The overall system design was unstable and the module interfaces were not set. Responsibilities were being shifted between modules. The project’s susceptibility to change is something that must be acknowledged from these observations, and development practices must be adopted to accommodate such changes.
Noting the high level of malleability in the developing software system, my software module was designed with insulation from external module changes in mind. Specific function signatures for my module were provided to me when I began my low-level module design. My module depended on the services that were provided by other modules, some of which have not been well-established. The gist of my module’s responsibilities was adequately conveyed, and the introduction of responsibilities into my module was rightfully resisted through a Socratic series of questions. The new responsibilities would have kludged the elegance of the design by introducing a distinct behavior to the module for a very special case. With much success in preventing drastic changes within my module, the development effort was placed on dealing with changes to the overall system design.
Distinct program entities were introduced at the entry points and exit points of my module. The module interface functions dispatched requests to the inner module functions. This allows the interface to the module to be easily changed without necessitating a risky modification to the module’s core. Also, proxies for the services of external modules were introduced for the module core functions to use. Instead of having several parts of my module make direct calls to external modules, my module’s core channels its requests through the proxy function, which forwards it to the appropriate external module. Although it may have been subconscious while I was designing my piece of software, it is clear now that this is an example of reducing module coupling. My attempt to isolate my module from changes in other parts of the system apparently resulted in a design that approximates good designs that are prescribed in academic texts on software engineering.
Compartmentalization was also employed within the module. Functions were introduced, for example, to isolate the code in the module’s core from the representation of data transferred between my module and other modules. In one situation, a change in the format for the data transferred between my module and another module required changes in only a handful of my module functions. Changes in a part of my module do not significantly affect any other parts, and as changes to my module became required, the changes were implemented in a way that minimized the impact to the rest of the module.
It’s very hard to discuss software engineering topics with respect to a given language when there’s some confusion between “function overloading” and “function overriding.”
I have ran into a few snags while trying to update parts of my code that depended on other peoples’ code. Other people updated the interface of their modules, and I needed to update the way my module interacted with theirs. Being slightly optimistic and feeling a bit of schedule pressure, a simple identifier substitution with an occasional update of data type seemed sufficient for the task without actually employing some refactoring techniques.
I was lucky enough to be able to tighten my development cycle. In particular, I was able to jump into testing very early in the implementation of the module. With the use of an automated test tool such as JUnit, the functionality of a module can be continually tested as the module is being developed. The automated test tool is also useful in ensuring that the expected behavior does not change while performing a refactoring such as modifying entity names within a module.
I acted to apply the changes as quickly as it was known to me that an update needed to be done. This resulted in an instance of a big bang that is often dreaded and warned of in software engineering circles. As Franklin says, “Experience keeps a dear school, but fools will learn in no other.” I have read the lessons that Fowler tries to spread in his book, Refactoring: Improving the Design of Existing Code, but I failed to appreciate how applicable his lessons are to my situation. My development cycle was very tight. I was developing a functional unit, testing it, refining it, and then repeating this cycle for other units. I deviated from this cycle, which served me well, by jumping into making multiple global changes at a time. After all changes were made, the suite of unit tests failed, and a sizable part of the day was lost to chasing faults.
I made the decision that it would probably be better to restart the day, since I usually leave my work each day in a stable and acceptable state to continue on the next day. This time, I took a breather and set up some scaffolding, as is suggested in a majority of the refactorings in Fowler’s book. After some scaffolding was set up, I compiled, tested, and continued. Now, I am able to make changes with less risk in a more controlled and well-tested manner. The scaffold allows the code to be functional, while it is being refactored, even if refactoring spans more than a day. Having unit tests available seems to be the primary factor in making this possible, because verifying consistency in a module’s behavior and detecting unintended effects without such tests is likely to be difficult.

The order was submitted on September 10, 2007. It was previously delayed until sometime between October and November. Now, the delivery date is estimated at January 9 to January 11 of the following year! Amazon is amazing. I’m afraid that if we stick around again, they’ll just move the delivery date another quarter.
I simply want the book at the agreed price in the agreed condition that was determined at purchase. So, it looks like I’ll have to accept the delay.