Showing posts with label Software development. Show all posts
Showing posts with label Software development. Show all posts

Tuesday, April 08, 2008

Automation for the people: Continuous Integration anti-patterns

How to branch codeImage by Phillie Casablanca via FlickrAutomation for the people: Continuous Integration anti-patterns discusses some interesting no-no's in software development team practice.

Today I ran into one, namely 'infrequent check-ins' but it was hidden under a pile of branching/merging confusion.

I was discussing branching and merging strategies for the development teams with one of the team members. He explained how work was done for some time, apparently to his satisfaction. A project team would branch off a release branch at the point when a release was going in acceptance test. The team would work on that, fixing issues, and would never merge back into the trunk, except for some cherry-picked bugs.

So far, I don't object to this way of working, but I introduced the idea of personal branches, or an alternative, feature branches, where developers would create branches for every feature, work on that and then merge it back into the stream of the release where that feature belonged in. Wholesale merges, in other words.

This was out of the question. Merges were supposed to be controlled, high exception operations performed under high levels of scrutiny.

This encourages infrequent check-ins: it prevents developers from doing frequent check-ins while working on their own corner of the project. A developer shouldn't only check in when they want to add a major feature; Ideally one should check in after every few lines of code which prove ok. However if one pollutes the main source tree with every little commit, then, yes, this is impractical.

The solution however is not to delay or generally discourage merges. One should setup branching policy so that developers can check-in however often they want without bothering the main line.

Conclusion

Sometimes it takes some time to discover a bad practice in disguise. The no-no of 'Infrequent Checkins', and all the other anti-patterns too, can be disguised in many ways of 'practice' which seems perfectly reasonable by itself. Until you fully work through the consequences.

Btw, don't forget to read part 2 of the anti-patterns article.

Tuesday, January 29, 2008

See kids? Modularity *is* good!


Here's a good one: we show that tightly coupled components have a higher probability of survival as a design evolves; in essence, they are “harder-to-kill.” We also find that tightly-coupled components are harder to maintain, in that they are more likely to experience surprise design changes unrelated to newly added or removed functionality. Finally, we show that tightly-coupled components are harder to augment, in that the mix of new components added in each version is significantly more modular than the legacy design. These results have important implications for managers, highlighting the impact of design decisions made today on both the evolution and maintainability of a design in subsequent years.

Basically they say that you don't want to mess around with objects that are hard to kill. I tend to agree.

Ok, now that I've actually read the article, it occurred to me that the central, hard to kill objects in most applications are the data objects. These are the payloads of data you pass around as arguments between your methods.

The key concepts of your business are represented by data objects, ie. customer, account, order, product etc. These objects are used by many of your processes, so data objects have a high visibility (good for survival, not good for adaptibility). Thinking long and hard about the definition of your data is thus a money saving tactic.

Crystal 128 kivio.Image via WikipediaOk, maybe I go a little fast here. The href'd article also shows that in later releases, much of the maintenance effort (read: cost) is sinking into the legacy, hard to kill, hard to maintain, objects. I propose that data objects are a fair share of that. This implies that designing your data objects well can cut on maintenance costs later on in the project.

The actual technology that produces the data objects isn't under discussion here. I don't care if my CustomerObject comes out as a POJO, entity bean, or as a chunk of xml. The actual data and definition of a customer, that's what I need to know.

In this regard, the REST architecture fits nicely. Within this architecture, most of the design effort is concentrated on the data formats, or resource definition. In contrast, the operations on that data are simple, as in equivalent with HTTP commands (GET POST PUT etc). This way the design effort must be spent at defining meaningful resources and formats.

Another thing comes to mind. The XML folks have over time gained some experience in how to handle evolving specs for their formats. This knowledge is perfectly suitable to 'evolve' entity data objects into more modular forms , so that they do not become legacy (see again the pdf for how that's bad).

Maybe it's worthwhile to think about refactoring data, or designing data for modularity and adaptability?

Creative Commons License

Unless otherwise expressly stated, all original material of whatever nature created by razor_nl and included in the 'How We Work' weblog and any related pages, including the weblog's archives, is licensed under a Creative Commons License.