Agile Zone is brought to you in partnership with:

Kirk is a software developer who has filled most roles on the software developer team. He is the author of Java Design: Objects, UML, and Process (Addison-Wesley, 2002) and he contributed to No Fluff Just Stuff 2006 Anthology (Pragmatic Bookshelf, 2006). His most recent book, Java Application Architecture: Modularity Patterns with Examples Using OSGi was published in 2012. Kirk is a DZone Zone Leader and has posted 77 posts at DZone. You can read more from them at their website. View Full User Profile

Grass Roots Agile

  • submit to reddit
Fundamentally agile

In lieu of adopting in complete form an Agile software development process, such as Scrum, XP, or Crystal, injecting practices can help ease the pain. Such an approach makes an agile transition easier, less risky, and ultimately more beneficial.

These practices take a very narrow view. If you develop a codebase that is infinitely malleable, fully tested, and frequently deployed, your team possesses the ability to adapt. By emphasizing creation, growth, verification, and deployment of your code from initial project inception to final solution delivery, these practices serve as the foundation of an agile environment.

To realize the greatest benefit from these practices, they should be adapted based on the constraints, attitude, and culture of your social and technology environment. After injecting and adapting these practices, allow them to evolve in a way that helps your team continue to increase agility.

Automated and Repeatable Build

The most important artifact produced by the software development team is the source code. It is the only reliable measurement depicting the current state of the application. If the source doesn’t compile, the application is not functional. Building on a regular schedule, such as hourly, helps ensure the team is on track. Incorporating e-mail notification into your build process informs all developers of the status of the build. Additionally, producing a build website allows the team to review important statistical information related to the application such as design quality, code quality, and percentage of code under test.

Continuous Integration is a strategy employed by teams to deliver functional software as frequently as possible. The cornerstone of a robust continuous integration strategy is an automated and repeatable build.

The Build

The build must be repeatable. Performing a local build in an integrated development environment (IDE) is a great way for developers to analyze the isolated impact of their changes, but it is no way to build, package and deploy an application in a team environment. Local builds are a manually intensive process performed by individual developers with no guarantee of consistency. Skipping a step, working with older copies of source or incorrectly performing a build task are common mistakes that can result in a corrupt application. A repeatable build helps solve these problems by ensuring the steps executed to build, package, and deploy the application are performed consistently each time. Fundamentally, a repeatable build consists of at least the following:

  • It must be a clean compile with no syntax errors.
  • It must be performed on the most current version of all source files.
  • All application source files are compiled.
  • The build should generate all units of deployment.
  • The build should execute all relevant tests successfully.

Depending on your platform, tools are readily available that allow you to develop a repeatable build script. Ant is the most popular utility for J2EE development.

The build must be automated. Even with a repeatable build, time must be spent manually invoking the build process. Eliminating waste is a core tenet of successful agile teams, and that which is repeatable can be automated. Build automation frameworks allow you to schedule the build so that it is run at predictable intervals. Frequency of the build is a product of team dynamics. For smaller teams, it’s useful to execute the build each time a change to the source code is released to the source repository. Larger teams may choose to execute the build according to a defined schedule, such as hourly, due to the heavy volume of released code. Project teams should experiment with frequency to address their specific needs.

CruiseControl is an example of a build automation framework for the J2EE platform that sits atop an Ant build script and executes the script based on configuration. Maven is a software management tool that helps manage the build, while also generating feedback aimed to provide the development team with additional project information.

The build must have a supporting infrastructure. In addition to build and automation tools, additional supporting infrastructure must be in place to support an automated and repeatable build.

Extending the Build

The build should be extensible. Once an automated and repeatable build with supporting infrastructure is in place, the team can think about other aspects of the development lifecycle that can be automated. Generating quality, dependency and coverage metrics metrics as part of a build process and subsequently publishing the results to a website or pushing the information to developers via e-mail gives team members the type of rapid feedback they need.

An automated and repeatable build is the cornerstone of any successful agile development team, enabling a plethora of important lifecycle activities. An agile environment is a living and breathing entity where progress is tracked in minutes, not weeks and months. Here are a few of the advantages you’ll realize as the result of an automated and repeatable build.

  • Incremental Growth. Iterative methods advocate incremental growth of the software system. Whereas some less agile methods encourage iteration plans attempting to predict incremental growth, agile teams experience incremental growth daily.
  • Frequent Deployment. Early and frequent deployment to a shared environment avoids integration risk, and offers the team the opportunity to tweak application parameters and execute tests that are best suited for a shared environment. Delaying deployment increases the likelihood of experiencing configuration problems or application packaging issues.
  • Functional Demonstrations. Early in the software lifecycle, most development teams aim to understand user requirements. Typically, meetings are held that emphasize driving out these requirements and documenting them based on discussions. As the software grows, functional demonstrations can be used to help gain additional insight to requirements in a different context. Regularly scheduled prototypes and functional demos involving team members and business clients ensure that all team members remain in touch with the core business objectives surrounding the development effort. For the development team, prototypes and demos offer insight into other processes that developers may not be intimately familiar with. For business clients, it gives them a complete view of the integrated system. It’s important to begin hosting prototypes and demos early in the development lifecycle to help identify inconsistencies across processes, system navigation and workflow issues, and duplication of effort. Wire frames and screen mock-ups can be used as prototypes before a functional codebase is available. As the system grows, functional demos replace the prototypes.
  • Constant Feedback. Extending the build with coverage, design and quality metrics allows the team to gain feedback on the integrity of the software. Potential areas of concern can be identified and corrected immediately upon discovery. Additionally, because the build is scheduled, teams can track progress and setback trends.
  • Lifecycle Automation. An automated and repeatable build automates many of the mundane tasks previously requiring manual intervention. Build, tests, packaging, and deployment are automated and therefore occur regularly and often times without manual intervention.
  • Adaptability. Your build serves as a system of checks and balances for the development team. Tests provide the courage to refactor. Refactoring is validated by frequent builds. And builds are deployed to a shared environment where they can be further tested and verified. The combination of these factors contributes to an environment where change is more easily accommodated.

Minimize Dependencies

Software tends to rot over time. When you establish your initial vision for the software’s design and architecture, you imagine a system that is easy to modify, extend, and maintain. Unfortunately, as time passes, changes trickle in that exercise your design in unexpected ways. Each change begins to resemble nothing more than another hack, until finally the system becomes a tangled web of code that few developers care to venture through. The most common cause of rotting software is tightly coupled code with excessive dependencies. For large teams and large applications, managing dependencies is especially important. Excessive dependencies cause numerous problems.

  • Hinder Maintenance. Dependencies hinder the maintenance effort. When you’re working on a system with heavy dependencies, you typically find that changes in one area of the application trickle to many other areas of the application. In some cases, this cannot be avoided. For instance, when you add a column to a database table that must be displayed on the user interface, you’ll be forced to modify at least the data access and user interface layers. Such a scenario is mostly inevitable. However, applications with a well thought dependency structure make change easier since developers have a more complete understanding of the impact of change.
  • Prevent Extensibility. The goal of flexible software architecture is to remain open for extension but closed to modification. The desire is to add new functionality to the system by extending existing abstractions, and plugging these extensions into the existing system without making rampant modifications. One reason for heavy dependencies is the improper use of abstraction, and those cases where abstractions are not present are areas that are difficult to extend. Abstraction aids large teams by exposing well-defined extension points, as well as encapsulating implementation complexity.
  • Inhibit Reusability. Reuse is often touted as a fundamental advantage of well-designed object oriented software. Unfortunately, few applications realize this benefit. Too often, we emphasize class level reuse. To achieve higher levels of reuse, careful consideration must also be given to the package structure and deployable unit structure. Software with complex package and physical dependencies minimize the likelihood of achieving higher degrees of reuse.
  • Restrict Testability. Tight coupling between classes eliminates the ability to test classes independently. Unit testing is a fundamental principle that should be employed by all developers. Tests provide you the courage to improve your designs, knowing flaws will be caught by unit tests. They also help you design proactively and discourage undesirable dependencies. Heavy dependencies do not allow you to test software modules independently. Teams with few tests cannot respond to change easily due to the inability to access the impact of change.
  • Hamper Integration. It’s easy for separate teams to plow forward, usually under tremendous pressure from looming deadlines. They operate under the false assumption that if they can simply reach the final feature destination, they can quickly pull things together toward the end of a project. This Big Bang approach to integration does not work. As individual modules are pulled together, common issues that surface include degradation of overall system performance, incorrect levels of behavioral granularity provided by system modules, and transactional incompatibilities. More frequent integration brings many of these issues to the forefront earlier in the project.
  • Limit Understanding. When working on a software system, it’s important that you understand the system’s structural architecture and design constructs. A structure with complex dependencies is inherently more difficult to understand. Clear and concise dependencies that are well-thought allow teams to more easily access the impact of change.

Published at DZone with permission of its author, Kirk Knoernschild.


Sergiu Ivasenco replied on Sun, 2009/02/01 - 10:53pm

A very good article about the essence of agile. Worth reading

Sergiu Ivasenco replied on Sun, 2009/02/01 - 10:53pm

A very good article about the essence of agile. Worth reading

David Michaels replied on Fri, 2009/02/20 - 3:28pm

You said: Ideally, the most effective artifact is executable against the source. For instance, a suite of user acceptance tests that have received customer approval. Source code is an executable artifact and must be wrapped by practices and processes that verify the correctness of the source. I have found a source code control tool to be valuable to Agile practices where it can manage both the source code assets and adapt our process on the fly and be as agile as we are. The only tool I have come across that can do this is Accurev. Giving our teams the ability to do individual testing in private workspaces, improve our continuous integration environment, and allow us to change our process with a quick drag and drop when story requirements change in invaluable.

john green green replied on Tue, 2009/09/15 - 11:41am

very helpful. Thanks!!
Get a good buy

john green green replied on Sun, 2009/12/06 - 11:37am

For it is us who produces the only artifact upon which a software system is judged. And it is we who must push, fight, and claw for a better way. It is our responsibility to lead the charge, and initiate the transition from the prescriptive and plan-driven processes of yesterday to the adaptive and emergent practices required of today’s software development effort.
nike china shoes

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.