December 31, 2009

Sand Mandalas and the Transitory Nature of Good Software

I once read a blog post by John Resig that exposed me to sand mandalas, which are a Tibetan Buddhist tradition where works of art are made out of colored sand. These mandalas are exquisite in detail, requiring weeks of effort by a team of monks. The most interesting part of the tradition, though, is that after the mandalas are finished and displayed, they are ceremonially destroyed. This destruction is meant "to symbolize the Buddhist doctrinal belief in the transitory nature of material life".

It floored me to think that such amazing art would ultimately be demolished, with the effort to create the art seemingly for naught. However, I think the spirit of the sand mandalas leads to a good lesson about programming. I sometimes become too attached to code that I've written, making me hesitant to change or remove it. But software should be transitory in nature. Good software results from constant refactoring, and unneeded code should be removed. Thus I should avoid becoming enamored with my original implementation and adopting a narrow-mindedness that ultimately harms the product I'm creating. Instead, I should be open to making changes when they result in a better design and more maintainable code. And though the effort to write my original code may seem like a waste, it really isn't, as it ultimately led me to better code.

December 27, 2009

C# Extension Methods For Ruby Integer Functions

I was wondering whether some of the integer functions in Ruby would be handy in C#, so I wrote a few extension methods for them. Thus you can write something like:

1.UpTo(5).Do(i =>
// do stuff like value = items[i];
// do more stuff with value
);

instead of:

for (var i = 1; i <= 5; i++)
{
// do stuff like value = items[i];
// do more stuff with value
}

There’s also:

10.DownTo(5).Do(i => ...);
3.Next();
5.Times(i => ... );

Not sure how useful these are, but if anything, the Times one is short yet expressive. I may end up using it.

The code and tests:
public static class RubyExtensions
{
public static UpToValues UpTo(this int start, int limit)
{
return new UpToValues { Start = start, Limit = limit };
}

public class UpToValues
{
public int Start { get; set; }
public int Limit { get; set; }
}

public static void Do(this UpToValues values, Action<int> block)
{
for (var i = values.Start; i <= values.Limit; i++)
{
block(i);
}
}

public static DownToValues DownTo(this int start, int limit)
{
return new DownToValues { Start = start, Limit = limit };
}

public class DownToValues
{
public int Start { get; set; }
public int Limit { get; set; }
}

public static void Do(this DownToValues values, Action<int> block)
{
for (var i = values.Start; i >= values.Limit; i--)
{
block(i);
}
}

public static void Times(this int value, Action<int> block)
{
for (var i = 0; i < value; i++)
{
block(i);
}
}

public static int Next(this int value)
{
return value + 1;
}
}


[TestFixture]
public class Tests
{
[Test]
public void UpToTest()
{
var result = 0;
1.UpTo(7).Do(i => result += 2);
Assert.AreEqual(14, result);
}

[Test]
public void UpToTest2()
{
var result = string.Empty;
5.UpTo(10).Do((i) => result += (i + " "));
Assert.AreEqual("5 6 7 8 9 10 ", result);
}

[Test]
public void DownToTest()
{
var result = 5;
10.DownTo(6).Do(i => result--);
Assert.AreEqual(0, result);
}

[Test]
public void DownToTest2()
{
var result = string.Empty;
5.DownTo(1).Do(i => result += (i + ".."));
Assert.AreEqual("5..4..3..2..1..", result);
}

[Test]
public void TimesTest()
{
var result = 0;
12.Times(i => result++);
Assert.AreEqual(12, result);
}

[Test]
public void TimesTest2()
{
var result = string.Empty;
5.Times(i => result += i);
Assert.AreEqual("01234", result);
}

[Test]
public void NextTest()
{
Assert.AreEqual(2, 1.Next());
Assert.AreEqual(0, (-1).Next());
Assert.AreEqual(-1, (-2).Next());
}
}

December 7, 2009

Design Thinking

I've been learning about design thinking and am excited to talk about what I've learned thus far, as I think it could be a great driver of organizational change and lead to a more innovative company. I've read two good books on the topic, The Design of Business by Roger L. Martin and Change By Design by Tim Brown, and the following summarizes some of the core concepts from these books.

