We present 3 views of software development which will frame the nature of software; in turn these views will allows us to focus on identifying the issues in software development which will affect its maintenance; using these views we will be able to coherently present the need to carefully model a solution to the problem at hand; and in particular the need to carefully design objects and make this activity distinctly different and far more important than algorithm design. The most fundamental consequence provided by these views of software is the opportunity that it provides us to instill in the mind of the students the true nature of software and the mental mind-set that students ought to acquired in regards to software development from its first encounters with this science and craft.
Instructors must provide students with a different mental mind-set as to the nature of the kinds of solutions sought out with software; a different to the one that has been provided up until now. A new mental mind-set is of increasing importance in particular when introduced to OOP. Software cannot be equated in these courses to the development of static code that "works", in particular and the teaching of a the syntactic component of a programming language in general, with some asides on design and documentation. The teaching of software development must be supported by the most appropriate views of what a piece of software is, as well as the appropriate mind-set to approach this task. Throughout the years the software community has developed many principles, methods and practices for the support of this activity; all of these can fall on fertile soil, when the practitioners have a precise view of the nature of a software system. Furthermore, these view ought to be instilled starting very early in the learning of their chosen career.
Current as well as past teaching books equate software of a computer system with the collection of programs; and programs are equated with the implementation of algorithms. Procedural programming, with its methods and practices, supports this view which has been brought to a highly recognized and well respected discipline, and deservedly so in our field; design and analysis of algorithms is at the heart of computing science. This view of software although correct does not tell the whole story behind the actual nature of software, nor is a healthy view of these objects.
With the advent of software engineering as a discipline, software engineering have been reshaping this view; as a consequence the nature of software has been further elucidated and brought to a state where we can easily conclude that is not just a collection of algorithms. The most fundamental software engineering principles formulated as result of the study in the nature of software are the Information Hiding Principle and the Software Continuity principle. The information hiding principle stated as A user of a piece of software does not need to know and should not be allowed to know how a the software works to use it.
The software continuity principle, as stated in [2], A small change in the specs should produce a small change in the implementation. These two principles stress the need for the use of Abstract data types at the solution model level; at the implementation level they are implemented by languages supporting the implementation of ADT's via a public specification separate from a private implementation; the software continuity principles also begs for the hierarchical development of library units based on kinds of values of a given type.
These principles guide us in the development of software amenable for changes; and it gives us a partial view of the characteristics that a software library unit or system ought to implement for the production of maintainable software in general and in particular for the construction of fire walls among software modules, as well as software that is malleable in the face of evolution. Furthermore with the advent of Object-based programming supported by languages such as Ada `83, and Object Oriented Programming supported by languages such as C++, Ada `95, and Eiffel among others, these principles as well as the current view of software are not only supported but the true nature of software, seen as solutions to problems, has been brought to the fore.
In the teaching of software development we would like to have whole views of the matter at hand as well as good definitions of the subject. In the case of the teaching of software methods and practices whole views of software help us focus on them as a supporting framework. We proceed to present 3 whole views of how software must be perceived and how this perception can help us in the teaching of methods and practices in software development.
First view: Software = Temporary solution to an evolving problem
This definition or view totally embodies the nature of software and help us in identifying the fundamental activities that must be undertaken in the design and implementation of a software system. These fundamental activities are the design of the system that models and isolates the current view of the problems and the actual implementation of this system. In object oriented software development, we say the two activities are Object design and algorithm design; Object design produces the collection of objects that not only models the current problem at hand but also it help us in modelling the dynamic component that makes the problem evolving. Algorithm design deals with the design of the algorithms used both in the support of the functionality of each of the objects involved in the solution but also in the design of algorithms that implement the interaction of these objects.
This view of software brings home the issues addressed by the software information hiding principle as well as the software continuity principle; furthermore it places object design in the drivers's seat of software development process. This view addresses the quality of the model used in the development of a solution, this model being the result of the design process; that is to say, weather the model given does contain the characteristics dictated by the nature of the problem is solving. The problem is evolving, thus we expect to have evolving solutions. Evolving problems search for solutions which successfully identify and separate the characteristics of the problem which will remain stable in the life of the problem and those which are likely to change; evolving problems also requests for solutions where change can be localized and solutions are grown and are dynamic as the problem they intend to model is dynamic (in the sense of their evolving nature).
This view does not conflict with the view of software as a collection of implementation of algorithms; it identifies that component of software development and it places it in a supporting role, that of the implemeter of the abstract model provided. The identification of the first activity as fundamental, data design in particular and design of a problem model in general, is what makes this view a fundamental view in the face of the nature of the problems intended to be solved using automated means.
It must also be added that the term temporary brings out the nature of the evolution of the problem at hand. Problems are not rigid, well-defined, well-behaved artifacts with their corresponding solution, implemented using automated means having, expecting to have same characteristics. By qualifying the solution as temporary it ought to provide an appropriate mental mind-set to place more effort in identifying those components which are at the heart of the problem or its solution; it also brings forth the fact that this is an instrument which will must undergo changes.
Second view: Software = Data + Algorithms
This view was initially inspired by Wirth's book [3], titled "Algorithms + Data Structures = Programs" Wirths makes the point that any algorithm handles data, and therefore attention must be given to the design of the data representation and its affects this representation can have on the algorithms. Here again the activity of design is recognized in the algorithm component of software development; in OOP, is found in the implementation of an object specification. For a book written in 1976, it was addressing the issues that affect not only the development of programs but also their maintenance and that is what we now readily recognize as Information hiding. Object orientation has brought a new cut and a revision to Wirth's equation. In the face of evolving problems, we now see that not only data representation plays a role in the design of a solution but its role is larger that what was originally thought. Data is the most stable and influential component in the design of a software system. Not only we must isolate the representation of the data, we must carefully design its abstract view, and its relationship with other data, i.e. we must pay serious consideration to the cohesion and coupling of the ADT's involved in the solution. This is the reason that in our second view of software we place data as the first component of this equation. We can rewrite the above equation to read Software = DATA ==> Algorithms; read Abstract data design then algorithm design. The abstract view of data and the implementation of this abstract view via algorithms gives us the essence of the programming process. Looking at software via this view provides a mind-set in the way we look at our activity of program development; it's placed on a much healthier path that the one given by Wirth's equation; it should also be noted that this view is a consequence of the first view given.
The view of a software piece as a math document addresses the kind of quality the contents it must hold. It puts in the proper perspective the quality of the code it contains and the practices necessary to produce it. Brooks [1] brings forth the fact that code must be perfect, wishing perfection from the programmer. By bring out the math component in a piece of software, it request from us to provide for checks that the code performs as specified (partial correctness). These checks can be given by pre-conditions, post-conditions, loop invariants, assertions, and ADT invariants and assertions. In face of the second view, we must abstractly design the data via ADT's; thus the specification/implementation of these ADT's using precondition, postconditions, invariants and assertions place us in a fundamentally sound scenario. This is what is now called programming by contract [2]; contract that ought to be drawn between the data specification and the user and (hopefully) validated by the system. (Eiffel is one such language which supports programming by contract).
Also his view addresses and brings out its correctness as well as the human component in a solution. The view that a solution is an english document acknowledge the fact that solution and its implementation will be read and maintained by humans. As an english document it provides a model for its presentation; this model has to be molded by the type of document it is, a technical document, but nonetheless a document. This then sets the stage for the kinds of requirements that such document ought to have starting from its presentation all the way to the method it uses to allows you to find information in the document. Therefore all issues introduced to address readability and understandability of the document are well based. It also brings out the fact that solutions are not only meant for machines to execute but for humans to consume; all issues addressing what constitute a humanly readable and maintainable piece of software[4] are there to support this view. Testing a means to test solution for its evolving requirement. All of these characteristics as presented above come together in determining the quality of the program developed to solve a problem. We can definitely say that A program is as good as its test bed. The goodness of a test is determined by its ability to detect a yet undetected bug. The quality of the goodness of a solution is then measured by the ability to identify and remove that bug. A successful removal of a bug measures the readability and understandability of the code, (third view), the localization of the bug and the code it affects (second view), and the adaptability of current (faulty) solution for a new correct solution (first view).
A Foundation for Software Development
Computer Science departments throughout the country are embracing the Object Oriented paradigm as the teaching methodology in the introductory courses. We perceive the reason for this shift not only because of the success of this methodology in the software industry but because of the recognition of the nature of problem modeling and solution using software systems. The procedural paradigm along with its functional decomposition methodology has found its place in the development of systems, and that is in the implementation of algorithms, not in the modeling of its solution. This is the fundamental role played by the OO methodology, to model solutions for evolving systems. Therefore the prevailing method of introducing programming using well-defined, static and self contain problems with its set of small complete programs must undergo a revision. The three views presented here only reinforce the need for the change in our pedagogy and for the need to shift our teaching emphasis from algorithm implementation to the teaching of design of solutions which can be measured using the views presented above.
It has taken over 40 years since the advent of high level programming languages for our field to elucidate the nature of software, along with a whole array of methods and practices to support is development. As educators we must provide students with an appropriate mind-set as well good models of development based on sound views; by providing fundamental views of our main activity, software development, we can not only teach the principles, practices and methods for the development of good software, but we can actually start by stating what good software is, and provide then methods not only to teach but measure its the goodness of their efforts.