Wednesday, February 08, 2006

Developer Tip - One Code Stream To Rule Them All

Here's something that I recommend that might fly in the face of conventional wisdom regarding the use of your CVS to manage multiple branches of code in the corporate world - if at all possible, DON'T!

It's not because the tools can't handle them - most modern CVS tools are adequate for managing separate code streams. It's the overhead in managing the streams that will kill you. Every bug found will need to be tracked once for each stream, fixed once for each stream, and tested once for each stream. If you have different code in modules along the branches, the fixes are more complex, since you can't just plug in the same lines of code.

If you have a fluid feature set for a given release, as is unfortunately common, you'll find that features jump between releases depending on:
  • Progress - if the work can't be done in time, the feature moves to the next release.
  • Contractual obligations - someone signed papers promising it earlier than previously scheduled.
  • Hail Mary business deals - the future of the company depends on closing this deal, and this feature is the only way to do that.
  • Customer release cycles - a common problem. The customer wants the feature by time N, and the schedules are drawn up, and suddenly the customer decides they need 6 weeks of certification testing to accept the new code you give them, meaning that you have to pull the important features back into the current release to get it to the customer before the certification deadline.
  • Customer A doesn't want Feature X, but Customer B does. Several releases later, Customer A wants Feature X, after a lot of divergence in the code streams.
So how to solve this?

For every feature in the product, have an activation flag. You may need more than one flavor of this, to account for the differences between optional features that everyone gets to choose to activate or not, and bespoke features that only some customers will be allowed to activate, or even know about. In any case, build a library that will have a set of simple functions that will determine if a given feature is in use at runtime. Don't forget multi-valued options, like a staged conversion between file formats - you'll have a value for pre-conversion, mid-conversion [when both old and new formats are valid], and post-conversion.

Once a feature has been defined, write all the code to handle that feature in all of its incarnations, so that there is no need to branch your code stream. You may need to branch for customer-specific configurations to present the options in a desired manner, but that code should be very small, and managing it on a per-customer basis will not be taxing.

Another important facet of this is to concentrate the decision-making for a feature in as few places as possible, and have the rest of the code handle all possibilities without checking for feature activation. An example of this would be a system that talks to some specific type of equipment only if licensed. The communication code should be written to handle messages from all types of equipment, and the next layer up would be the code that decides to send messages to that type only if licensed, and to respond to any message from that type only if licensed. The fact that messages from an unlicensed type of equipment are passed up to the higher layer instead of being rejected at the lower layer is not a problem - the logic of licensing has no business in the communications layer of a system.

This will develop your system as both flexible and simple, and spare you the headaches of trying to port features into radically different code streams. Your CVS tool will present simple trees instead of briar patches of inheritance. If you use a database, the schema will easier to upgrade, since there will be no releases that have different parts of a later schema - they will all be the same, or newer ones will be supersets of older ones (barring removal of tables, in which case they will be subsets, but functionally complete subsets).



Technorati Tags --
, , ,

Tuesday, February 07, 2006

In on the ground floor

Let's talk for a minute about the ideal software developer situation - when you are there before the product exists. Getting in on the ground floor is exhilarating; there is no cruft in the code, there is no backwards compatibility to maintain, there is no build-up of sludge in the process. But it's also a challenge - there is no structure to work from, no library of existing code that you know fit your problem space. So what do you do?

If you've got a team already, then you probably have a work style that the team is comfortable with. Take a few days to meet and analyze this, to see if there are issues that need to be handled, and if there is anything the team really wants to change. Get consensus, but you don't need unanimity - as long as the dissenters are recognized and taken seriously, things can proceed.

From that point, you have a number of things to decide:
  • pick your code management system. Make sure it fits your development process, and your company's release style. If you don't plan to have more than one code stream, things like RCS and SCCS may be perfectly suitable. Otherwise, something like CVS, or Subversion may be more suitable. For large companies, something like Telelogic's Synergy or IBM/Rational's ClearCase might be mandatory. In any case, settle the question and set up the project in the system.
  • System startup and shutdown. Decide how the system will start and stop. If the product is a single program, this may be a no-brainer - a command line or desktop shortcut may be all that is needed. If the product is a full suite of programs that need to be running all the time, you may need to interact with the operating system in some way - inittab for UNIX-style OS's, for example. Don't forget to examine the need to stop the system for upgrades!
  • Configuration. Determine how your applications will get their configuration. The two obvious choices are a database or a configuration file. If the application does not have a DB, then file(s) are your only choice. If you have a DB, then you can choose. The factors influencing you will be the type of data you need for configuration, and the amount of data needed. Be sure to make your programs capable of re-reading configuration on demand, to make runtime changes possible and easy.
  • Logging. Your programs will need to log abnormal conditions, errors, and other information. Decide how you will need to report this data. On UNIX-like systems, syslog is a good choice. if you want to piggyback on the OS facilities. One thing to consider with your logging system is rollover - you do not want to fill up the disk with one large file. Design the logging system to allow the log file to be moved out and replaced, and manage the saved files so you don't fill the disk. Another consideration is whether or not you have multiple copies of a single program running - your file naming scheme should make allowances for this, as well as the rest of your logging scheme - if you have a single logging process that connects to the work processes by name, or some such.
  • Interprocess communication. You've got a lot of options - RPC, CORBA, plain sockets, shared memory. Don't overlook some newer options, given the versatile libraries of modern languages, of email and instant messaging; also don't discount such old-school options like using the database, or files on the disk as communications channels. Build your libraries using the minimum number of options, but keep the interfaces clear (see my previous entries on this )
  • Coding Standards. I'll address this more some other time, but work out a coding standard for your project with the developers, and if possible, make that format automatic - use hooks in the CMS to convert files into that standard upon check-in. This will prevent disagreements from stubborn developers - they can code their own way if they insist, and the code gets dropped into the common area in the standard form.

That's at least a few of the things that I feel important about a starting project.



Technorati Tags --
, , ,