Times change - as do development practices and tools. C++ was once the new kid on the block with all the latest gadgets. Agile methods have changed the focus away from language features and towards ways of working with the language. Can C++ continue to move with the times?
It is always hard to know what is happening in a field as broad as software development. Particularly as we so often are under pressure to deliver a new product, new version or just to fix the one we have delivered. This pressure takes its toll, and I know that I have, on occasion, 'surfaced' after months of intense focus to discover that there are new interesting things that everyone else knows all about.
One way to ensure that these periods of several months do not turn into years is to ensure that I make it to the ACCU conference. If I've missed something, then someone will bring it to my attention there! (There are, naturally, other ways to achieve the same effect - the local meetings of the ACCU, the Extreme Tuesday Club and the SPA conference have all worked for me - and I'm sure that if I found time to attend XPDay that it would do the same. You will all have your own favourites - but I'm sure it isn't a coincidence that I meet the same people at many of these places.)
The point is that we all need to keep fresh and be on the lookout for the great new ideas and tools that will make it possible to deliver the next system we work on.
It has always been apparent that the tools are continually becoming capable of doing more for us. I remember re-reading The Mythical Man Month [ Brooks 1974 ] some time ago and noticing that a task that it describes as requiring a dedicated person has all but disappeared. This was the process of incorporating updates to project documentation - which was done by merging replacement pages into a ring-binder. Managing documents in electronic form is definitely easier - especially when it comes to distributing and tracking changes.
I'm sure that everyone reading Overload will be aware of the popularity of 'agile methods'. What may not be so apparent is that many of the techniques advocated are reliant on today's technology. Honestly! Just think what 'continuous integration' relies on - the availability of a build server, automated access to a shared version control system and reliable and a way of publishing results. Some of us can still remember the days of 'sneaker net' - when the only way to get code from one machine to another was to copy it to a diskette (get one of the old timers to explain) and walk across the office with it.
Shortly after the days of 'sneaker net', a team I worked on employed a contractor whose main task was to perform an integration build of the system each day. It took him all day every day. (Even after I took over and automated most of the steps so they could run overnight it still took around 8 hours. As the system grew this started taking longer - until it got to around 16 hours and steps were taken to speed it up).
Changes in technology make for dramatic changes in what is practical to achieve. We must not let the opportunity go by - because our value lies in the ability to deliver software. And delivering software is hard enough without denying ourselves the best tools available.
It is apparent that the agile software development movement has been effective in pushing effective tools. I've used CruiseControl to perform continuous integration on a number of projects now - it integrates nicely with several version control systems (I've used CVS, ClearCase and Subversion with it), it can build projects in different languages (I've used it for both Java and C++ projects), it runs on any platform that supports Java (I've used it on both Linux and Windows), it publishes notifications by email (I've used it in organisations using both Notes and ExchangeServer), and it presents its functionality via a nice web page. A great piece of software - it does one job and it does it well. There may be other products that do this job, but I'm not aware of one that is equally agnostic the environment it is used in.
Unit test frameworks
Unit testing underlies the agile practices of 'relentless refactoring' and 'test driven development'. Over the last decade or so a range of testing frameworks have become widely known. Although JUnit (for Java) is probably the best known it derives from the earlier SUnit (for SmallTalk).
C# has NUnit.
Python has PyUnit.
And C++ has boost.Test, CppUnit, CppUnitLite, Aeryn, CUTE, FRUCTOSE, CricketTest, CxxTest, and more.
While I know there are alternatives to JUnit in Java and PyUnit their use is unusual: I've not met a Java developer who is not familiar with this JUnit. The situation with C++ is somewhat different - although there are many frameworks, I've met many C++ developers who are not familiar with any of them! And many developers who prefer not to use the ones they are familiar with. This probably says something about both C++ and C++ developers. It definitely says something about test frameworks for C++: it isn't easy to produce one that is accepted by by the community.
Integration test frameworks
While I can assume that most of you know what unit tests and continuous integration are I feel I have to explain integration test frameworks. These are tools that allow interactions that involve a significant portion (or all) of the system to be scripted in a way that allows the system to be tested. So for example, if the system being tested is a junk mail generator then it should be possible to supply a template letter, a mailing list and the expected list of letters. Running the test would supply the inputs to the system and validate the resulting addresses, salutations and letter contents.
I've dabbled with FitCpp (and the separate but related FitNesse) but, despite overcoming the technical barriers, cannot yet report a successful use in a real project. Others, working with Java have had mixed success applying Fit to this work.
One area where I've noticed significant progress is in the automation of editing tasks - after Fowler published his refactoring catalogue [ Fowler1999 ], editing tools began competing against each other to provide automated support for these activities. Progress has been good in some modern languages 1 - in Java the Eclipse and IntelliJ IDEs initially ran out ahead of the field, and while I hear that NetBeans has now joined them all the Java developers I know are using Eclipse. C# also has refactoring tools - but progress has been slow in C++ tools.
What is that Edward? Oh yes, 'what is refactoring?' Yes, I should explain. It is a reorganisation of code that doesn't change the functionality, but makes it easier to work with. One example would be to change the signature of a function, and make the matching change to all the current invocations of the function. Another would be to extract a block of code from a function, place it in a new function and place an invocation of the new function where the code came from.
There are a number of reasons for the slow progress in C++: is is much more complex to parse, it has more dependencies of context, and the activities of the preprocessor causes significant difficulties for tools (as well as humans). Over the last couple of years I've been disappointed by the tools I've tried - but they are getting there at last. As always, as soon as someone proves that it can be done it will become commonplace. I hope that this will be the year that C++ gets its refactoring editors.
Functionality vs usefulness
The tools I've mentioned above - CruiseControl, JUnit, Fit, Eclipse - all focus on doing one clearly delimited job well. This is sadly very rare in the field of software - too many products make themselves less useful by tying in too many ancillary features. IBM once had (maybe still has) a great Java editor - VisualAgeJava, that was essentially useless because it included its own substitute for a file system and version control. These are useful features, but if you wanted to use text processing tools on your code, or your project required a common version control repository for Java and files that are not Java, then this approach got messy quickly.
I've seen code follow the same path at a lower level - classes (and functions) that try to do too much and fail to be useful. It is almost three years since I described the fate of a 'properties' class that I wrote as part of a client application. I think this was Overload 62 - but I don't have a copy to hand in order to check. Since I know that some of you won't have a copy either I'll repeat the story here.
This C++ class mirrored the Java class java.util.Properties - it allowed keys (of type std::string ) to be used to store and retrieve values (also of type std::string ). I suspect that classes with this functionality have been developed a number of times in different contexts. I tried to avoid this implementation being too specific to the context it was being used by limiting the functionality to that needed.
I left this class alone and went on with other things - until I was looking for something to do this same job and discovered that it was gone! It didn't take long to find what had happened: it had grown some additional functionality and changed its name. The new name and functionality related to the solution domain in which it was originally developed - it was now calculation_options which has the additional ability serialise and deserialise its contents into an application specific message format. Unfortunately, while the original 'properties' class would have solved my problem this new class had too much baggage to be useful to me (I didn't want to pull in the message format and associated protocols).
It is only a small example, but it illustrates a paradoxical point: the more functionality a piece of software acquires the less useful it becomes.
Is there life in the old dog?
At the conference this year I'm running a workshop [ Griffiths2007 ] that I hope will help us determine how useful C++ is going to be in the future. As a language C++ is rich in functionality. But to exploit this effectively the developer need tools to match those available when working in other languages. My plan is to collate the experiences of those present and to identify the tools that we need for the third millenium.
See you there!
[ Brooks 1974 ] Brooks, The Mythical Man Month and Other Essays on Software Engineering , Addison Wesley, ISBN 0201006502
[ Fowler1999 ] Fowler, Refactoring: Improving the Design of Existing Code , Addison Wesley, ISBN 0201485672
[ Griffiths2007 ] Griffiths, http://www.accu.org/index.php/conferences/accu_conference_2007/accu2007_sessions#Reviewing%20the%20C++%20toolbox
1 . SmallTalk was probably the first language to support a refactoring browser - but is hardly mainstream