VP-SE Research Group (C)
We used a graphical description formalism for the specification of computer based learning (CBL) lessons long before we decided to create a computer based development environment to support our methodology and reduce our development costs [7][8]. The development environment is now operational and this paper will try to draw more general conclusions from this experience in regard to the use of semiformal visual languages, i.e. a combination of a visual representation of software and natural language.
In our century of communication, image is a predominant vehicle for information. The world of computers is also getting more image- and graphics-dominated. After icon based command languages and graphical user interfaces, visual programming environments are now becoming more popular. One can already find nowadays a few such environments, available on PCs and graphical workstations, spanning a wide range of levels of abstraction. Some are indeed comparable to usual general purpose programming languages, mapping graphical structures over regular programming structures [2][3][5][6][12][13][16], and others, more application oriented, have a level of abstraction that is closer to the problem domain [10][15].
Even if they have a more friendly user interface, these visual programming languages are still programming languages, and as such, require a certain level of expertise from their users. If, as for spreadsheets, we want to make a visual language more widely used, we have to keep it simple enough to be usable by people without a computer science background. The problem, then, is to find the best trade-off between the simplicity of the language and its power of expression.
An alternative to this trade-off is to stop considering the visual representation as a programming language, but rather as a semiformal specification language by adding a natural language component to the graphical formalism. The visual language is then no longer a programming language, but merely a specification formalism (specification is used here in a broad sense, since it actually covers most of the design and, hopefully, the major part of the implementation).
The formalism is thus not totally graphical, but there are different advantages in adding a natural language component: firstly, it helps in keeping the overall language simple; secondly, it allows the designers to keep the specification relatively close to the problem level rather than forcing them to enter a detailed solution at a programming level. The specification thus remains limited to specifying actions lying in the domain of teaching and learning.
The simplicity comes from the fact that it is not necessary to include in the graphical formalism all the constructs needed to use it as a general purpose programming language. The natural language component is there to allow the designers to specify relatively complex actions without having to make explicit the "how", but just the "what" (and perhaps the "why"). As in [14], we believe that asking the user to input a program completely graphically can be rather cumbersome and undesirable. Of course, the more that can be done without resorting to the natural language component, the better (except, maybe, for documentation). The visual language should thus include most of the basic primitives required for the type of application it is used for, at the highest possible level of abstraction. To keep the language simple, the number of different basic elements of the language shouldn't exceed five to ten, and the way these elements combine shouldn't follow rules that are too complex. If these requirements are not met, the language becomes too complex to be easily used and mastered by non-computer scientists.
The price to pay for this simplicity is that further programming is needed after the specification has been written. This is not necessarily a bad thing since the designers are often not skilled programmers, if they have any programming background at all. As such, they are probably not aware of all the pitfalls of the programming activity and the notion of software engineering is most probably foreign to them.
How much additional programming is needed after the specification has been written depends a great deal on the primitives available in the visual language and on the type of application that is being developed. For large scale projects, that are, by nature, a team effort, it makes perfect sense to use domain experts for the specification and the design of the software and programmers for the actual implementation. The graphical specification can then not only be used to make the link between the designers and the programmers, but can also be used to obtain a partial initial implementation by using automatic programming techniques to convert the formal part of the specification into executable code. Artificial intelligence techniques can also be used to convert even some of the nonformal part of the specification into executable code. The automatically generated code should be executable as is, giving a rough idea of what the final product will look like. This technique allows the designers to do rapid prototyping and undertake a few design review cycles even before any "low level" programming has been done.
With this approach, it becomes important to have computer tools supporting the whole life- cycle of the development of an application. Indeed, one has to keep a tight link between the visual representation and the handcoded parts. Interactive multi-window editors that link the different components together can prove very useful. One interesting aspect of this approach is that it allows for a continuous enhancement of the automatically generated prototype to get to a complete implementation by what is called in [4] "evolutionary prototypes". Indeed, the prototype obtained with the automatic program generator is not a throwaway prototype, but rather a skeleton to which handwritten code will be added to get the final complete implementation of the program. This is very useful in a context where the people working at the design level are not necessarily working at the implementation level.
In some ways, this is an extension of what has already been done for many years now for the design of user interfaces (graphics, text, voice, sound, video or a combination of these) by using state transition diagrams, first as a paper and pencil methodology [11], and, later, with computer supported tools [9][17]. The major difference being that these visual programming methodologies were meant to be used by programmers to ease the design and the implementation of their programs. Therefore, the visual formalism was designed as a formal notation to build the actual implementation of the application. There was thus no room for natural language in the specification and the visual language had to allow for the specification of the lowest levels of details of the algorithm under construction. For instance, in [9], the diagrammatic component of the formalism is completed with a more classical textual programming language. Similarly, in [17], the state transition diagrams only specify the user interface of the application; the rest of the application still has to be designed and implemented in a traditional way.
With such authoring systems, developing courseware is very much like handicraft. The craftsmen-teachers directly implement their courseware with the tools that will save them as much work as possible. With little or no background in programming or in software engineering, they will naturally limit themselves to rather small modules only useful to their author.
Developing courseware in the large, for instance a complete curriculum, requires a much more complex and methodical approach to programming, very much like any programming in the large. One has then to consider that different individuals are involved, with various backgrounds and with different understandings of what can be done with a computer and how it can be done. Another important factor is that the designers might not be available anymore when the courseware is operational and needs improvement, adaptation or debugging.
Courseware is a very special kind of software, in that it is (or at least should be) very interactive, involving a very high proportion of input and output operations and a good amount of condition evaluation to make it as non-linear as possible in order to adapt to the user's profile and capabilities. Thus far, this description corresponds quite well to what could be said about more general user interfaces and one could thus imagine that some of the techniques (e.g. visual programming) that have been developed for the design of user interfaces could be useful for the development of computer based learning programs.
This is indeed partially the case, but courseware development in the large has some specificities that nevertheless make it different. First of all, courseware can include hours of very varied man-machine interactions with very few repetitions, whereas more general user interfaces will commonly involve a limited number of states. Secondly, the design of general user interfaces focuses mostly on the response to a correct user behavior, whereas in courseware, one should expect a lot of mistakes on the part of the user. Good courseware should thus, often, vary its response to identical user input, mainly when it is a mistake on the part of the user. Indeed, if a learner repeats the same error, it means that the help he/she got from the system the first time wasn't appropriate to make him/her correct the misconception that induced the error. Thirdly, as has been said earlier, the design of courseware will generally be done by people with very limited programming knowledge. It would therefore be an error to want to have the courseware designers specify all the implementation details during the design phase.
With all its specificities, courseware development can benefit a lot from the use of visual representation techniques. As in [17], we believe that simple state transition diagrams need to be extended to fulfill the needs of courseware design. But, as opposed to the USE specification notation, we do not try to use a completely formal formalism. As said earlier, having a natural language component in the formalism helps in keeping this formalism simple, and, in addition, helps in having a higher level of abstraction in the specification.
In order not to impose any limitation on the teachers who want to develop CBL lessons, we initially chose to use a two phase approach in which the teachers specify the behavior of a lesson in a detailed script (pedagogical design phase) and then a team of coders implement this script using a general purpose programming language (coding phase).
An initial, simpler, version of the visual formalism we use in this project was invented by Prof. A. Bork and his team, at the Educational Technology Center of the University of California at Irvine. It is independent from any programming language and is precise enough to give an exact description of the conversational flow of the final product, i.e. the lesson. In order to make it easier for teachers to master it, the formalism comprises very few basic primitives and includes a natural language component. Both aspects allow it to have an abstraction level very close to the conceptual level of the problem, i.e. computer based learning.
Although simple, this formalism allows for a complete and detailed description of a lesson (partially in natural language). Similar to a movie script, but less linear, the dialogue between the computer and the learner can be described semigraphically. A script is thus a kind of directed graph and bears some resemblance to the extended state transition diagrams described in [17]. The nodes of the graph usually contain actions and the edges represent the flow of control of the program. The graphical decoration of a node indicates the kind of action that is described in the node. The formalism is based on the following basic elements, each with its own graphical representation:
A script is internally stored as a directed graph structure with typed nodes. The automatic program generator then translates this graph into code implementing a finite state automaton. Each state of the automaton contains the execution of the action specified in the corresponding node of the graph and each edge can be translated into a change of the state variable of the automaton. One important aspect of the program generator is its ability to produce source code in different commonly used programming languages to easily adapt to what is available on target machines. The constraints that dictate the choices of a programming language is partly induced by the way the code will be generated. The target language has to be modular to allow a clean separation of automatically generated code and "handwritten" code. The states of the automaton at which a nontrivial action has to be executed are each coded as a call to an external procedure. For such an external procedure, the program generator produces a temporary implementation that will work as a prototype and that will have to be replaced by an actual implementation by human programmers.
One major difficulty in using code produced by an automatic program generator is that this code is hardly readable by a human being. In order to avoid having to deal with automatically generated code, the parts that have to be "handcoded" are in separate modules. A synchronous editor is available to help the programmer(s) write these separate modules. The idea is to have different windows show the different aspects or views of the same thing: a regular text editor in one window to edit one of the separate modules that have to be handcoded and the script editor in another window to show the corresponding specification. The programmer can thus very easily see, write or modify the code corresponding to a specific part of the script by finding the location in the script window and then asking for the module window to show the code for that part of the script. One can also find a specific location in the code (e.g. where an error occurred) and then ask for the script window to show the part of the script that is the specification of that part of the code.
With this tool, the programmers can always see the specification at the same time as they see the code they are working on. This specification (the script) should help them understand and manage the code, since it can be seen as a human readable description of the code. As a side effect, this approach also encourages the designers to keep the specification up-to-date with the code. Indeed, the fact that the graphical specification is easily modifiable with an appropriate tool and that the specification and the code are tightly coupled makes the developers less inclined to patch the code directly as they might be tempted to do if the specification were a independent document. In addition, a version mechanism integrated to the synchronous editor allows the programmers to easily find the places where the specification has been modified since the last implementation was completed. They are then shown the changes in the specification and they can then adapt the implementation accordingly.
For those cases in which the graphical language is not powerful enough to fully specify the behavior of an application, a conventional programming language is generally used in complement. Part of the specification of the application can then be written using this programming language, most probably in a textual form. Such a code segment could be visualized as a specific kind of icon in the graphical specification.
If the graphical language is interpreted, it makes a lot of sense to choose an interpreted conventional programming language to go with it. The interpreter for the conventional programming language would then have to be integrated into the graphical interpreter to allow the latter to invoke the former for a code segment item of the graphical specification. An easy solution is to write the graphical interpreter with the same interpreted programming language as the code segments. The graphical interpreter then just needs to pass the text associated with an icon, representing a code segment, to the programming language interpreter. For example, one could write the graphical interpreter in LISP and have LISP also used for the code segments of the application.
If the graphical language is compiled (i.e. translated into source code for a conventional programming language), it seems better to use a modular target programming language. This way, the code needed to complement the graphical specification of the application could be given in separate modules and compiled separately from the automatically generated code. This solution is more flexible than using a graphical interpreter since the programming language for the graphical compiler need not be the same as the programming language used on the target machine. The graphical compiler can even be table driven in order to generate source code in different target languages, which allows the developers to adapt to whatever programming language is available on a target machine.
Another aspect that is worth discussing is the separation between the development and the runtime environments. Even though this approach has its drawbacks, the fact that we want to be able to develop courseware for many different target machines makes it mandatory to have this separation if we do not want to have to port the whole development environment to each different target.
Although this is not surprising, it is interesting to note that the introduction of computer tools led us to extend the visual aspect of a formalism that existed prior to these computer tools. In addition, these new tools changed the way people managed their work, mainly in the design phase. Indeed, the use of computer tools encourages the designers to build a more modular description of the software they are creating.
In spite of the fact that it is not commonly done in visual programming, we are convinced that the combination of a visual representation with natural language leads to a clearer description of software than strictly visual languages would allow. This combination helps in keeping the description at a high level of abstraction, making it more readable by other people. It also helps in saving the designers from having to specify too many details that pertain more to the implementation than to the specification or to the "problem level" design. The main risk here, is to have ambiguities in the description of the application. For instance, in our case of courseware development, the designers may leave various matters undecided at the level of the lesson. It is not infrequent that coders have to consult the project manager, and through him, the designers, to try to resolve questions that the designers failed to handle, or maybe even to notice. Evolutionary prototyping can, in some ways, compensate for this, in that it allows the designers to test the implementation already during the implementation phase and not just after everything has been coded. One can therefore hope that misinterpretations of the specification can be discovered at an earlier stage, and thus reduce the cost of the corrections.