Idémaskinen


Projection programming, the future of software development?

Posted in Annat av Robert Wensman på 20 augusti 2010
Tags: ,

I would like to share with you one of my deepest insights in regard to software deveolopment and programming languages. This is an idea that I have been searching for in over six years, working proffessionally with related issues, and spending endless of hours thinking about how to solve a particular problem. Finally, one nice summer day 2008 I was lying on the grass this idea suddenly hit me like lightning! What I came up with could result in a new programming language paradigm, and possibly change the way we write interactive software. Here is the story.

(and yes, projection programming has some things in common with Neo’s dodging of bullets in the movie Matrix)

Problem domain

So, what is the problem I tried to solve? Well, how about if you want to create a really advanced interactive user interface. I am not talking about some simple modal user interface with a couple of modal dialog boxes. I am talking about the kind of user interface that continously give advanced feedback to the user, such as a word processor that continously updates a WYSIWYG layout, or checks your spelling. Or for example advanced IDE:s that compile and verify your programs at the same time as you write them. Just to give some examples.

What is characteristic for this kind of software is their predominant non-modality. When the user interacts with the user interface, he is continously presented with various consequences of his interaction, giving an interactive experience. I have been professionally involved in developing this kind of software, first working briefly for Intentional Software and then later Configura.

Contemporary methods

Undoubley, there are a number of such user interfaces around, created using contemporary programming methodology, such as ordinary OOP. The methodology to provide interactivity is to use listners/observers to propagate change through the data strucutres of the program. This is often referred to as the observer pattern, closley related to the model view controller design pattern (MVC pattern). Sometimes change propagation comes in the form of more simple ”hooks” or ”callbacks”.

The underlying reason for dealing with data change propagation in the first place, is because it would be too expensive to re-generate the whole user interface at every underlying change. In essence, the incremental update of the user interface is the sole purpose of dealing with change propagation.

Although these methods without doubt works, and has been used to produce a lot of great software, they have huge dissadvantages. In essence, the programmer first has to write code that produces data, and in addition, write code that incremetally updates that same data or parts of it as a response to change. Hence, any data structure or algorithm has to take incremental updates into consideration. Not only that, the program has to explicitly keep track of all data dependencies that might exist in the program. Also, in addition to managing the program’s state itself, the program needs to deal with the computational state of itself in the form of validation meta-data that is used during the update process. This poses a challenge for the programmer, and it should come as little suprise to anyone that building a large application using these methods is diffcoult and expensive. The possible pitfals are:

1. Logical errors introduced when a non-incremental algorithm is translated into an incremental counterpart.

2. Incorrect setup of data dependencies.

3. Incorrect handling of invalidation.

This is probably the reason why there only exist a handful of usable word-processors in the world today, while at the same time there are endless numbers of simple text editors. As we move from dealing with a simple text flow, to the full blown consequence analysis of an advanced WYSIWYG layout, the programming task simply becomes too difficoult  for the average programmer to deal with in an efficient way.

The Vision:

But what about if there was a way to propagate change through a program that did not require the programmer to consider incremental updates of data that was once written? Some method, that would make it just as easy to write a WYSIWYG word processor, as it it would be to write a text editor. Inspired by Configuras new programming langauge cm invented by Göran Rydqvist, I started a pursuit of new programming language constructs that could help to solve this particular problem. At the beginning when I approached this problem, I tried to come up with programming language features that would inherently support the observer pattern, thinking that this might be sufficient.

But finally I realized, that what makes a programming langauge strong, is not foremost about what you can express with it, but rather, what you do not even need to express with it!

So, projection programming is all about that. A programming language paradigm, where change propagation to a large degree is implicit. So projection programming is not a programming paradigm that will let you create observer patterns or MVC patterns more easily. It is a programming paradigm where you do not even need the observer pattern or the MVC pattern!

Down the rabbit hole

To give some relief to the curious reader, I will already here give a small glimpse of what projection programming is all about. After having looked at the basic idea, we will continue with the ”why” and ”how”.

