Why Developers Make Tactical Code Changes

November 3, 2009

There is saying that every speech is actually three speeches – the speech you planned to give, the one you gave, and the one you wish you gave. I think software development is very similar in spirit. Most software professionals want to produce high quality code. Yet,there is a difference between code that they write and what they wish they wrote.

There are a whole host of tactical code changes that creep into an application or product line which will have a negative impact for the long term. By tactical I mean short-sighted changes that corrupts the sanctity of the codebase – maybe it violates encapsulation, breaks the design principles that we meant to be followed, introduces needless coupling, worsens technical debt, and so on.

Why are these tactical changes being made? This question is extremely relevant to systematic reuse – whether you are pursuing reuse via objects, component based development, service orientation, or a combination of these. Here are some of my observations on why this happens:

  • Time pressure – the need for meeting deadlines. Often senior developers are fully aware of the right place to add code yet proceed with tactical changes. If technical debt is consciously taken on, this isn’t too bad. But, are these always conscious decisions?
  • Unwillingness to question key design assumptions (e.g. not considering ill effects of tight coupling between entities or systems) and not addressing support needs.
  • Not considering the need to support multiple concurrent versions. Backward compatibility and client integration needs aren’t considered at development time.
  • Lack of knowledge about existing capabilities in the codebase. It could also be inadequate knowledge about planned assets, or the roadmap for application transformation. This could be due to lack of communication and/or the developer being new to a team.
  • Thinking about changes within the context of short-term deliverables only. This usually manifests itself in seemingly harmless code changes that mushroom into bigger problems later – adding a method in a convenient place rather than the appropriate one or cutting and pasting a variation of existing functionality.
  • Lack of collective code ownership – if it isn’t my code or i didn’t write the first version why take the initiative to make it better?
  • Inadequate knowledge of team’s coding and design standards and practices. Where should a new component be added? who will review the code to ensure that it is reusable? how do i let other developers know? how do i document assets?

Do these reasons resonate with your experience? What could be added to this list?

Like this post? Subscribe to RSS feed or get blog updates via email.

tweet this add to del.icio.us post to facebook

Using Agile Practices for Building Reusable Services

November 2, 2009

I wrote earlier about using agile software reuse and the key ingredients that are beneficial when pursuing such a strategy. In this post, I want to summarize how agile practices can be used to build reusable service capabilities.

Practice How is this practice supported? Why is this practice supported?
User stories Examine user stories within the context of the overall reuse strategy. Differentiate functionality for the overall domain vs. for a single application. Match story with known service and identify development and refactoring tasks. User stories are the primary means for getting requirements for services. User stories can be used to recognize common functionality across services. It bridges business needs with reusable services.
Don’t Repeat Yourself Code reviews done to remove duplication across existing and new services. Review code at multiple levels of granularity – source code snippets, classes, services, and across the domain services inventory. Prefer building only domain services. Ensure services are reusable and do not have channel/technology/transport coupling.Keeps codebase light by removing unwanted code. Helps leverage internal and/or external solutions for functionality that is outside of your core domain.
Refactoring Heavily used for two primary purposes: iterative service development and legacy asset leverage. Refactoring used to identify and fix service limitations (functional and technical). Align user stories to known set of service refactorings. Refactoring also used to wrap legacy functionality and loosen coupling among legacy systems. Refactoring is the foundational technique to achieve agility and helps deliver functional services iteratively. Refactoring is also necessary since domain knowledge and business strategy gets refined over time. Legacy assets can quickly be put to use as part of the service inventory by refactoring them saving time and money.
Done, Done Unit and integration test the service, perform necessary refactorings, add suite of tests to the continuous integration process, and document service in the service catalog. Ensure reuse-friendly techniques are performed and quality isn’t comprised when adding/updating services to the domain inventory.
Release planning Only build services when there is a known consumer. Support backward compatibility using service wrappers and co-existence using versioning. Bundle enhancements across multiple services. Deliver business value early with service orientation. Maximize service reuse across initiatives by releasing early and often. Reduces burden on development team and allows graceful migration path for consumers.
Iteration planning Plan iteration scope using prioritized list of user stories. This list will in turn drive new service development and updates to existing ones. Allocate time for service development, decomposing legacy code, perform reviews, refactoring, integrate with continuous builds, as well as documentation. Capture assumptions and known refactorings to continuously deliver working software and address limitations over multiple releases. Iterations help build reusable services over time greatly minimizing schedule risk.

This isn’t an exhaustive list of agile practices that facilitate reuse – consider these as a starting point.

Like this post? Subscribe to RSS feed or get blog updates via email.

tweet this add to del.icio.us post to facebook

Have a plan for every reusable software asset

May 10, 2009

Have a plan for every reusable asset. At a minimum the plan needs to address:plan

  1. The scope of the asset’s functionality for your immediate deliverable
  2. The asset’s place in within your product line
  3. The impact to your existing design and overall architecture
  4. Tentative road-map for evolving the reusable asset over several iterations or releases

You don’t have to get answers for all these areas rightaway! The point is to think about them so you can make decisions on scope and effort. In the midst of an iteration there will be several questions about whether or not to invest time in refactoring or developing a feature. You can use this tiny list as a guide to help you make decisions on what to refactor or build and whether or not it is in line with your overall strategy.

Like this post? Subscribe to RSS feed or get blog updates via email.

add to del.icio.us: Digg it : post to facebook: Stumble It! : :

Risks with software reuse

May 7, 2009

Why should you care about risks with reuse? Because, these risks are real not made up and can make the difference between success and failure for your development effort. Here are a few risks that spring to mind:

  • Needless complexity
  • Inflexible design/will cost too much to modify
  • Domain irrelevance
  • Inadequate documentation/training/awareness
  • Ability to meet deadlines/dates (schedule risk)
  • Increased development, testing, and maintenance costs
  • Pursuit of technical elegance/architectural purity

These are not all the risks with reuse but the major ones that I have come across.

Now, what do you with these? You do what leaders do and that is address them head on. Instead of sulking about these you should plan and execute mitigation steps for these. Refactoring is the fundamental technique for addressing these risks! Take another look at the above list. You can use refactoring to handle most of these if not all of them.

  • Needless complexity – build only what you absolutely need with just enough abstraction. Refactor needless layers and abstractions. Keep things as simple as possible.
  • Inflexible design/will cost too much to modify – refactor your design to focus flexibility on the variations inherent in your problem domain. Not everything needs to be flexible!
  • Domain irrelevance – Build only what is relevant to your domain. If you are not sure, don’t commit prematurely.
  • Ability to meet deadlines/dates (schedule risk) – cannot take a reusable asset to the planned design target? Plan to pursue refactoring these in your future iterations
  • Increased development, testing, and maintenance costs – don’t build domain irrelevant reusable assets. Every asset you build should be for a real business need. Refactor the rest so as to leverage existing solutions – watch your costs go way down.
  • Pursuit of technical elegance/architectural purity – again, refactor imperfections over time. Think incremental and iterative.

I am not saying this will solve all your problems and address all the risks. But, it will get you on the right path. If you step back and focus on what is essential and what you know is likely to vary you can adjust your efforts accordingly.

Like this post? Subscribe to RSS feed or get blog updates via email.

add to del.icio.us: Digg it : post to facebook: Stumble It! : :

Systematic Software Reuse Podcast Updated…

April 26, 2009

Want to listen using iTunes?

Using iTunes?


Just posted the second episode on software product lines based approach.

Like this post? Subscribe to RSS feed or get blog updates via email.

add to del.icio.us: Digg it : post to facebook: Stumble It! :

%d bloggers like this: