We have 6593 guests and 19 members online

Agile Sponsors

HP


CollabNet


TechWell

Home > Articles > Columns > The Agile Developer > Checks And Balances

Checks And Balances

E-mail
Written by Kirk Knoernschild   
Thursday, 09 November 2006 07:30
Agile software development is no less formal than the predictive and contract-driven ceremonial processes used on many enterprise development efforts today. However, large enterprise development efforts have been weary of adopting agile development practices. Skeptics fear that an agile approach is nothing more than an excuse for developers to avoid documentation, while requiring heroic efforts on the part of a few developers who hack together a compromised solution without clear guidance, control, or governance. Overall, critics imply that while such approaches might work well for smaller teams with less complex problems, similar practices on enterprise development efforts thwart communication and  quickly thrust the team into chaos. While the communication obstacles present on large project teams contribute to software integration issues and a lack of architectural consistency, agile practices help strengthen collaboration and increase information dissemination, serving as an effective system of checks and balances that make agile practices not only helpful for large teams, but a required element of success.


The Communication Gap
Knowledge management among developers is a key ingredient of successful software projects. On smaller teams, it's easier to ensure developers are not geographically separated. This close proximity of developers to each other allows for osmotic communication, where ideas flow into the background and are absorbed by other team members, as though by osmosis.[1] Team members tend to overhear background communications, and join in as necessary based on their vested interest in the discussion or ability to make relevant contributions. Larger teams do not have this luxury. It is not feasible to shove 50 developers into a project room and expect productive collaboration. On larger teams, it's common to break developers up into smaller teams.


Regardless, as teams grow in size, communication issues arise. As the number of developers increases on a project, the paths of communication between those {sidebar id=1} developers increase exponentially (see Figure 1). Even for a team of 15 developers, the unique lines of communication amongst all possible combinatorial groups of developers is over 32000. In The Agile Matrix, I discussed various ways of organizing teams of developers to increase communication and collaboration. Yet large projects present technology issues of scale that are challenging for even the highest quality teams.

kk1106-1

                                                                Figure 1


Software Rot

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:

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.

Dependencies 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.

Dependencies 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.

Dependencies 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.

Dependencies cause integration issues. 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.

Dependencies 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.

Checks and Balances
Managing dependencies between classes, package, and components throughout the development lifecycle is imperative when developing a software product that accommodates change and meets the business objectives. While breaking larger teams into smaller groups of developers helps establish fewer channels of communication, these smaller teams tend to introduce other architectural and integration issues. For larger projects, it's likely these issues will affect your software before your first production deliverable. Agile practices applied throughout the lifecycle help minimize dependencies and encourage more frequent integration. In Activating the Lifecycle, I discussed the importance and value of an automated and repeatable build and supporting infrastructure. Such an environment is the foundation of an agile team, and serves as a system of checks and balances to ensure large teams maintain forward, sustainable, and cohesive progress.

Separate teams should be disciplined in releasing their changes to the source code repository on a frequent basis. Frequent builds help identify integration issues almost instantaneously, and help avoid the risk associated with Big Bang integration. Automated unit tests verify the integrity of code released by each team, while more complete integration and functional tests can verify behavior spanning team boundaries. Ensuring the complete system is free of compilation errors allows for frequent profiling of the application to identify serious issues related to performance, memory, and other environmental constraints. A shared environment that closely resembles the future production environment is also a critical aspect to help identify environmental issues. Additional techniques help add to this system of checks and balances to ensure development teams minimize dependencies and emphasize integration earlier in the software lifecycle:

  • Dependency Metrics and Diagrams. Utilities, such as JDepend and JarAnalyzer for Java, are available that allow teams to obtain real and accurate feedback on the structural relationships between software packages and components. Understanding module and package dependencies allows developers to somewhat objectively evaluate the cost of change. As dependencies become excessive, such utilities help guide developers in prioritizing areas of the system that are higher priority candidates for refactoring.
  • Levelized Build. Cyclic dependencies, recognizable as bi-directional relationships between packages or components, are especially dangerous as neither can be tested or deployed in isolation. One way to enforce acyclic relationships is building components individually, and including in the build and test execution path only those modules required to compile and test the component being built.
  • Parallel Build. As systems grow, build times tend to slow. This is natural as more code must be compiled and more tests are introduced that exercise more code. When build time degradation occurs, it's important to identify ways to increase the efficiency of your build process. One technique is to build components in parallel. If dependencies are managed carefully, components with no dependencies on each other can be built simultaneously.
  • Component Tests. Components built in isolation, can be tested in isolation. For each component represented by a deployable unit, creating a corresponding test component helps ensure the functional integrity of the component. Test components are typically manifest as suites of individual unit tests, and aid any refactoring to help maintain the design integrity of the component.
  • Integration Tests. Test suites that verify component integration certainly help ensure that the interfaces between components remain compatible, but also help identify behavioral issues, as well. Incorporating these test suites into your build process ensures that integration tests are frequently executed, reducing the likelihood that extended periods of time pass between periods of integration.
Conclusion

Agility is an ability to respond to change as quickly and as easily as possible. While team structure and process are important success factors on large software projects, excessive dependencies prevent teams from changing a software system easily. Leveraging and extending proven agile practices improves feedback and strengthens collaboration, helping teams manage excessive dependencies, encourage architectural consistency and resiliency, and prevent issues from arising late in the lifecycle due to delayed integration.



[1] Cockburn, Alistair. Agile Software Development. Addison-Wesley Professional, 2006. ISBN: 0321482751


About the Author
Kirk Knoernschild is Senior Technology Strategist at TeamSoft, where he leads based on his firm belief in the pragmatic use of technology. In addition to his work on large development projects, Kirk shares his experiences through courseware development, teaching, writing, and speaking at seminars and conferences. Kirk has provided training to thousands of software professionals, teaching courses on UML, Java J2EE technology, object-oriented development, component based development, software architecture, and software process.

{mos_sb_discuss:10}

Trackback(0)

Comments (0)Add Comment


Write comment

security code
Write the displayed characters


busy
Last Updated on Saturday, 20 October 2007 04:47
 
Cialis

Agile Marketplace - Announcements and Special Offers

Upcoming Webcasts
Sponsored by Urbancode - On Demand
Mastering Complex Application Deployment
Sponsored by CollabNet - Wednesday, August 24, 2011
Closing the Agile Loop: Continuous Integration, Continuous Information

ScrumWorks Pro – The World’s Best Agile Project Management Tool
Simply put, CollabNet’s ScrumWorks Pro is the best Agile project management solution on the market, bar none. More than 150,000 Agile professionals rely on the power and simplicity of ScrumWorks every day.  But don’t take our word for it – try it yourself for free. CollabNet is now providing the first 10 users of ScrumWorks Pro at no charge!
Download ScrumWorks Pro today!

The Business Case for ALM Transformation
Are legacy systems holding your company back?  Breakthrough these technical constraints with an open and scalable environment that meets your unique business need to transform. There is no reason to be locked into an obsolete platform. The output of a number of recent transitions from legacy systems, this is practical white paper shares lessons learned and illustrates how guidance and enablement can pave the way for change.
Download this Whitepaper