We can try to understand projection programming by using a methaphor. In the movie Matrix, Neo can avoid bullets by moving in a timespace where the bullets seem to have less of dynamic movement, but rather appear more as static linear projections. In this time space Neo can even pick the bullets out of the air using his fingers. In a similar way, projection programming treats execution time as static, and like we shall see, it will allow us to do completley amazing things! Some software design problems that could be considered hard, or even very hard, can be made to simply vanish.

So, how does it work? In most contemporary programming langauge paradigms, functional as well as imperative, and possibly for logical programming as well, it is customary to execute programs using an execution stack. The only exception to this is really just distributed programming where components on a higher level communicate through signals, like for example in Ada or Erlang. The stack conceptualizes the idea of:

”doing something while keeping track of what you are doing at the moment”.

But what about if instead of just using a stack to perform computations, we store the computation itself using a tree. The stack of a running program is projected on to a tree, hence the name ”projection programming”. In addition to this, all data that is manipulated throughout the projection, is beeing kept under version control. This conceptualizes the idea of:

”doing something, while remembering exactly how you did it”.

The execution stack relates to the execution tree as a picture would relate to a movie. For a long time it was impossible to view movies on a computer as the hardware of the time was only able to deal with static photos at most. Maybe now it is time to make the same transition for the execution of programs?

(OBS! One text in the figure above turned out wrong. It should say ”Version controlled heap” instead of ”Version controlled stack”.)

Now, what is the purpose of this anyone might ask, well, since the computation is stored explicitly it becomes possible to automatically update the computation itself as a response to change, thus releaving the programmer of ever having to create incremental algorithms using change propagation methods.

What happens, is that whatever parallell data flows exist in a computation becomes plainly visible in the execution tree. For example in the figure above, it is possible to identify 2 parallell data flows. These parallell data flows can be  used for change propagation that only demand computational resources that correspond to the extent of a certain data flow. This way it would be possible for the execution model to automatically perform incremental updates of a user interface.

Pay a lot to gain a lot

Anyone having the slightest understanding of performance issues might be taken aback at the idea of storing the incremental stages of the execution of an algorithm. But even though this poses a grand challenge, it might not be as bad as it first might seem. For example, not all parts of a program has any parallell data flows, and for those parts who don’t it becomes uneccessary to store the entire execution tree. So with some fairly intelligent compiler, the extra memory requirements might turn out not to be so much in the end. There is even a theoretical possibility that the memory usage could be comparable to what a corresponding ordinary program would use. We will discuss the possibility of reducing the memory requirements more in detail later.

But on the other side, we have to look at the gains. It turns out that this not only provides powerful methods for creating higly advanced user interfaces, but also gives a lot of benefits for free in regards to creating version control software and general undo systems for editors. Because if our execution model is able to manipulate execution trees, creating undo as a built in language feature that operates on statement level becomes fairly straightforward.

In the long run, there are even potential benefits in terms of performance. How projection programming reveals the parallell data dependencies of a program might very well turn out to be a key technology as we increasingly put our faith in multipple processor cores and parallell computing. Because if our programming language gives us access to whatever parallell data flows exist in a program, we have a better chance of dividing work between different processors.

Parallellism and change propagation

It turns out that there is a relationship between incremental updates on one side, and parallellism on the other side. This is because wihtout any parallellism in the data flows of an algorithm, there would not be any possibility for incremental updates, making change propagation pointless. So any programmer using contemporary change propagation methods, are in fact trying to reveal the parallell nature of the problem domain. Controversivley, if we create a system for automatically revealing the parallellism of a computation, there is no need for writing code that deals with change propagation.

This brings us to another question. It is a common missconception that the parallellism programs in general is fairly limited. This dates back to some observations done in the 60’ties and the early 70’ties, but clearly there is a limited scientific value in such a statement, as the programs of the 60’ties and the 70’ties are hardly representative of programs today, or the programs that might exist in the future. Some algorithms are 100% parallell while others are 0% parallell, and there is no general rule which could state that algorithms in general are only parallell to a certain degree. This page gives a proper definition of parallellism, and some words of wisdom.

Actually, there is a relationship between the parallellism of a program, and its non-modality. In a user interface that instantly gives the user advanced feedback on multiple levels, there are typically more parallellism. The background compilation in an IDE is for example largley parallell to the tiny changes that the user might do to a program. The layout of a large formatted text document is to a large degree parallell since page breaks and paragraphs break up the sequential text flow. So, for the particular problem domain projection programming was intended for, there should be a lot of parallellism to exploit.

Games, physical simulations and AI applications are other areas of software design, where there are large possibilities of finding parallellism to exploit.

What is at stake, and the current state of the Art

When I briefly worked for Charles Simonyi on a project of his, former project manager of Microsoft Word, he once told me that

”Programming is the opposite of dimond mining. When mining for diamonds, you start out with a lot of mud, and you dig out the diamonds. In programming, you start with a crisp and clear idea, and then bury it in the implementation details.”.

We shall now have a look at the current state of the art in terms of programming languages, and just how much extra programming code they require. This can help to explain why projection programming can be important enough to motivate investment into a completley new programming language paradigm, even if there are large risks involved in doing so.

In our example A, we have a simple loop, that reads values in an array, and updates another array creating a blured virsion of the first array. This could for example be similar to what happens in an image manipulation program.

A:

blur(int[] a) {
   int[a.length] b;
   b[0] = 0.75*a[0] + 0.25*a[1];
   for(int i=1, i + 1 < a.length) b[i] = 0.25*a[i-1] + 0.5*a[i] + 0.25*a[i+1];
   b[a.length - 1] = 0.75*a[a.length - 1] + 0.25*a[a.length - 2];
   return b;
}

But assuming that the array can be very large, it migth make sense for a programmer to organize this code so that only a part of the output array needs to be updated if only a part of the input is updated. It might look something like this.

B:

blur(int[] a) {
   int[a.length] b;
   blur(a, b, 0, b.length);
}

blur(int[] a, int[] b, int intervalStart, int intervalEnd) {
   if (intervalStart == 0) {
       b[0] = 0.75*a[0] + 0.25*a[1];
       intervalStart++;
   }
   if (intervalStart == b.length - 1) {
      b[a.length - 1] = 0.75*a[a.length - 1] + 0.25*a[a.length - 2];
      intervalEnd--;
   }
   for(int i=intervalStart, i + 1 < intervalEnd) b[i] = 0.25*a[i-1] + 0.5*a[i] + 0.25*a[i+1];
   return b;
}

But there is even more to it, in a larger software project, it becomes necessary to keep track of what data is dependent on what other data. Using contemporary methods, this is done through either simple callbacks or so called ”hooks”, or more commonly using the observer pattern. In Java, the concept of ”listeners” is perhaps the most known application of the observer pattern. So we need an additional array to keep track of observers who needs to be notified when a certain blurred image of an array is updated. Thus, we need to encapsulate the blured array, together with a list of its observers.

C:

class BlurredArray {
   int[] array
   BlurredArrayObserver[] observers 

   blur(int[] a) {
      int[a.length] b;
      blur(a, array, 0, b.length);
   }

   blur(int[] a, int[] b, int intervalStart, int intervalEnd) {
      if (intervalStart == 0) {
          b[0] = 0.75*a[0] + 0.25*a[1];
          intervalStart++;
      }

      if (intervalStart == b.length - 1) {
         b[a.length - 1] = 0.75*a[a.length - 1] + 0.25*a[a.length - 2];
         intervalEnd--;
      }
      for(int i=intervalStart, i + 1 < intervalEnd) b[i] = 0.25*a[i-1] + 0.5*a[i] + 0.25*a[i+1];
      return b;

      for(observer in observers)
         observer.notify()
   }
}

We now have a program that notify the observers when the blurred array is finished or updated. But even that is not the end to it, as it turns out that more often than not, chains of observers in a complex program will often form general directional acyclic graphs, often called DAG:s. Since the naive propagation of an event through a DAG might give cause to exponential computational complexity, it becomes necessary to gurad against this using a commonly seen invalidate/validate pattern. So in the end our simple program might look something like this:

D:

class BlurredArray {
   IntArray source
   IntArray array
   BlurredArrayObserver[] observers
   int invalidStart
   int invalidEnd

   constructor(IntArray source) {
      array = IntArray.new(source.length)
      invalidEnd = array.length
      invalidStart = 0
   }

   invalidate(int a, int b) {
      invalidStart = min(a)
      invalidEnd = max(b + 1)
      for (observer in observers) {
         observer.blurredArrayInvalidated(this);
      }
   }

   isValid() {
      invalidStart == -1 and invalidEnd == -1
   }

   get() {
      if (!isValid()) revalidate();
      return array;
   }

   revalidate() {
      blur(source, array, invalidStart, invalidEnd)
   }

   blur(IntArray a, IntArray b, int intervalStart, int intervalEnd) {
      if (intervalStart == 0) {
          b[0] = 0.75*a[0] + 0.25*a[1];
          intervalStart++;
      }

      if (intervalStart == b.length - 1) {
         b[a.length - 1] = 0.75*a[a.length - 1] + 0.25*a[a.length - 2];
         intervalEnd--;
      }
      for(int i=intervalStart, i + 1 < intervalEnd) b[i] = 0.25*a[i-1] + 0.5*a[i] + 0.25*a[i+1];
   }
}

We can also note that two additional design decisions arise for C and D, namley the granularity of observation, and the granularity of invalidation. For example, when we invalidate the array, do we invalidate only a specified interval as shown above, or do we simply invalidate the whole array all the time. As a contrast projection programming opens up a possibility of dealing with this tradeof in a more automatic way through settings in the compiler, separatley from the programming process.

So, what we have seen here is how a simple program of 7 lines of had to be expanded to 46 lines of code to take change propagation into account, using the current state of the art. This is an increase of roughly 550%, a lot of mud for burying the diamond!

In addition, can you see at a glance if I introduced any errors in the last steps? Actually, I do not know either, because the complexity of the program has increased substantially by the introduction of an validation state, and in general such a program will require testing in order to find out if there are any errors, for example using test driven development (TDD). Just think about how many bugs exist in programs today because data was updated in the wrong way. This is in part a reason for the typical ”if all fails restart” mentality that even the end users has gotten used to. Projection programmign will eliminate at least some of that state management, an possibly help producing more stable software for the end users.

What is projection programming?

Unfortunatley, no one can be told what projection programming is, you have to see it with your own eyes.

Let us continue the example from the previous section, and see what it would turn out using projection programming. In projection programming, a programming language construct called ”project” is used to create a projection out of a function call or any programming expression. A Projection object is then created to allow first class manipulation of the projection.

E:

...
Projection p = project blur(a);
...

blur(int[] a) {
   int[a.length] b;
   b[0] = 0.75*a[0] + 0.25*a[1];
   for(int i=1, i + 1 < a.length) b[i] = 0.25*a[i-1] + 0.5*a[i] + 0.25*a[i+1];
   b[a.length - 1] = 0.75*a[a.length - 1] + 0.25*a[a.length - 2];
   return b;
}

When the code outside the projection modifies the projection input, the projection is automatically updated, or at least whatever part of the projection that is actually used. Hence, the projection programming equivalent of D would be about the size of A, saving 85% of the code. Here is an image of E when run. The red shows an example of when a certain input data gets updated, and how the change can propagate.

Some other experiments supports that this is somewhat representative of what order of improvement that is to be expected from projection programming in the described problem domain. I made another test program, a kind of WYSIWYG editor, of over 1000 lines of code. Its PP equivalent ended up beeing 70% smaller. More importantly, those extra 70-85% that projection programming has removed, will generally deal with maintainting a state used for change propagation, and is therefore inherently hard to debug.

