The Codesmith's Library
Written by Carsten Whimster
The Codesmith's Library is a monthly column which focuses on development oriented books and materials. The column is from a beginning PM programmer, but intermediate REXX programmer's eyes. Pick up whichever book strikes your fancy, and join the growing group of people following our PM programming columns. I will review books aimed at beginners for a while, and then move on from there.
Please send me your comments and thoughts so that I can make this column as good as possible. All mail gets read and responded to.
Designing OS/2 Applications is not a normal programming book. In fact, it talks very little about programming, and a lot about designing programs, as might be expected from its title. If that sounds a little cryptic, read on...
This month is a month of corrections. I obviously try to be accurate and fair, but recently I made a couple of minor blunders:
In last month's review I criticized Charles Petzold's new book for using "Windows graphics" in some of the figures. Of course it wasn't Windows graphics, but rather OS/2 1.x graphics which happen to look identical. This is a hangover from the first version of the book. One reader told me that the new version is very similar to the old version, and that there is hardly any new material, just some updates. If you can live with this (which means little, if any, 2.1+ material), then I still recommend this book for its thoroughness.
Even further back, I managed to miss the WPS coverage in Anthony Rudd's Application Development Using OS/2 REXX. When I looked closer, it actually covered almost as much as the REXX Reference Summary Handbook, so I have changed its rating in WPS from "No Coverage" to "Introductory Coverage", which is now the same for both. The handbook covers a little more, but it is less tutorial, so they end up about the same.
Well, with that off my chest...
I have rearranged the Content Index in a more logical order, and created a
new table called SYSTEM AND DESIGN BOOKS to suit books like this one, and
other non-programming books for programmers. At the moment, the first two
tables are near identical in layout, but that will change over time. In any
case, comparing programming books with design books doesn't make any sense,
and the separate tables reinforce that.
Designing OS/2 Applications is a unique type of book. It does not attempt to teach you how to program, but rather how to design programs, or how to think about programming. These are the chapter titles:
In addition to this layout, the chapters are divided into sections as follows:
I will concentrate on the sections, rather than the chapters, since the divisions between the chapters are much fuzzier than in actual programming books.
Section I explains the advantages of OS/2 over other platforms. This is explained both from an end-user's point of view, as well as from the programmer's point of view. We all know the advantages of pre-emptive multi-tasking, multi-threading, a flat 32-bit address space, device independence, the object-oriented interface (WPS), DDE, virtual memory, paging, swapping, drag-and-drop, and a consistent user interface (CUA). These are all elaborated on. In addition, the API is touted as an advantage, both with respect to power, and also with respect to the (theoretical) portability of it. Third, the advantages of OS/2 as a development platform are outlined, and include crash protection (tm), multi-tasking, and debugging support.
Section II is a large section, which outlines the overall application design theory and procedures. The importance of good, solid, up-front design are stressed over and over again. Examples of poor design practices are listed, and their faults explained. Proper design techniques are carefully explained. One funny quote which is a favorite of the author's is "There's never enough time to do it right the first time, but there's always time to do it over". This is so true! It doesn't take long thinking about the various products on the market to come up with concrete examples of this. Even large multi-platform companies with huge resources seem to think that if they release a suite of programs quickly, and then fix it later, it will gain a large, devoted user base. Wrong! Doing it wrong the first time loses a developer a lot of potential respect, which is replaced by suspicion and mistrust. Finally, the 60% design/30% code/10% test rule is introduced, and the logic behind it is explained.
Starting in chapter 5, an overview of the inner workings of OS/2 is given, beginning with the kernel, and proceeding through to the Presentation Manager, The GPI, and the WPS. This section is important in that it gives those of us who don't yet own a copy of The Design of OS/2 an insight into what goes on behind the scenes. Following that, there is a section which explains what features are available to programmers, on a purely conceptual level. Again, this is very helpful, since it is hard to know what is available when you haven't done much OS/2 programming. Then again, even if you had, there are enough additions from version to version that keeping up with all the new features would be difficult. Each feature available is explained in terms of advantages and disadvantages, and intended use.
Application structure is the next stop on the journey, with device independence featured prominently up front, closely followed by modular design and using threads. Multi-process applications are also discussed, along with some reasons that you probably shouldn't use them, unless you can't do it any other way. DLLs, code sharing, resource sharing, and synchronization are all stops along our merry way, and the chapter finishes with a mini lecture on upgradability, portability, and serviceability concerns.
The next section discusses modularization in much greater detail. Reich presents his idea of design (which is tempered by years of writing for OS/2, so listen up), starting with the overall design accomplished by taking a black-box approach to your app. The user interface is the next stop along the design path, and CUA, data presentation, and window controls are all lightly visited. Dialogs are paid a slightly longer visit, application defaults and CASE tools are discussed. The Workplace Shell is treated particularly well, as is fitting. The various levels of integration with the WPS are discussed, and the ways of accomplishing them (in theoretical detail) are presented. I particularly liked this chapter, and learned a lot about things that I only had a vague idea about before. Core functions are discussed next, and modularization, memory management, device drivers, application layout, file system support, EXEs versus DLLs, INI files and multiprocess applications are all revisited in greater detail than last time.
Making it Happen is the title of section IV. Practical decisions are the main focus here, such as the choice of development environment, tools, source code revision systems, and so on. Writing the code for the user interface is next, and the pros and cons of using separate threads to do things like painting your window are presented. Prototyping the interface is also a good way to check the validity of your design, since only a little code needs to be written to allow "walking through" your application. Self-verification steps are common in this book, and allow you to get a better feel for whether you are on the right track with your application design or not. Multi-threading the interface is discussed in great depth at this point, and ways of keeping the user interface responsive are presented, while keeping the code manageable.
The next chapter deals with setting up the core function of your program properly. Again, multi-threading is discussed, and semaphores are re-introduced as one way of sharing resources safely.
Note: the example on semaphores and deadlock is, strictly-speaking, inaccurate. I quote: "You can see there are three threads. Threads 1 and 2 make use of semaphore A. Threads 2 and 3 make use of semaphore B, and threads 1 and 3 make use of semaphore C. No two threads make use of the same resources, but you can see that if thread 1 has semaphore A, thread 2 has semaphore B, and thread 3 has semaphore C, any semaphore request by any of the three will cause a deadlock." In fact, if, say, thread 1 requests semaphore C, it is still possible for the three threads to complete as follows: thread 1 requests semaphore C, and locks. Thread 2 requests semaphore A, and locks. Thread 3 finishes with semaphore C, releases it, requests semaphore B, and locks. Thread 1 can now get semaphore C, and run to completion, releasing semaphore A and C. Now thread 2 can get semaphore A, and run to completion, releasing semaphore A and B. Finally, thread 3 gets semaphore B, and runs to completion. In fact, any sequence of events will complete, which has one thread giving up a semaphore before requesting another. If all three threads needed two semaphores at the same time, and each acquired one, then any further requests causes deadlock. This is slightly different than the statement of the problem, but it is significant. I imagine this is what was meant.
Critical sections are introduced next, as a still safer way to share resources. The large expense of critical sections is explained, however, emphasizing that if other designs are possible, they should be pursued.
The next topic is IPC. Various mechanisms, such as queues, pipes, and shared memory are explored. Data formats, file formats, and file system dependency is discussed, including LANs. Advanced functions come next in the ASCII stream of the book. Getting the basic user interface and functionality into code has been the priority so far, but now is the time to add the advanced features that you want your application to have. It is good to do this long before adding the advanced functions, partly because of the reluctance to change something major after you have added lots of code. As Reich points out, if you add the simple stuff first, changes are easier to make because they don't make for much longer development cycles. DDE, printing, fonts, and the help facility come under this heading. Non-English language support is another, frequently overlooked item on the long list of things to look for. It is very easy to do, when done right, and extremely tedious when done wrong. How you can do it right the first time is carefully explained.
The next section deals with performance tuning. Many little neat performance tricks are presented, such as minimizing fix-up costs, accessing DLLs intelligently, thread priorities, EXE packing, and DLL placement. User interface speed is also discussed in some detail.
The penultimate section deals with testing and changing code. These two chapters are short, sweet, and use common sense, so I will leave them out here.
The final section is on installation programs, and this happens to be a pet peeve of mine. Frequently, you pick up some really neat program, but get frustrated trying to install it correctly. In my opinion, a decent installation procedure should include instructions on how to install manually, in case the installation program fails. This is obviously difficult to do in the case of something as complex as OS/2 itself. With the types of programs that most of us write, however, it should be a breeze. In addition, reinstalling and uninstalling are mentioned.
There is a brief summary following this, which concludes the book.
Designing OS/2 Applications is a different kind of book than anything else I have reviewed so far. It is theoretical in nature, and avoids actual code as much as possible. Instead, it concentrates on teaching the proper design principles needed to create a new OS/2 application. As such, in many ways it is much more valuable and important than a "mere" programming book, but it sacrifices programming detail to do this. If you have ever wanted to know how to go about designing and creating an OS/2 application, get this book. Once you need to know about the nuts and bolts of programming, you'll have to look elsewhere, however.
I like this book very much, yet there are a number of small areas that could be addressed.
The few examples that are in the book are in C. Much of the material is inherently bound to C programming, as well. For example, talking about the message implementation in OS/2 doesn't make much sense in VX-REXX or PM-Cobol. Because this inherent bias is there, I would like to see it be more explicit and upfront. The alternative would be to abstract the material away from C even more than it is, but I think it would be more workable to simply state that 99% of all OS/2 programming is done in C, and that therefore there will be a C bias in the examples. Even C++ programming is quite different, and many of the topics covered in the book become irrelevant when programming in C++.
Some parts of the book have a vague feel to them, perhaps due to the fact that the author tried to avoid a language bias. Specifically, the earlier parts read slowly, and there is a fair amount of repetition. I do not mean that the book is difficult or tedious to read, merely that it is sometimes slow going. Tightening up the earlier parts might help a bit.
Of course, the semaphore and deadlock example should be reworded.
There are some OS/2 2.1+ features that warrant mentioning. This book has been around for a bit, but a newer book is currently being written, and hopefully this information will be included there.
Designing OS/2 Applications, Reich
Our Bookstore has reviews and links to Amazon for all books we have reviewed in the past, as well as several books waiting to be reviewed, and others which we recommend.