Do I Need Prototyping?

Introducing a Dynamic/Static Typing Transformational Approach

David L. Shang



Okay, let me put it this way: the result of prototyping is not the prototype itself, rather, the design conceived in the prototype. When we throw the prototype away, we don't throw the design away. A sculptor would use clay to get the approved figure of a creative art piece before using the expensive and tough material. The clay piece is going to be thrown away, but the approved design is retained and patterned by the finish work.

So do I favor prototyping? Not always. The key point is whether it is worthwhile to work on a prototype.

First of all, what is prototyping? It is an iterative approach to requirement analysis through the production of a functional form of a new design of a system. The functional form must have a full-scale architecture (elements and the relationship among elements) and all the required functionality.

Since prototyping is an iterative approach, we must have an economical way for design changes during the whole process. Elements to build the prototype should be flexible or generic in both architecture and functionality. They usually add a significant overhead to the whole system; so that a prototype, though functionally equivalent to a real product, cannot run efficiently.

In software development, dynamic languages are usually chosen for rapid prototyping. During requirement analysis, a change of the system architecture or functionality is often required. When this happens, we need an economical way to add/delete/modify attributes and methods to a group of objects. Since a dynamic language supports dynamic typing in which a type can be changed at runtime, it breaks through the edit-compile-run-crash-debug cycle, which is a quite time-expensive procedure in a static language when thousands of changes are required.

A prototype is not cheap, since it is a first model of a new design. It is sometimes so expensive that the cost of the prototype can double or triple the price of millions of real products. Thanks to the invention of the information duplication system, we have almost zero cost in software mass-production. Do we still need prototype in information industry? The answer depends on the development cost.

If you chose to develop software without prototyping, you are going to build your software system with elements which are efficient but intractable. You stick to a single static programming language like C++ or Eiffel in the whole development process. The more changes in the development process, the more expensive your approach is.

If you chose to develop software with prototyping, you are going to build your software system with elements which are flexible but inefficient. You use a dynamic language to build a prototype first for concept approval and then transfer the design into an efficient implementation in a static language. The more changes in the development process, the more benefit you can get from prototyping.

Therefore,



If the system you are going to develop is mainly a duplication of an existing work, or an implementation of a mature design, you may not do any prototyping because you already have the picture of the system in your mind. You can develop your system right away, and follow your mind to make the sculpture from the real material.

If the system is a new design derived from a vague concept and you have no idea what it exactly looks like, you should use prototype to approve the concept and detail the design, reduce the risk of a bad design that is too late to be changed economically in a real system.

To speak in truth, however, I never use prototyping in my software development career. I didn't ignore the benefit of prototyping as many other people obtained in their development experience;



No one is willing to have a redundant development. Building a software prototype is not as easy as clay sculpture, nor the re-development work as easy as baking the clay work into a piece of ceramic.

If there was a magic wand or alchemy that could transfer my prototype into a real product without any re-development work, I would have used prototyping without any inhabitation. Programming languages like Self and Dylan are supposed to give us the alchemy, which begins with a dynamic system and provides an automatic transformation to efficient static systems. But the result of the transformation is doubtful. Self uses extensive in-line expansion for speed but sacrifices space. As a result, even a small program requires a huge memory footprint. Dylan uses multiple dispatches for function calls, which is time-expensive. The major task of transformation, therefore, is to eliminate run-time dispatches by type inference, which is impossible for an open system. The performance of the result may be disappointing if an open interface is used by a frequently called function, for instance, a function interface that handles a large number of small grained objects in a heterogenous collection. Both languages are in a dubious state.

No one is willing to keep separate versions of a system either: one in prototype and another in the released product. Requirement and design never stay unchanged even after your product is delivered. They continue to evolve, sometimes a little bit but sometimes maybe so radical that you need to redesign your whole system for the next generation. When the fundamental change is required, you have no way to start with your original prototype because the real product has been changed, a little by little, and far away from its original prototype. If you want to keep the consistency between the two versions, you have to make a corresponding change in the prototype every time when you make a small change in the product. The trouble to maintain the consistency might greatly overweight the benefit of using the prototype.



So, where can I get the benefit of fast development and get rid of the annoying edit-compile-run-crash-debug cycle?

You can get it, not necessarily from prototyping, but from the production of the real product.

Some modern development system uses a static language and makes the environment dynamic. The development environment uses interpreters, incremental compilation, and dynamic linking in order to speed up the development process. Examples include some advanced C++ development environments, ISE Eiffel, and Delphi for Pascal. Today's processor are so fast that the difference in turnaround time between a dynamic/interpreted environment and a static/compiled environment might be indistinguishable for some small systems. The improvement, however, is still limited. Development speed is still constrained by a frequent edit-compile-run-crash-debug cycle; and the shape of a system model must be captured at the design phase, which is very difficult for systems derived from a vague idea.



A system element (class) is initially developed in the dynamic environment for rapid development. The element can be modified and tested dynamically without compilatation. When the element becomes stable and comes to meet a certain required standard, it can be frozen into the static environment. Note that the system element is not frozen for testing, rather, it is frozen after being fully tested and is ready to be released to customers either internally within the developement team or externally. This is a fast development process without edit-compile-run-crash-debug cycle. For a large system, all system elements may be fully dynamic at start-up, which enables fast development. As the development process proceeds, finished sections are frozen into their static form. The system gradually evolves to maturity from the "prototype" quality to the product quality. This is an evolutionary development process without throw-away prototypes; Market requirement continues to change even after your product is delivered. What this happens, you can melt your whole product into the dynamic environment agian for redesign, which introduces a different cycle: melt-redesign-freeze-release, which significantly reduces the cycle time for developing next generation products.

What is large, what is small? What is dynamic, what is static? There is no watershed. In reality, we need a gradual transition from the dynamic state to the static state. We need something between the two extremes: a fully dynamic typing system as offered by current dynamic programming languages, and a fully static typing system as offered by current static programming languages. Application developers need to pick up the right mechanism which is flexible enough to meet the challenge in functionality, but not too flexible to satisfy the requirement in performance. Do we have such a thing? Yes. But I'll reserve it until my next column on dynamic typing.

A joint research program on this new development system has been established in December, 1995. The research partnership includes University of Illinois, Nanking University, and Motorola. MagicFrame, the new software development environment, will be based on the Transframe programming language, a C++ derivative.

Stay tuned in. In my future columns, I will provide an on-going discussion of various design issues in the Transframe language and language features, giving emphasis to new and advanced concepts.

Here is a list of questions reguarding to the new development system, click on questions for answers.