For anyone developing software, a 70-80% reduction of the code base could translate directly into tremendous savings on software development costs. So this is what is at stake, and this is why it could be important to pursue projection programming.

The projection tree

This section will go deeper into the semantics of projections, and how they interact with the ordinary imperative world that exists outside the projections, this is just as a preparation for the next section where we describe how projection programming will be used in practice for larger projects.

Projections can be related to each other in two ways, either through procedence or through containment. Both these relations form trees.

Precedence is used to determine what projection is before another projection, and such a relation is required whenever the projections manipulate or access the same data. Note that the procedence relation is allowed to branch out as a tree, but is not allowed to form general DAGs, as there is no way to automatically merge the effects of two projections possibly operating on the same data (but since projections are treated as first class objects that can be copied, mergeing models should not be that difficoult). In effect, the precedence relation is only allowed to branch out on the top level.

In cases when the projection abstraction is used to build version systems, merges has to be created explicitly by some algorithm and stored in the projection tree. The root of the precedence tree is allways the ”imperative projection” which is only used to store all data that is the result of manipulations in the imperative world.

Sometimes code run in the imperative world can manipulate the projection tree itself wich causes data manipulation to happen at some stage in the projection tree, but that kind of manipulation is always indirect, and allways occur either through direct manipulation of Projection objects, or through the use of the ”projection” keyword in order to create new projections, or through some combination thereof.

The containment relation is pretty straight forward, and is used to create compound projections. For example, a compound projection can consist out of a number of smaller projections that execute in some order. The execution tree of a projection can be seen as a compound projection.

So, essentially, it is possible to take any ordinary programming langauge, imperative or functional, or create its projection programming counterpart by simply adding the projection keyword, the projection tree concept and an object model of it. This creates a new programming language of tremendous powers in terms of expressiveness. This means that even though projection programming is a novel idea, it does not need very much special training.

Projection programming in the large

So how is PP intended to be used? To create a larger PP application, the main display would typically run as one large projection, and the event loop would mainly run outside the projection.

This also shows how the time of the projected function call is used explicitly. More specifically we can consider selection/navigation time and the model build time. When an event is triggered by some widget, new code is executed in the model build time to make modifications to the data model, or in the selection time inside the projection to modify the user interface state. To execute projections inside some other projection, there is another keword namley ”project … in”. When the event dispatch is finished, and the  event code starts to really do something, it would typically use this combination to place a new projection under a certain place in the projection hierarchy. This is about how it would look like:

class Checkbox {
   ...
   Boolean model;
   Projection modelBuildTime;
   ...
   void onClick(boolean newValue) {
      project { model.setValue(newValue) } in modelBuildTime;   // Insert last in model build time
   }
   ...
}

class Boolean {
   boolean value;
}

This shows how the ordinary imperative code is used to inject tiny projections into the larger projection tree of the application.

We can also note that the model class ”Boolean” is completley free of any observer patterns etc, even if there are more than one checkbox linked to that particular model. This is because the projection programming paradigm will automatically update all projections that depend on a certain model. For example, we can easily change so that every checkbox in the system that is checked, is slightly larger than an uchecked box. Even though this decision is made in the constructor of the checkbox, the check box need no other code to update this choice when the model changes. It is as if the checkbox is constructed over again automatically if the model changes.

class Checkbox {
   int size;
   ...
   constructor(Boolean model, Projection modelBuildTime) {
      this.model = model;
      this.modelBuildTime = modelBuildTime;

      size = (model.value) ? 14 : 10; // This is the only place we have to make this decision. Updates are taken care of.
   }
}

This is just to show how easy the implementation of interactive changes becomes in projection programming. If this would be done in an ordinary OOP setting, you would have to modify the size every time the check box is checked, and then propagate this change to some widget parent to possibly redo some layout work now that the size has changed.  There are a number of potential ways in which this could go wrong.

But there is also a bonus to projection programming that is not only about creating the user interface. If we create the underlying data model inside the main projection, we can also get undo systems or version systems for free as shown in the application setup shema.

Update progress

There are some more things that we might need. As it turns out that user interfaces in general has high demands on responsiveness, it might not be possible for the evaluation model to update the entire application projection at once given some larger change. Therefore it is necessary for the programmer to somehow be able to express what parts of the execution tree that needs update first. For example, in a word processor it is customary that the spell-checking lags behind to some degree, or in a IDE that the background compilation might not allways be in synch with the users editing. There are several possible ways of doing this, but one simple way to do this on the langauge level is to add the keywords ”slow” and ”fast” that can be used together with ”project”. If none of these two keywords are used, the update priority is assumed to be ”average”. This gives the user 3 different priority levels to play with. These could for exampel be used for

1. Rendering of carets and highlights etc.
2. Advanced formatting.
3. Background processes such as spellchecking or compiling

When a slow projection is updating, there are a number of ways it could be dealt with depending on what is most efficient. Preferably an update that propagates a slow projection would finish completley, before the faster projection is notified of this change and is able to view the data modified by the slow projection.

Another thing is that the projection objects might need to export some data about its update progress. This way it would be possible to display various animations that indicate progress, such as task-bars or spinning time-glasses. In general, computation progress is a tricky subject, and even for the imperative parts of the program, it could be helpful if the programming language had some built in support for dealing with it.

Optimization and feasibility

So is it possible to reduce the memory requirements, making projection programming feasible given todays hardware? We will now just briefly look at the basic principle of how to optimize the memory usage and execution time of projection programing. The point of this section is not to provide a finished methodology of how to optimize the memory footprint of a projection, but rather just to show that it would be possible to find such methodology.

There are two basic methods to save memory usage for the execution model of projection programming. The first is to fold the execution tree, and the second is to fold data. Folding of data depends on identifying certain groups of variables that are allways updated together. This means we do not need to store invalidation revalidation data for both of these variables.

Folding of the computation works as follows. The idea is to identify certain parts of the data flow and execution tree that are beneficial to fold. This means that this part of the computation is not in particular efficient to store explicitly, so instead that part of the code is executed using standard imperative methods every time the destination data is required while the source data has been updated. Folding is typically beneficial when the source data for a certain computation is not parallell. For example, a call to a factorial function would typically be folded, because it only takes one integer as an input, but produces a lot of inermediary steps during the computation. Another example is the call to a function that takes an integer n, and then produces a list with the n first prime numbers. In general, when the data flow expands it is good to fold. If the amount of parallism is small, as defined by the previously mentioned article about parallellism, it might also be a good idea to fold.

If we futher want to assess the feasibility of projection programming, we should consider the following facts:

1. It would be wrong to assume that the memory consumption of an projection program version PP(P) of program P would be the same as applying version handling on Ps memmory usage. This is because P most likley contains a lot of data structures which are related to change propagation, and that can simply be omitted in PP(P).

2. It can be noted that memmory allocations that occur inside a projection and are not visible outside the projection can be dealt with without any need for traditional garbage collection. For such memmory allocations, safe automatic deallocation becomes possible.

3. Giving the compiler responsibility for change proapagation is to trade human expertise for automation, and although an automated approach might fail to take advantage of certain possibilities of optimization, an automated approach might also avoid certain human errors or neglect that needlessly waste memory. In particular excessive invalidation of data structures is one such error.

4. Even though projection programming would eventually turn out expensive in terms of memory usage, it does not automatically mean it does not have any usage. There was for example a time when function calls with its corresponding stack frame management was considered too expensive in comparison to simple program pointer manipulation. Garbage collection was at a time considered wasteful compared to manual memory management. The lession learned from looking at the history is as follows:

a) Hardware capabilities will steadily increase.

