Getting Started | Documentation | Glish | Learn More | Programming | Contact Us |
Version 1.9 Build 1556 |
|
The AIPS++ project has a mission statement ([#!hunt:mission!#]). Somewhat simplified, the portions of it which have design ramifications are:
It is probably worthwhile quoting verbatim the final point of the mission statement:
``15. In summary, AIPS++ shall be programmed to be flexible and versatile to use, to modify, and to enhance. Researchers other than the main support staff shall be invited and encouraged to add applications and functionality.''
Some other issues related to the implementation of these goals by the AIPS++ project are described in [#!sn:strategic!#].
A fundamental decision was made to use object oriented concepts in designing and implementing AIPS++. Largely because of the requirement for portability, C++ was chosen as the implementation language. While C++ implementations presently tend to be immature and painful to use, on balance it has been a suitable choice.
Object oriented design and implementation offers some major benefits. Probably the primary advantage is that of encapsulation. Encapsulation imposes the discipline that data can only be modified through a well defined and consistent interface. The unit of encapsulation in C++ is the Class, which is (more or less) the same thing as a type. With encapsulation, if only the implementation of functionality needs to be changed, but not its interface, then no source code changes outside the class need be considered (i.e., changes in implementation are localized).
In a sense, adding classes to an OO language can be considered to be tuning the language to the problem domain (especially in a language like C++ which has syntactic sugar such as operator overloading).
Another advantage of OO is inheritance: the ability to create a new derived class by adding on to an existing class.
Much more important than inheritance is polymorphism, which allows classes with a sufficiently similar interface to substitute for one another. This allows, for example, a new kind of clean deconvolution to be introduced without having to change any client code that needs such deconvolution. That is, not only does a class interface hide its own implementation, it can also hide the details of exactly what class is being used, allowing the class in question to be substituted without causing changes in the clients.
In C++, polymorphism is achieved through inheritance (derived classes may substitute for base classes) and templates.9.1
The above short summary cannot hope to do justice to the subject. For more details on OO design and programming in general see [#!booch:oo!#,#!meyer:oo!#,#!rumbaugh:oo!#]. For an introduction to C++ by the creator of the language, see [#!stroustrup:c!#]. For an excellent description of the C++ idioms necessary to build a complex, real-world system, see [#!bn:scientific!#].
The gems of any software project are its application-domain algorithms and unique support structures. It is vital that these be reusable, not constantly reinvented.
The primary consequence of this is that application-domain expertise should be available in libraries, not ``locked up'' in an executable. Functionality which is only available through an executable is only able to serve those needs the application programmer was able to foresee.
Applications should thus be fairly simple. In some sense they are merely a convenient packaging of some aspects of a library. At the very least, functionality should at least be put into application specific classes and functions which can later be migrated to a library.
Users and programmers will want to approach programming in AIPS++ in a variety of ways:
This type of computing may be performed via a command line interpreter (CLI). For users with unusual ideas or needs, it lets them perform ad-hoc computations or try out new algorithms without having to enlist a ``pro.'' While much can be done merely with a language that allows whole-array computations, to be most useful the application-domain functionality in libraries must also be available to the CLI programmer. In fact, the CLI can be thought of as the most flexible interface to a library.
If no significant classes or functions need to be written, this programmer should consider programming at the CLI level instead.
When AIPS++ is more mature, this programmer will typically use AIPS++ classes, but will not necessarily write any, or at least the classes written will be fairly simple. This programmer might well write significant functions (algorithms) however.
At the next level down is the class developer. This programmer might need to do something fairly straightforward, like introduce a new CLEAN variant (straightforward once the algorithm is thought of!), or more involved like implementing a set of classes to encapsulate a calibration scheme.
Below this level lie the programmers who provide the support classes (e.g., arrays and tables) that the whole system is built upon. These programmers have a difficult job since all other programmers leverage off of their efforts.
See the next section (9.2.4).
In the future there may be people who want to use the services in our libraries, but are otherwise uninterested in AIPS++; for example the FITS classes. While such uses aren't in our core constituency, this reuse will allow them to concentrate on their application domain; this also advances the cause of Science.
Non-AIPS++ packages may wish to use parts of AIPS++, or in turn be used from AIPS++. While many levels of operability might be possible, the most promising would appear to be:
Parallel to the above programming levels (``how much stuff is done by each line of code'') are levels that correspond to how much of an underlying model (e.g., a calibration and imaging model) the programmer has to accept.
Since there are certain to be disagreements about such models, programmers who are too impatient to learn them, and new instruments or disciplines that do not fit them; it is important that such programmers be accommodated.
To accommodate such programmers, the actual computations they might need must be available at a mid-level. For example, rather than having CLEAN embedded solely in a high-level ``Measurement model,'' the actual computational kernel should be available in mid-level classes that work on arrays and/or images. Irrespective of other concerns, such layering is good software practice.
The X-Windows system has a similar problem and solution. The core functionality is encapsulated in policy-free libraries, and the higher level ``models'' are encapsulated in additional libraries (Motif) and entities (e.g., window managers).
A decision which has caused some controversy is that all9.3 AIPS++ data should reside in a common data structure, the AIPS++ Table (described in section 9.4). This decision allows several important capabilities:
Given the ``impedance mismatch'' between C++ and C or (particularly) FORTRAN, it is unrealistic to assume that programmers in those latter languages will have full access to the functionality developed in C++. However, if the FORTRAN programmer at least has access to all the data, he can perform any desired computations.
While computations should normally take place through well defined classes, occasionally an arbitrary calculation needs to be performed or arbitrary values need to be inserted. If all data ultimately resides in tables, such operations can always be undertaken. An example of this would be modifying a calibration value through a GUI table editor.
It is certainly true that the user can get into trouble by arbitrarily modifying tables (since software might not understand what to do with those tables if sufficiently changed). However, the alternative is worse; after all the data does belong to the user, and sometimes scientific exploration will require operations that no software system can anticipate.
While the following run the danger of being non-controversial statements of motherhood and apple pie, perhaps they will be of some use written down: