Chapter 1. Introduction


Everyone who uses C++, or any programming language, brings along their biases and experiences to their software development efforts. In this book, we will apply C++ to solve problems in our chosen problem space of digital imaging. What better way to apply C++ constructs and see the immediate effects than by manipulating digital images, perhaps from your own digital camera.

We begin with a simple, inadequate application that generates thumbnail images from digital pictures. Through prototyping, we test a variety of C++ techniques and design ideas on the thumbnail application. We then use what we learn by applying the appropriate C++ techniques to build a robust image framework, as shown in Figure 1.1.

Figure 1.1. Development Road Map

graphics/01fig01.gif

Along the way, we explore such issues as: What's the best way to design this application, using inheritance or templates? Should we do everything at static initialization time or use a Singleton object? Does explicit template instantiation give us any syntactic or functional advantages? Does reference counting using rep objects and handles add to the design? How do we partition functionality between global functions and objects? What kind of framework makes sense for handling exceptions? Does template specialization help us? How can I make my routines run faster? We don't just discuss these issues; we write lots of code to test our assumptions and to examine the trade-offs in choosing a particular application.

Our background is in developing commercial software, that is, software with the following characteristics: built by many, expandable, maintainable , understandable, and stable. The C++ design and implementation techniques that we explore are evaluated in terms of all of these characteristics:

  • Built by many: Software that is built by a team inherently means that no single person has firsthand knowledge of all of the code. It also means that good communication among the team members is critically important to the software's success. Communication has to start at the beginning; everyone on the team must share an understanding of what exactly is being built, for whom, and when it is needed. By understanding the customers and their requirements, you can always go back and ask yourself, "Is this feature I'm adding really necessary?" Understanding both the business and product requirements can help you avoid the dreaded feature creep or increasing scope that often delays products. Communication has to continue throughout the process: conveying interface designs so that integration among components runs smoothly; accurately and completely documenting your code; and conveying new member functions and their purpose to the Software Quality Assurance (SQA) and Documentation groups.

  • Expandable: You must be able to add new features quickly and extend existing features in commercial software. These requests often seem to come when an influential customer finds that they need just one more thing to solve their problem. Even worse is when a limitation is discovered only after the product is released. Whether or not code can be easily expanded to accommodate these requests is often a function of the design. While it may be as easy as adding a new member function, significant new features require that the design be extended. Put simply, you have to think ahead when designing and writing code. Just implementing to a specification, with no thought to future expansion or maintainability, makes future changes much more difficult. A further complication is that most software won't allow features to be deprecated once the product is in use. You can't simply remove a class that was ill conceived, as it is certain that if you do so, you'll find a whole host of customers using it. Backward compatibility is often a key design constraint.

  • Maintainable: No matter how many unit tests are written, automated tests are run, or functional tests are executed, it is inevitable that bugs will be found after the product has been released. For commercial software, the goal of all of the rigorous testing and preparation is to ensure that any post-release bugs have minor consequences to the product. What becomes crucial is that these bugs be easily and quickly corrected for the next release. It is also likely that the person who implemented a particular component won't be the person responsible for fixing the bug, either because enough time has passed that he has been assigned to a different project, or there are designated engineers responsible for support and maintenance. Given these constraints, maintainability must be designed into the software. There has to be an emphasis on solid design practices and clarity in coding styles, so that the software can be efficiently maintained without further complicating it.

  • Understandable: Commercial software often includes visible software interfaces. If you are building an embedded system library, it needs to be understandable to the application engineers within your company. If you are building a software library, the interface you present must be easily understood by your customers so that they can use it to build their own applications. This doesn't just mean that naming conventions must make sense, but more importantly that your design and your use of language elements, like templates, are clear and appropriate.

  • Stable: Commercial software must be stable; that is, it must be able to run for extended periods of time without crashing, leaking memory, or having unexplained anomalies.

Our biases are probably most evident in our approach to building software. We start each product development cycle knowing that we will be successful. We reduce the risk by getting things running as soon as possible. We start with the infrastructure and move on to the actual code. By doing so, we ensure the success of the product in a number of ways:

  • We establish a code base or mainline and make sure it builds nightly from the very first day.

  • We establish a simple unit test framework and make sure it runs every night using the nightly build system.

  • We get very simplistic prototypes up and running quickly, so that we can apply different C++ techniques and methods to achieve the appropriate design and final implementation.

  • We never break the main code base; it is always running so that other engineers and support groups, such as SQA and Documentation, always have a working base.

  • We never meet as a team for more than thirty minutes. If you can't say what you need to in that amount of time, you need to rethink the purpose of the meeting or meet with a smaller, more focused group .

So what do you get when you finish this book, aside from a better understanding of when to apply specific C++ techniques and the trade-offs in doing so? You get the complete source code for both the thumbnail application and the imageframework. The image framework offers efficient storage and manipulation of images, routines for processing images (such as sharpening edges, reducing noise, and subtracting images), and interfaces to third-party image processing and file format libraries. You can use the image framework to create your own robust application, either by using the framework directly, interfacing to some third-party image processing libraries, or by expanding the image processing routines we provide to create your own library.

We also include all of the unit tests and the unit test harness that we designed to run those tests. And, should you want to internationalize your software to use double-byte languages, such as Chinese or Japanese, we've included a simple resource manager to help you.

We provide a list of useful libraries and software tools in Appendix A.



Applied C++
Applied C++: Practical Techniques for Building Better Software
ISBN: 0321108949
EAN: 2147483647
Year: 2003
Pages: 59

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net