b) There will allways exist certain limited domanis where the benefits of a new technology
will outweight the increased cost in terms of memory.

c) At some given time, certain tresholds will be reached which enables new technology to be used on a broader scale.

5. Last but not least, it is more and more evident that the word is moving towards a multi-core / multi-processor paradigm, and even if projection programming has certain overhead costs, it might turn out to be more efficient in exploiting multi-core prorcessors or parallell computers. This is because the execution tree effectivley exposes any parallellism there might be in any program, which could be used by a scheduler. However, as the data flow exposed is to some degree dynamic and could rearange itself as an effect of update, createing a core schedulation sheme for projection programming opens up an entirely new field of research that could keep many PhD:s busy for a long time.

But in the end, there are of course no guarantees when developing something new like this.

Enabling the future

I would like to empasize that projection programming could have a huge importance for the future of software development in more than one ways. It does not only make it easier to create certain softare with a lot of interactivity and incremental algorithms, such as mentioned before. Because our software development tools such as Eclipse or Visual Studio are themselves pieces of interactive software, projection programming could be used to create our next generation programming tools, and therefore help advance software development on a broader scale. And this was actually the task I set out to do when I started this journey many years ago.

For example, with projection programming as a base, it would be a simple thing to create a debugging feature that could visualize the execution tree of a projection, allowing the programmer to browse both back and forward in the execution tree without the necessitiy of breakpoints. But perhaps the most important aspect of this is that it will enable very sophisticated structure editing that could finally make the standard text format for code obsolete. This means that code will no longer be manged as text-files, but as object structures. It would then be very easy to combine text with graphics that serve as an integrated part of the code, and it would be easy to hide excessive information in the code structures, and improve code navigation immensley. Maybe this is what projection programming is really all about in the end.

So, what about the silver bullet?

Many people in computer sience like to recite the ”no silver bullet” paper, as to express a certain skepticism against anyone trying to finde the ultimate solution for programming that will solve every problem. A ”silver bullet” that magically kills all enemies is used as the given methaphore. But as we have seen, projection programming if realized could potentially be tremendously powerful, completley vaporizing certain obstacles, and potentially reducing some code bases by up to 70%. So, it would be natural if some people believe it too good to be true.

But in that case, let us look realistically at projection programming. Projection programming is not a silver bullet in the sense that it automatically will solve all problems. There will still be a need to invent algorithms that produce a certain result given a certain complexity. Projection programming will not make that task in itself any easier. Projection problem will just solve the updating problem, and a number of other issues related to version control and undo. What this could do, is only to relieve the programmer of this burden, so he or she can focus on other problems at hand, such as the algorithms.

Using this balistic metaphore, it is more close to think of projection programming as a machine gun. In comparison to an ordinary single shot handgun, a machine gun will use an order of magnitude more bullets just ”to get the job done”. This is very similar to how projection programming potentially uses an order of magnitude more memory resources, in order to drastically reduce the effort required by the programmer. In some cases, this could be what counts in the end.

Nothing new under the sun

So, is this a new idea? For this specific purpose, with this specific concept of projections using an ordinary programming language as a base? It is hard to tell. At least I have never heard of it before.

But for sure there are areas of computer science that deal with incremental change propagation in general, for example functional reactive programming and incremental computing. Although I have never seen the idea to create reactive programming out of an imperative program. There also exists numerous of reasearch on how to exploit the parallellism of ordinary imperative programs, but the purpose in this case is most likley to increase the performance by taking advantage of parallell computing, and not to simplify the work for the programmer by making incremental change propagation implicit.

One reason why perhaps projection programming has not been explored yet for this particular purpose, is because of it’s contraintuitive nature. Normally programmers are trained to save memory, not to assume that every computation is stored automatically, or at least create the illusion thereof. It took me at least 6 years to break down any mental barriers I might have had about doing this. Every time I tried to create an automatic change propagation model that would work well together with ordinary OOP from a programmers point of view, I had to surrender and accept a little bit more change propagation data stored in the execution model. Should change propagation be managed on object level? For a long time I thought I could get away by modelling change propagation on the class member level, until I eventually realized that change propagation needs to be a part of essentially all computing that is done inside some limited scope that later came to be called the ”projection”. It is also contra intuitive with an approach that instead of explicitly dealing with change propagation, uses a more implicit way of dealing with it.