Let me first start with a description of what Martin calls the "knowledge funnel", which is the process for advancing knowledge from an unsolved problem to an algorithm that is a fixed, repeatable solution to the problem. The first step in the funnel is the investigation of a mystery, where you're trying to gather a better understanding and more insight into a problem. This process of observation, critical thinking, and imagination leads to the next step in the funnel, where you develop a heuristic to explain the mystery. This heuristic is just a general explanation of the problem. It's an incomplete understanding but definitely reflects a deeper, more advanced understanding of the problem and its potential solutions. The heuristic also leads to a narrowed exploration of the problem, as you're only focusing on the parts you've deemed essential. The heuristic then guides you to the final phase of the knowledge funnel, the creation of an algorithm. An algorithm is a defined process for solving the problem. It simplifies the complexities of the problem and allows you to repeatedly solve it in a verifiable manner. Thus the company that drives a problem through the knowledge funnel from mystery to algorithm not only benefits from the development of products or services that address a heretofore unsolved problem but also benefits from substantial gains in efficiency.

However, you can't just advance knowledge through the funnel. A company must also effectively operate within each step in the funnel and iteratively sharpen and improve their heuristics and algorithms in order to reap the greatest benefit from their knowledge-refining efforts. Thus an organization should have two focuses. Once focus is what Martin calls the "invention of business", whose goal is the advancement of knowledge through the funnel. This approach applies intuitive thinking, favoring gut feelings, creativity, and originality. The other focus is what Martin calls the "administration of business", whose goal is to exploit the existing gathered knowledge for maximum profit. This focus relies on analytical thinking, emphasizing quantitative analysis and the removal of bias and subjectivity from decision making. Intuition and hunches are avoided in favor of measurability, predictability, and ultimately reliability.

To no surprise, analytical thinking is the overwhelmingly predominant form of current organizational thought. After developing a heuristic or algorithm that grants them a competitive advantage, many companies focus solely on exploiting this heuristic or algorithm and no longer concern themselves with advancing more knowledge through the funnel. Unfortunately, this complacency in leveraging existing knowledge and aversion to supporting initiatives that can't be measured and reliably predicted exposes them to competitors willing to develop new heuristics and algorithms. Thus design thinking tries to solve this dilemma by seeking a balance between the analytical world that uses data and past events to drive decision making and the intuitive world that is more creative in nature but rife with uncertainty.

Design thinking is a different approach to product development. It first frames a problem in the form of a question (such as "How can we...?") and then intensely explores possible answers to the question until arriving at a feasible solution. It's an iterative process where ideas are constantly refined and optimized, yet there's still room (and a willingness) to sometimes veer and explore different directions. Design thinking involves actively observing and inquiring about the world around you to identify solutions to problems that people have a hard time articulating or may not even realize they have. It's a very human-centered approach, marrying what people desire with what is technically and commercially viable. It's also holistic in nature. Instead of stopping once a new product or service is created, design thinking strives to deliver the best possible end-to-end customer experience, so even things like the marketing and distribution of a product are critically examined for enhancements.

So on the one hand, design thinking ensures that ideas are continually advanced through the knowledge funnel. However, design thinking also stresses practicality. It doesn't involve the exploration and exploitation of any and all ideas, nor does it encourage solutions that are aesthetically pleasing but have little use. The problems that design thinking attempts to solve have defined boundaries around them. In fact, in his book Tim Brown mentions three core constraints that are used to evaluate how successful an idea is: "feasibility (what is functionally possible within the foreseeable future); viability (what is likely to become part of a sustainable business model); and desirability (what makes sense to people and for people)." Thus design thinking provides a way to quantitatively monitor a project, so it also ensures that innovations are being appropriately exploited as they advance through the knowledge funnel.

For these reasons, design thinking should be applied to at least a certain degree within every organization. However, you can't strictly rely on a team of designers and other "creatives" to utilize this mode of thinking. A company must instill design thinking within all its employees in order to truly leverage its advantages. Companies like Proctor & Gamble, Herman Miller, and RIM have done so, resulting in the creation of several innovative products. Thus I'm anxious to learn more about design thinking and find ways to adopt it within my company, in hopes that it will lead to a culture of innovation and the creation of products that overwhelmingly please customers. I encourage you to read the two abovementioned books, and let me know your thoughts on design thinking and its applicability to the software industry.