Review: "Scaling Lean & Agile Development", by Craig Larman and Bas Vodde PDF Print E-mail
Written by Ed Willis   
Saturday, 10 July 2010 18:22

This was an excellent book - I reviewed it on O'Reilly here.  Here's an excerpt:

I've managed a group that ran software projects using Scrum but also provided Scrum support to the wider R&D organization by developing Scrum templates and procedures, developing and delivering Scrum training and providing coaching and mentoring for groups taking their first steps down the Scrum path. So, to be honest, I pretty much figured I had Scrum licked. Then I read " Scaling Agile & Lean Development" by Craig Larman and Bas Vodde. I'd yet to scratch the surface of lean and so the excellent treatment lean gets in this book was expected to be new to me, but it was pretty embarrassing how much I learned about Scrum and agile development along the way. If anything it left me feeling a bit of an agile fraud. In the introduction to " Modern C++ Design" by Andrei Alexandrescu, Herb Sutter talks about how reading Alexandrescu's work made him realize that his understanding of C++ templates was still at the "container of T" level while Alexandrescu's work opened his mind to the vast possibilities offered by C++'s generics. This book leaves me feeling similarly abut agile methods. The book presents a great treatment of agile and lean development methods, places them in the context of queuing theory and lean thinking and provides a road map for configuring the organization in what will be a novel manner for most of us but a manner which has led Toyota and others to remarkable improvements in efficiency, employee satisfaction and responsiveness to market needs. If you're an agile practitioner and proponent, go get this book - you'll be glad you did. Note that a companion volume, " Practices for Scaling Lean & Agile Development" is due out soon also.

 
Review: "Practices for Scaling Lean & Agile Development", by Craig Larman and Bas Vodde PDF Print E-mail
Written by Ed Willis   
Saturday, 10 July 2010 18:26

Posted a review of this great book over on the Rally Dev Agile blog. Here's an excerpt:Desire Lines

I was blown away by “Scaling Lean & Agile Development”, as you can see from my bullish review on O’Reilly. Some time has passed since then but I still feel that it’s one of the most important development books I’ve read. That book alluded to the companion volume, “Practices for Scaling Lean & Agile Development”, and as you can imagine I awaited its publication eagerly. It came out in February – I’ve worked my way through it now. It’s most definitely a worthy successor.

The post in its entirety can be seen here.

Last Updated on Sunday, 11 July 2010 03:38
 
The CMMI in 2500 words or less PDF Print E-mail
Written by Ed Willis   
Saturday, 10 July 2010 18:24

Posted on O'Reilly.  Here's an excerpt:

This article provides a brief introduction to the Capability Maturity Model Integration (CMMI) that aims to cover most of the ground, if at a fairly shallow depth. The CMMI is a process-based model that sketches out a comprehensive picture of development. It builds on that to define a method for developing organization standard processes and for keeping them relevant. Those processes are leveraged to ultimately deploy statistical process control to improve organizational performance. The model is supported by a standard method for assessing an organization, SCAMPI appraisals. My hope is that after reading this article, the reader will be able to make an informed decision on whether or not digging into the CMMI further is warranted. Note that the notion of the "organization" in the CMMI allows for smaller groups within a company to be the focus of CMMI-based process improvement - so you don't have to wait for your whole company to get on board to get started.

 
Ed Willis Delivering a Scrum Overview Session 2010 PDF Print E-mail
Written by Ed Willis   
Thursday, 05 August 2010 01:54

This is a video of me delivering training earlier this year.  The session was thrown together very much spur of the moment.  The audience for the most part had some previous exposure to Scrum on other projects.  Their needs centered around using Scrum on larger projects and in an ISO9001 context.  I tried to tailor the presentation to cover more of the concerns they actually had voiced in advance of the session and cover some real-world examples relevant to the work they're doing.  Some of the discussion was proprietary in nature - I've edited those parts out and apologize for the resulting abrupt cuts during the video.  The audio quality is less than optimal also - I hope it is mostly comprehensible.

Dim lights Download

Last Updated on Monday, 09 August 2010 12:08
 
An Exercise in Refactoring and Design Patterns: CGImpegManager/DMS PDF Print E-mail
Written by Ed Willis   
Saturday, 10 July 2010 18:16

Introduction:

This is an experiment for me on a number of fronts.  I needed to update my skills in C++ (rather than just my comprehension), I wanted to practice with JUnit-style unit testing and I wanted a forum for experimentation with refactoring.  CGImpegManager provided an excellent opportunity in all three areas.  It was originally written in C (pretty bad C, too, I might add - I wrote and extended this under extreme time pressure due to the expectation that I'd have to stop working on it at any moment) and thus I'd get ample practice by "migrating" many of the implementation details to C++.  CGImpegManager used no framework for unit testing at all, so adoption of the JUnit-style UnixCppUnit would require no rework.  Lastly, the program had grown so unstructured that new features were very hard to add and thus demanded re-design or refactoring.

History:

CGImpegManager started off as a tool for mp3 collectors that stored the majority of their collections off-line (i.e. on home-made CDs) to determine the extent of their on- and off-line collections.  This was primarily intended to allow the user to avoid downloading the same songs repeatedly (which I was prone to doing).  So, it read one or more files that contained listings of these off-line resources as well as examining user-specified directories (recursively) for on-line resources and finally prepared this list for display.  These preparations included user-specified sorting by filename or (physical) location as well as selecting a smaller set of files to display by sub-string match.  The resulting output was formatted as an html page with little html specified by the program itself - the majority of this html was stored in a configuration file.  So, the user was free to modify this html to their liking - in essence, the program needed to know what header html to display, what to display before each item in the list (and what to display between each attribute - filename, location, etc.) and what html to end the list with.  Once the page was prepared, it was sent out to stdout to facilitate use in CGI - thus using a web browser as the UI.  This provided reasonable configurability and utility and at least a couple of people started using it.

Once CGImpegManager had users, it started to suffer changing requirements.  One user wanted to see file sizes added to the attributes in order to determine if a new song was a better (or different) version of a song they already had.  I wanted to expand the selection criteria to include "and-ing" and "or-ing" search terms.  I also thought negating search terms might be useful.  A port to Windows was requested.  As all these features were added, what little structure the source had originally enjoyed was eroded.  That said, each successive version worked and was accepted by the users of the program.  The death knell for the design (and maintainability) of the program came when I realized that I could have the created web page permit the user to select a sub-set of songs and then "POST" them back to the web server where a (different) program could create a mp3 playlist to send back to the user.  This addition would allow the program to act as a "juke-box" over all on-line resources.  Definitely useful but adding this functionality broke some of the original requirements - notably, the html in the returned page was no longer completely user-configurable.  This new functionality depended on certain html sections appearing in the page.  As well, the addition of this new feature broke some of the original features - the new distinction in handling on- and off-line resources created logical problems that effectively prevented the program from handling off-line resources correctly.  The Windows port was also a casualty.

The program stayed in this useful but broken state for quite some time.  Recently, though, I started to think quite a lot about cataloging my movie collection with this program.  Consider how many requirements this would impose - the on- and off-line distinction would have to be handled correctly (because, until the hard drive equivalent of Moore's Law does its job, my movies aren't going to be on-line), the notion of "mp3" would have to be abstracted to allow for files of different intention and very likely the notion of "playing" an on-line resource would have to change, as the fact that a movie is on-line ought not be mean that it is "playable".  So, this small set of new user requirements would demand a disproportionately large amount of work.  Thus, refactoring was in order.

Design Goals:

  • I want to be able to add new file resources to the index beyond just mp3 files.
  • I'd like to be able to abstract where run-time configuration data (other than that given by the config file) comes from to simplify testing.  Right now, I have to either run the program out of a browser or set environment variables to get it to work.
  • I want to resolve the issues concerning on- and off-line resources.
  • I want to handle target-specifics better and get the Windows port back.
  • I want to resolve the problem of dependencies on the config file while still maintaining the freedom of users to alter the appearance of the program.
  • I want to be able to extend the boolean logic in the file selection criteria without having to deal with endless conditionals.
  • I want to separate the processing from the view so I can create other versions than the current HTML one.
  • I want the program to handle error conditions more gracefully - I don't want it to recover, I just want to get useful information out of it when it fails.
  • Most of all, I want to break the program up and make it more manageable.

Plan:

This project respects more constraints than meet the eye.  What to do next can be decided based on any or all of these concerns:

  • things I need or want to know about for work
  • things I'm most curious about
  • a desire to ease the learning curve in refactoring
  • a desire to ease the learning curve in design patterns
  • a desire to ease the learning curve in doxygen usage
  • a desire to ease the learning curve in unit testing
  • the management on this site and what I'd like to put on it next
  • design goals
  • desired features

That said, there is a rough plan in my mind at the moment:

I need to clean up some basic issues in the code itself before I can really begin to do any more serious work.  These include:

  • removing all the C style strings in favor of std::string
  • setting up the makefile for C++ (including changing the target names)
  • removing all the stdio file usage for iostreams
  • changing from my own container classes to STL ones
  • adoption of exceptions as an error handling mechanism rather than error codes
  • take every struct and turn it into a simple data class (Fowler's recommendation)
  • take every free function and put it on a class with no data members (here, too)

Once this is done I'll have to think about what's most sensible to do next.  I'll update this section when I've done so.

Progress:

The table below lists the (logical) revisions of the program and associates a comment with each one to describe what changes were made.

Be advised that I'm holding off doxygen-ing things until the design stabilizes a bit.  Also the first four class diagrams don't show very much change because most of the work went on behind the scenes.

Revision Class Diagram Notes
Version 1
  • The initial version from my backups.
Version 2 Diagram
  • A partial milestone.
  • Got rid of most of the C-style string handling.
  • Made "bogus" classes around data objects (mpeg) and all free functions to provide a basis for refactoring (as recommended by Fowler in "Refactoring").
  • Got rid of the stdio file handling and put in streams.
  • Along the way, the original 518 LOC dropped to 424.
Version 3 Diagram
  • This version should form the basis for real refactoring - at least everything I can think to do next is one form of refactoring or another.
  • The vast majority of C style string handling has been replaced with std::string.
  • The expandingArray class has been scrapped in favor of std::vector.  expandingArray and error were removed from the project.
  • LOC dropped further from 424 to 301 (originally 518!).
Version 4 Diagram
  • Well, it seems I spoke too soon. There was still a bit of char * shenanigans in main.c and quite a lot in cgiUtil.c/h.
  • I added simple setters and getters to mpeg to better facilitate later refactoring.
  • There was a temporary measure in place that used an array to store the query search terms - I replaced this with a vector.
  • This will be the last of the basic clean-up. The next version will be annotated refactorings.
  • LOC down to 242 - this should be the bottom.  I'd expect LOC to be increasing (reflecting the added structure) from here on out.
Version 5 Diagram
  • Added unit testing on Mpeg.
  • Applied move method from BigMoneyMan::isMpeg to a class method Mpeg::isMpeg.
  • Applied rename method from BigMonkeyMan::fixUpName to BigMonkeyMan::copyFileNameWithoutExtension.
  • Applied move method from BigMonkeyMan::copyFileNameWithoutExtension to an instance method Mpeg::copyFileNameWithoutExtension.
  • Created CgiUtilities as a class in its own right.
  • Added unit testing to CgiUtilities.
  • Created class DirectoryUtilities. The Directory searching/globbing functions are target-specific. My plan is to have one DirectoryUtilities.h and target-specific implementations like DirectoryUtilities_Linux.cpp and DirectoryUtilities_Windows.cpp. That way, I can simplify includes in target-independent files and have a unified way of treating target-specific sub-targets in the makefile.
  • Added unit testing to DirectoryUtilities.
  • Removed class DirectoryUtilities - these are now free functions in the DirectoryUtilities namespace.
  • Gave CgiUtilities the same treatment - these weren't really classes - I was just blindly following Fowler's advice. This would have made sense in Java, but free functions are somewhat common in C++ and I felt this approach better reflected the true design (i.e. CgiUtilities isn't really an entity in this system).
Version 6 Diagram
  • Added MpegManagerException.cpp/h to the project. Starting simple with exceptions - these guys just carry along a char * to describe what went wrong.
  • Added exception-based error handling to CgiUtilities::parseExpr (private) and cgiGetNthItem (public). The former throws when there is no '=' in an expression while the latter does so when the QUERY_STRING environment variable is empty.
  • Added exception-based error handling to the Mpeg class - setFileName and the five argument constructor now enforce the constraint that the file name should always be a legal mp3 name (Mpeg::isLegalMpeg). The default constructor does not enforce this constraint, so an Mpeg's file name is always either null or valid.
  • Added exception-based error handling to DirectoryUtilities function getFileSize - it now throws if called on a non-existant file.
  • Added unit tests to verify that (all of) these exceptions are thrown when they are expected to be.
  • Completed separating the directory utilities into Linux and Windows implementation files.
Version 7 Diagram
  • Went into the weeds a bit.  Tried to add a builder to do the configuration file reading and interpreting.  Turned out this kept me from being able to test for hours, so eventually I gave up and went back to an earlier version.  Having kept the program correct for the vast majority of the time I've worked on it, I'm really reluctant to let it go now.  It really is funny how that outlook dominates your decision-making once you've got testing going on through-out your work.  I saved the new files I made elsewhere and may use them later, once I've figured out a safer way to do this refactoriing.
  • Fixed two bugs and added unit tests to catch them : QUERY_STRING being *empty* is not an error - I handle this correctly now and failure to open the configuration file results in an exception.
  • Applied extract method to take the CGI input processing out of main() and put it in method BigMonkeyMan::storeUserOptions().
  • Applied add parameter to bigMonkeyMan::makeDirListFromFile to add the file name to read. Currently, this is determined by that method by reading the configuration file.
  • Applied remove parameter to get rid of the istream parameter on bigMonkeyMan::makeDirListFromFile (so now that method does not read the configuration file).
  • bigMonkeyMan::makeDirListFromFile now throws an exception if it can not read the off-line file listing file.
  • Gave bigMonkeyMan::makeDirListFromDir the same treatment to separate reading the configuration file from acting on its directives. This method now throws when the given directory can not be cd'ed to.
  • Applied extract method to take all the configuration file reading out of main and put it on bigMonkeyMan::storeConfigurationOptions.
  • Applied introduce parameter object to bundle up all the strings used for formatting the html output. I called this new class DisplayEmbellishments. No unit testing for this class yet - it only has getters and setters.
  • Added system testing for regression.
Version 8 Diagram
  • Added the class StringSelector to the project. This class will eventually provide a Command (maybe) that does the file selection.
  • Applied move method from bigMonkeyMan::includedInSort and bigMonkeyMan::includedInSortOr to like-named methods on StringSelector. Made the latter method private. This is really extract class.
  • Applied rename method from StringSelector::includedInSort to isSelected.
  • Applied move field from locals in main() to StringSelector to allow that class to own the selection terms and the boolean operator to use.
  • Set up unit testing for StringSelector (was this ever fruitful - I think I discovered 5 or 6 out-right bugs or nebulous cases just over the course of laying out the tests).
  • Applied remove parameter, add parameter to StringSelector::isSelected to replace the Mpeg& parameter with a string - this reduces the coupling between these units.
  • Applied move field and remove/add parameter to move the selection terms and search type from parameters on StringSelector::isSelected to data members of that class - they are now given in the constructor.
  • Doxygened CgiUtilities and DisplayEmbellishments.
  • Doxygened MpegManagerException and DirectoryUtilities (not the Windows implementation, though).
  • Doxygened Mpeg, StringSelector and main.cpp. That completes the initial doxygen work.
Version 9 Diagram
  • Added OffLineMpegComposite, LocalOnLineMpegComposite and MpegComposite to the project. None do anything yet.
  • Added unit testing for MpegComposite - no test cases yet.
  • Applied move method from bigMonkeyMan::MakeDirListFromFile to OffLineMpegComposite::makeDirListFromFile.
  • Applied move method from bigMonkeyMan::MakeDirListFromDir to LocalOnLineMpegComposite::makeDirListFromDir.
  • Applied move method from bigMonkeyMan::recurseDirectory to a private method LocalOnLineMpegComposite::recurseDirectory.
  • Applied move field from a local variable in bigMonkeyMan::storeConfigurationOptions to a private data member in OffLineMpegComposite (changed constructor and makeDirListFromFile).
  • Applied move field from local variables in bigMonkeyMan::storeConfigurationOptions
    to private data members in LocalOnLineComposite (changed constructor and makeDirListFromDir).
  • Applied rename class from StringSelector to MpegSelectorVisitor.
  • Applied move field (more or less) to get MpegSelectorVisitor::isSelected to take an Mpeg as an argument rather than a string.
  • Made OfflineMpegComposite and LocalOnLineMpegComposite derive from MpegComposite (really, this was extract superclass, but I went at it differently.
  • Added methods addChild and accept to MpegComposite.
  • Over-rided accept in OffLineMpegComposite and LocalOnLineMpegComposite to
    always throw.
  • Removed the vector<Mpeg> argument from bigMonkeyMan::storeConfigurationOptions.
  • Added a MpegComposite argument to bigMonkeyMan::storeConfigurationOptions.
  • Added accept(MpegSelectorVisitor) method to Mpeg.
  • Added visit(Mpeg) method to MpegSelectorVisitor.
  • Added private data member mSelections (vector<Mpeg>) to MpegSelectorVisitor to allow the class to store the selections it finds.
  • Applied rename method from MpegSelectorVisitor::isSelected to visit (also isSelectedOR to visitOR - God help me).
  • Added a private data member, mLeaves (vector<Mpeg>) to OffLineMpegComposite -
    this class could create one Mpeg at a time, but that's too much change for now.
  • Made OffLineMpegComposite::makeDirListFromFile private and removed its vector
    parameter (it uses the private member now).
  • Added accept(MpegSelectorVisitor) method to OffLineMpegComposite.
  • Added a private data member, mLeaves (vector<Mpeg>) to LocalOnLineMpegComposite - as above, this class could create Mpegs one at a time, but letting it create them all at once makes sense for now (in terms of risk).
  • Made LocalOnLineMpegComposite::makeDirListFromDir private and removed its vector parameter (it uses mLeaves now) - did the same for the private method
    recurseDirectory.
  • Added accept method to LocalOnLineMpegComposite.
  • Changed main to use the new setup:
    • main creates a MpegSelectorVisitor
    • main passes it to the created MpegComposite
    • main gets the product
  • I've really gone around the bend here. Introducing this Composite has led me pretty far a field. I haven't been able to run system or unit tests for hours. Now things seem to be working again, but I broke two unit tests along the way. I'm going to have to be a lot more careful in introducing design patterns by refactoring in the future. The remaining unit tests work. The system tests pass. I'm taking this as reason enough to leave this modifications in.
  • Added MpegCompositeInterface from which the other Composite classes now derive.
  • Changed the Composites' method addChild to take an argument shared_ptr<MpegCompositeInterface>. This was necessary because moving to referring to these composites by the ABC demanded doing so by pointer, which changed a few method signatures, forced me to abandon by-value semantics and required dealing with dynamic allocation (hence the shared pointer).
  • LOC back up to 490. I think it's a bit better now, though :)
  • Brought file naming into conformance with the coding standard.
  • Reworked makefile to use makedepend and use pattern rules to relieve the burden
    of maintaining it. This was simplified by moving target-specific code into target subdirectories.
  • Much work was done to bring the current code up to the coding standard. This actually took ages. In the process, some defects were discovered as well. Most of this work reduced to applications of rename field and rename method.
  • Applied remove parameter to remove an unused parameter and a parameter on the private method LocalOnLineMpegComposite::recurseDirectory - this latter parameter was actually only ever set to the value of a private data member.
  • Reorganized project lay-out. Modified all the unit tests to bring them in line with file naming conventions in the standard. Renamed project dms and changed the version number to 0.80 (I'll likely call it 1.00 when the distributed indexing is done). Put all test code and scripts in dms/tests. Put all target-specific files in target_specific_files/<target>.
Version 10 Diagram
  • This iteration was primarily concerned with getting the Windows port going again, cleaning up some long-standing but comparatively minor issues and with feature-work rather than refactoring.
  • The long-promised Windows port was done. This turned out to be far more work than it really should have been. Adopting the STLport on the Linux port was seen as a stepping-stone but was complicated and ultimately abandoned because UnixCppUnit was not easily buildable with the STLport. I found and adopted the cppunit unit test framework (just amazing amounts of busy work, that) but found that it, too, was not easily buildable with the STLport. Ultimately, I decided to use gcc's STL implementation for the Linux port and the STLport for Windows. Getting DMS to use the STLport was complicated by the fact that I'd screwed up namespace/using directives in all the code. Anyway, DMS builds on Windows now. I have decided not to port the unit tests - I have no doubt that I will live to regret this, but I am only one guy.
  • Fixed a long-standing issue with error-reporting - it turns out that any output on stderr will hose any normal output in CGI. So, you get an empty page if you emit on stderr. I changed my exceptions to use cout for now until I have a better way of managing the context of program
    execution.
  • Introduced "target.h" in target_specific_files to allow compiler-specific
    defines, pragmas et al. Currently, all I've needed to do with this is
    pragma out the exception specification warnings on MSVC 6. The Linux target.h is empty.
  • Added a feature to permit OffLineMpegComposite to transparently manage the interpreting of the current listing file format and the original one (the distinction is mainly that the latter has file sizes while the latter does not). To facilitate this, I changed the behavior of Mpeg - it now understands the notion of having an undefined file size. Attempts to get the file size when in this state result in an exception. The determination of the version of the listing format is possible without adding to either format.
  • Tidied up some basic configuration management issues by removing hard-coded paths to boost, the cppunit headers and libraries and the STLport (even though it's not used) on the Linux port. The hope is that this will make it possible for others to build DMS without too much hair-pulling.
  • Factored directory_utilities to consolidate common code into directory_utilities.cpp which left the target-specific files much smaller. Along the way, I got rid of my last ifdef.
  • Added a modest suite of automatic, nightly tests. All the unit tests and system tests are run and a summary report is prepared and posted to the project homepage.
  • By far the biggest news is the addition of the remote listing feature. After all the preparatory designing work, this was really pretty easy.
    RemoteMpegComposite was added to the project and followed a similar strategy as did OffLineMpegComposite. The former class hides the contents of a file that lists on- and off-line resources that are hosted remotely. Ultimately, this new class is almost a hybrid of LocalOnLineMpegComposite and OffLineMpegComposite - the listing itself is stored in a file, as it is with OffLineMpegComposite but the files themselves can be "live" as they are with LocalOnLineMpegComposite. DMS itself is used to prepare the listing by passing it a CGI "argument" "html=false". This causes a new method, BigMonkeyMan::displayTextPage to be called rather than BigMonkeyMan::displayHtmlPage. This is just as awful as it sound, actually. I'm ok with it for now because I wanted this feature in there at long last and because I know a good way to deal with this (and this bad solution is a reasonable stepping-stone toward it). Refreshing this listing is left as a sysadmin exercise (in lynx and cron). The security issues of access to remote on-line resources are left to httpd configuration - I've done this myself - apache can be configured to serve out mp3's using user authentication and at least one player (Windows Media Player) can handle the authentication request gracefully (i.e. prompt the user once per session per host). I have an  open task to get in touch with the XMMS team to ask if (or when) similar functionality is (or will be) available.
Version 11 Diagram
  • Back to refactoring for this iteration.
  • Added DisplayManager to the project. Eventually, this will be responsible for display context (i.e. for DMS, CGI or shell - need to avoid stderr and must output "Content Type" string before any other output if CGI) - I'm basically doing "Extract Class" here but am taking it little by little.
  • Added FormatManager to the project. This will be the target of Move Method refactorings later on.
  • Applied Move Method from bigMonkeyMan::displayHtmlPage to FormatManager::displayHtmlPage.
  • Applied Move Method from bigMonkeyMan::displayTextPage to FormatManager::displayTextPage.
  • Made DisplayManager into a Singleton - used shared_ptr to control the lifetime of the instance.
  • Renamed DisplayManager DisplayManagerSingleton.
  • Added unit testing for DisplayManagerSingleton.
  • Added private member m_bUseHtmlFormat to FormatManager to store what format the output will be displayed in.
  • Added public method FormatManager::setParameter to set the above value.
  • Added public method FormatManager::displaySearchResults which delegates to displayHtmlPage or displayTextPage based on m_bUseHtmlFormat.
  • Rewrote client code in main to set the above parameter and then use the format independent method to display the results.
  • Made displayHtmlPage and displayTextPage private in FormatManager.
  • Rewrote bigMonkeyMan::storeUserOptions to store the output format directly in a string to simplify configuration of the FormatManager instance.
  • Decided not to add unit testing for FormatManager because this would overlap the system tests almost completely.
  • Added setParameter method on DisplayEmbellishments.
  • Rewrote code in main to use the new setParameter method on DisplayEmbellishments rather than the set methods.
  • Removed all the set methods on DisplayEmbellishments.
  • Moved the "LAST_VALUE_HERE" header text transformation code (which replaced the empty search entry text with the last search string) from main() to DisplayEmbellishments::setParameter.
  • Reverted to cerr usage (made safe by DisplayManager) in exception handling in main.
  • Added code to dynamically determine the output context (and set it on DisplayManager) in main.
  • Added system tests for the remote indexing functionality.
Last Updated on Wednesday, 21 March 2012 17:15
 
«StartPrev12345NextEnd»

Page 5 of 5