Outlook

So, will we see any projection programming language anytime soon? Well, even as mentioned, PP can save at least 70% of the work effort on some very standard programming tasks, it is not very certain that we will see any development soon. There are several reasons for this.

Maybe the most important reason is how our industry is organized. As Bjarne Stroustrup, creator of C++ puts it ”no one has ever made any money from a programming language”. And this is perhaps one of the first obstacles. Developing a new programming language including all the necessary tools is not a cheap process, and I doubt that any company would spend any effort on this unless their competitors do it first, which creates a kind of ”catch 22”. To put it another way: We live in a debt based monetary system enslaving the entire population anyway, and there are a lot of slaves to go around for the elite. Improving worker efficiency might not be the topmost concern in this age off neo-feudalism we live in.

As for the academia, some programming langauges can evolve in the scientific community before they become generally useful, but as far as I know PP is not anything that is currently beeing studied in any university.

So, maybe the best thing to hope for that some enthusiasts in the general web-community will pick up this idea and start to produce some interesting things. Last but maybe not least I am also working on a PP platform myself, but there is no telling when or if my project will result in anything concrete.

So, this was my testimonial. The result of my 6 years wrestling certain problems, which I give away here for free. I hope it could serve as a source of inspiration for someone reading this. Next time I write about computer science in my blog I have some things to say about type systems, and object orientation in general. Stay tuned!

And remember, there is no spoon!

3 svar to 'Projection programming, the future of software development?'

Subscribe to comments with RSS eller TrackBack to 'Projection programming, the future of software development?'.

  1. joasi said,

    Interresting, though I didn’t fully understand it on the first read.
    To Charles Simonyi however I would reply:

    ”’Programming is the opposite of dimond mining. When mining for diamonds, you start out with a lot of mud, and you dig out the diamonds. In programming, you start with a crisp and clear idea, and then bury it in the implementation details.’” – ”And the you use refactoring to clear the mud off and shape the diamond into a brilliant.”

    I wonder what the code he produced looked like??

    I have also wrestled with the question of how to produce responsive GUI’s more efficiently and my answer so far is to create a domain specific declarative language where all relationships and logic are stated in a timless manner and then to generate traditional oop code from that.


    • Thanks for taking the time to understand this! :-)…

      About mud, I think it would be fair to say that all of our programs exist out of mud sometimes, even if we are unaware of it. This is because we sometimes cannot comprehend any more efficient way to express a certain thing, even if we at a later stage find a way to do so. The observer pattern is the example of this in this article.

      I would think of it more as if we smear the mud around, to produce a nice dimond shaped sculpture, with the real diamond inside. A little bit like the japanese art dorodango where you start out with a handful of mud, and produce a shiny sphere.

      I think that PP could be seen as a ”cheap” way to express timless relations, without the need for any additional programming language constructs or domain specific languages. What happens is, that when you project an imperative program, you get a timeless description of its execution which in turn can be used to propagate change.


  2. It’s difficult to find experienced people about this topic, however, you sound like you know what you’re talking about!
    Thanks


Kommentera

Fyll i dina uppgifter nedan eller klicka på en ikon för att logga in:

WordPress.com Logo

Du kommenterar med ditt WordPress.com-konto. Logga ut / Ändra )

Twitter-bild

Du kommenterar med ditt Twitter-konto. Logga ut / Ändra )

Facebook-foto

Du kommenterar med ditt Facebook-konto. Logga ut / Ändra )

Google+ photo

Du kommenterar med ditt Google+-konto. Logga ut / Ändra )

Ansluter till %s


%d bloggare gillar detta: