Code Architecture

There is a fair amount of documentation in the code itself, and users interested in the detailed workings of the code should examine it themselves. This document provides an overview. I have tried to separate the code involved in the calculation from that involved with user interaction. Part of this was by design prior to the 3.0 overhaul, but most was incorporated in the version 3.0 overhaul and was necessitated by the desire to retain as much as possible of the pre-3.0 C++ code intact.

Overview of program operation (from a code perspective)

When run, the OS automatically displays the Settings window, pre-populated with the default values (either the hard-coded ones, or those from the previous run of the program). Every change in a setting is immediately saved to the preferences. When the Begin analysis is clicked, control is handed to a spawned thread in which the calculation runs. This enables the application to have user interaction (updating progress, clicking the cancel button) during the calculation. The inter-thread communication is handled using the high-level Distributed Objects method. This allows data to be sent either synchronously or asynchronously between threads, and allows synchronous or asynchronous method calls between objects.

When the cancel button is clicked, a notification is posted, and the AppController will receive a notification of the fact. It then merely sets a flag. This flag is checked after many portions of the calculation (but not every time the progress indicator is incremented). If the flag is set, then an exception is thrown, objects are cleaned up, and the settings window is posted again.

C++, Objective-C, and Objective-C++

Way back in the early 1990, Reduce3D was written in Pascal. It was overhauled and substantially expanded as part of Dave Hirsch's dissertation and during that process was ported to C (briefly), then C++ for version 2.5.8. As part of the 3.0 overhaul, due to the obsolescence of the CodeWarrior IDE and PowerPlant UI classes, all the PowerPlant UI was replaced with XCode/InterfaceBuilder UI, and the utility classes of PowerPlant (LArray, LString, etc.) that were heavily used in the code were replaced with classes from the C++ standard library (e.g., vector, string). This makes the computational part of the code largely independent of the UI, and fully portable to other operating systems.

For the Mac OS X user interface code, it is much easier to write in Objective-C. All the top-level code (AppController) is Obj-C, and the classes designed to manage to user interface are objective-C as well (AppController, progressController). There is another Obj-C class that serves to setup the Distributed Objects thread system and starts the calculation when the button is clicked (Mediator). A number of classes need to make Obj-C calls (e.g., to interact with those Obj-C classes for updating progress bars, checking whether the cancel button was clicked, getting settings from the settings window, using OS calls to read and write files) but which must be C++ for interfacing with the rest of the program. These use a language construct called Objective-C++ and have the ".mm" extension. Objective-C++ classes can mix the two languages, almost at will. An Obj-C The primary instance of this is the Calculator class, which does the bulk of the work in the program. Most of these classes have pure C++ header files that can be included in other C++ definition files. In some cases, a C++ class needs to hold a pointer to an Obj-C object, but have the header be include-able by pure C++ definition files. In such cases, these are stored as void * and are cast to (for example) AppController * before use.

Computation Overview

Here is pseudo-code for a standard execution involving a set of input files, each with null hypothesis interface-controlled envelopes:

Back to top