Chapter 4
|
The history of software development methodologies is really a search for a ”silver bullet”, that is, a search for some way to manage the complexity of software systems. My personal take: developing complex software systems is, well, complex and therefore time consuming and expensive. We will look at five popular methodologies in the rough order that they were developed and used.
I was programming professionally (started in 1973) for a few years before the ideas of structured programming started to gel and catch on. Structured programming deals with the correct use of block structure, procedure call statements, and various loop constructs. We had a new mantra: ”go-to considered harmful”.
The idea that programs should be well structured with transparent, easily understood flow of control seems like an obvious idea today. I would argue that the ideas from structured programming are integrated into all later methodologies.
Object Oriented Programming (OOP) methodology certainly grew out of structured programming ideas. OOP manages software complexity by packaging code and the data that code uses together. We are used to dealing with physical objects in the real world. In OOP, we sometimes model real world objects (e.g., writing simulation programs, where OOP concepts were first developed) as software objects and also model non-material things like processes, ways to organize information, etc. as software objects.
A software object maintains its own internal state. This is very different from structured programs where the code may have been laid out in a structured and easily understood way, but global shared data was available to all parts of a software system including those parts with no real need to access or to modify the data.
Intelligent people notice patterns in their worlds. As children, we might have noticed that classmates who exhibited patterns of good study habits earned better grades. When we learned to cook, we might have noticed that experienced cooks had work patterns like preparing ingredients before starting to cook, frequently tasted food as they added spices, etc.
In software development, the use of design patterns is based on observations that some software projects fail while similar projects are successful (these could be management patterns, scheduling patterns, testing patterns, etc.). In software design, the use of patterns is based on further observations that common design patterns for specific tasks are used repetitively for successful projects.
Extreme programming is based on identifying the needs of customers and concentrating on developing and delivering what customers need quickly. Using simple designs to communicate with customers, Extreme developers iteratively develop software prioritized on what is needed the most.
Extreme programming is the opposite approach to the traditional scenario where developer and customer spend lots of time up front trying (usually with limited success) to document in detail what software is to be developed over a long period of time. Experienced developers understand that staged implementations positively affect the design process. Extreme programming is especially effective when requirements are complex and not well agreed upon.
When we study UML in this book, we will look in some detail at user cases that detail individual aspects of how people will use a software system. Extreme programming uses something similar called ”user stories” that are provided by the customer to describe their perception of how the system will be used. The user stories are then used to define both estimate development time and to help define automated tests that will be used for both development and for acceptance testing.
Extreme programming is often described by a phrase that makes a lot of sense to me: test driven programming. Write the test code before writing the application code! Then write just enough software to pass the unit tests. Do not allow software updates to a source code repository until all unit tests pass. Use tools like JUnit (www.junit.org) to write automated tests.
The main idea behind aspect-oriented programming (AOP) is the separation of concerns of different parts of a software system. This is accomplished by allowing developers to intercept method calls and to have auxiliary code executed before and/or after method calls. Aspects can define new aspect-specific data to an object in addition to behavior. In principle, this philosophy allows for the development of systems that are more modular, with the modularity being driven by different concerns of developers. For Java programmers, I recommend looking at the AspectJ project (eclipse.org/aspectj). To quote the AspectJ web site:
”AspectJ enables the clean modularization of crosscutting concerns such as: error checking and handling, synchronization, context-sensitive behavior, performance optimizations, monitoring and logging, debugging support, multi-object protocols”
Both the free Eclipse Java IDE and the commercial IntelliJ Java IDE support AspectJ. Aspectj is an extension of the Java language and requires preprocessing. I used Aspects with Java when I was working as a paid consultant on the Jaffa open source web application framework. Aspects are more useful when used with dynamic languages like Ruby and Lisp. Ruby and Common Lisp also have the advantage of being able to add methods to a class in any source file. This means that special purpose and application specific additions to libraries can be kept separate from the original code for a library.
A simple example of using Aspects is the following: you might have a class library used for sending and receiving emails. There might later be a business reason to record the number and size of each email, tagged with senders and recipients. Separate Aspects could inject code into these classes to meter email without having to modify the original code. This might make it easier for the authors of the original code to maintain their class library because it would not have email volume metering code sprinkled through their code base.