So far, I have covered two important aspects of software design that will impact how this software will evolve into the future. A brief recap:

Evolvability. When developing software, you are fighting a battle against the combinatorial mathematics that govern the complexity of any respectably sized software project. There are simply a huge number of possible approaches. Most of these approaches do not work. Of those that do, some will be better, either in terms of security, performance, maintainability, etc. Genetic algorithms are a special case of this - this is a technique for rapidly covering a problem domain without investing the man hours to actually code each separate solution, and may take approaches that seem completely non-obvious to the developer, but are in fact preferable to the straightforward approach that a human would apply to that problem. However, even if using a genetic algorithm to crawl your problem domain is not practical, there are lessons to be learned from the implementation of evolution in biology. For example, it is a bad thing when modification of a gene at locus A confers some evolutionary advantage, but simultaneously presents a phenotype that is negative. The same is true for software. At a granuar level, object oriented programming helps to solve this problem. At a higher level, there are architectural approaches that make this easier. What is important is the underlying ideal.

Parallelism. There is no question in my mind that massively parallel algorithms are going to be key to success in the future, even more so than they are today. Being able to design systems that are massively parallel will not only allow your software to take advantage of hardware designs that increase computation capabilities through parallelism, but they present a whole new set of opportunities to interact with external processes and services in a way that is non-blocking and more intuitive. Why should I wait for my email client to check email before I can read email that I have already downloaded?

On top of this, I would add a third category, which does not have as direct a biologial analogy as the others, but is nonetheless extremely critical.

User Experience.

From user experience, I am thinking of two perspectives. The first is the overall appearance, which is how we frequently think of UI Design. Given a particular screenshot, implement this in code. Why is this experience important? Here, we are trying to convey a sense of quality, and drive a strong initial first impression. Depending on the software you are creating, this may be more or less critical. Some software is of the nature that people have to use it because there is no real competition, or who make up for this first impression with solid interaction design. But I believe it also drives how you feel about using the application. Does it feel modern? This may make me more excited about using it. Does it feel of high quality? This will make me trust the software more.

Windows Media Player 11 UI Design

The value of this experience is important, which is why screenshots are actually interesting to post on new products.

The next perspective is of user experience, or interaction design, which is different from that I am calling UI Design. Are you able to get your work done in a more efficient manner? Are your options exposed to you in a way that you can discover them? Is the act of navigating the appliation effortless and logical? For example, consider that we are designig a VCR. Rather than sending one group away to develop a list of features (such as multiple timed recordings, playback, and manual recording) and another to design the appearance of the device itself, can we approach it differently and design it first from the perspective of interaction? Yes. We can think in terms of scenarios. One important scenario is setting the clock so it is not flashig 12:00 indefinitely! Another is the scenario where somebody wants to record what they are currently watching. The final scenario is one where we want to set up several programs to record on an ongoing basis. Given these scenarios, we can start to explore them more thoroughly. We would like to understand why so many VCRs blink 12:00 all of the time. Can we solve the first scenario more easily? Is there a time source accessible to our VCR that doesn't involve the human at all? If it must involve a human, can we design it as part of the setup experience, understanding that nobody is interested in having a flashing 12:00 sign? But if we make it part of the setup experience, now we are preventing people from using their new VCR to play a video tape right away, until they answer a bunch of our questions - should we postpone that experience until the user requests it? If we do, how to we expose a way to do it at the user's convenience? Do we expose a hardware button? Do we post a notification that can go away? We haven't even exhausted our set of questions about the first scenario, and already we have to make some difficult decisions. However, this is time well spent, as this affect everyone who uses the VCR.

As I continue to evolve my blog, these are the three areas that I have run into time and time again as being important skills for the software practicioner (including myself!) both today and going into the future. To solve the hard problems that await us, we need to be able to search the problem domain more efficiently. We need to support parallelism, which will be supported more and more completely in hardware as time passes. And we need to provide a positive user experience that is focussed on fulfilling users' goals.