On Thu, Jul 28, 2011 at 2:16 PM, BGB <cr88...@gmail.com> wrote:

> striving for simplicity can also help, but even simplicity can have costs:
> sometimes, simplicity in one place may lead to much higher complexity
>
somewhere else. [...]
>
it is better to try to find a simple way to handle issues, rather than try
> to

sweep them under the carpet or try to push them somewhere else.


I like to call this the difference between 'simple' and 'simplistic'. It is
unfortunate that it is so easy to strive for the former and achieve the
latter.

* Simple is better than complex.
* Complex is better than complicated.
* Complicated is better than simplistic.

The key is that 'simple' must still capture the essential difficulty and
complexity of a problem. There really is a limit for 'as simple as
possible', and if you breach it you get 'simplistic', which shifts
uncaptured complexity unto each client of the model.

We can conclude some interesting properties: First, you cannot achieve
'simplicity' without knowing your problem or requirements very precisely.
Second, the difference between simple and simplistic only becomes visible
for a model, framework, or API when it is shared and scaled to multiple
clients and use cases (this allows you to see repetition of the uncaptured
complexity).

I first made these observations in early 2004, and developed a
methodological approach to achieving simplicity:
(1) Take a set of requirements.
(2) Generate a model that *barely* covers them, precisely as possible. (This
will be simplistic.)
(3) Explore the model with multiple use-cases, especially at large scales.
(Developer stories. Pseudocode.)
(4) Identify repetitions, boiler-plate, any stumbling blocks.
(5) Distill a new set of requirements. (Not monotonic.)
(6) Rinse, wash, repeat until I fail to make discernible progress for a long
while.
(7) At the end, generate a model that *barely* overshoots the requirements.

This methodology works on the simple principle: it's easier to recognize
'simplistic' than 'not quite as simple as possible'. All you need to do is
scale the problem (in as many dimensions as possible) and simplistic hops
right out of the picture and slaps you in the face.

By comparison, unnecessary complexity or power will lurk, invisible to our
preconceptions and perspectives - sometimes as a glass ceiling, sometimes as
an eroding force, sometimes as brittleness - but always causing scalability
issues that don't seem obvious. Most people who live in the model won't even
see there is a problem, just 'the way things are', just Blub. The only way
to recognize unnecessary power or complexity is to find a simpler way.

So, when initially developing a model, it's better to start simplistic and
work towards simple. When you're done, at the very edges, add just enough
power, with constrained access, to cover the cases you did not foresee (e.g.
Turing-complete only at the toplevel, or only with a special object
capability). After all, complicated but sufficient *is* better than
simplistic or insufficient.

I've been repeating this for 7 years now. My model was seeded
in 2003 October with the question: *"What would it take to build the
cyber-world envisioned in Neal Stephenson's Snow Crash?" *At that time, I
had no interest in language design, but that quickly changed after
distilling some requirements. I took a bunch of post-grad courses related to
language design, compilers, distributed systems, and survivable networking.
Of course, my original refinement model didn't really account for
inspiration on the way. I've since become interested in command-and-control
and data-fusion, which now has a major influence on my model. A requirement
discovered in 2010 March led to my current programming model, Reactive
Demand Programming, which has been further refined: temporal semantics were
added initially to support precise multimedia synchronization in a
distributed system, my temporal semantics have been refined to support
anticipation (which is useful for ad-hoc coordination, smooth animation,
event detection), and my state model was refined twice to support
anticipation (via the temporal semantics) and live programming.

I *had* to develop a methodological approach to simplicity, because the
problem I so gleefully attacked is much, much bigger than I am. (Still is.
Besides developing RDP, I've also studied interactive fiction, modular
simulations, the accessibility issues for blind access to the virtual world,
the possibility of CSS-like transforms on 3D structures, and so on. I have a
potentially powerful idea involving multi-agent generative grammars for
intelligent controlled creativity and stability in a shared, federated
world. I doubt I'll finish *any* of that on my own, except maybe the
generative grammars bit.)

Most developers are clever, but lack perspective. Their eyes and noses are
close to a problem, focused on a local problem and code-smells. When they
build atop a *powerful* substrate - such as OOP or monads - composition and
integration issues are opaque to them. A common consequence is that their
algorithms or DSLs are *simplistic*: they work okay for *a specific* program
or example, but they are difficult to integrate in a new context.

*Too much power with too little perspective - that is the problem.*
*
*
Developers have recognized this problem, at least implicitly, and so they
build frameworks. A framework is an ad-hoc, slow, informally specified,
bug-ridden language that is, critically, more constrained than full OOP. The
idea is that we write code in the context of a framework, and the
constraints imposed on us help with integration. Unfortunately, most
frameworks are simplistic, built too close to a problem, and do not
integrate nicely with other systems and frameworks. A common consequence is
that developers spend more time working around a framework, or adapting
between frameworks, than working within them.

Still, the goal of frameworks is noble. Just, to make them work, we must
start with a large set of diverse problems across many domains, and at
enormous scales... millions of developers, integrating thousands of DSLs or
frameworks. We need a general framework programming language, one that
ensures a large number of compositional properties - most critically, those
useful for system integration. This is, in a sense, what my RDP attempts to
be. My pursuit of *reactive* programming stems from this requirement
directly: if we have reactivity, then abstracting or composing a framework
is little different than abstracting or composing any other object.

Some people question the value of simplicity. They think complicated is
'good enough'. But these people don't understand that simplicity opens doors
that we never realized were closed, raises glass ceilings we didn't realize
we were struggling against, and removes performance barriers that we wrongly
assumed to be a natural part of our environment (wow! who knew there was a
racetrack under all this debris?). A subtle qualitative difference in our
abstractions can make huge quantitative and qualitative differences in our
emergent systems. Pursuit of simplicity, at scale, tells us just how
ineffective and unscalable our systems are today... and offers great hope
and optimism for tomorrow.

Regards,

Dave
_______________________________________________
fonc mailing list
fonc@vpri.org
http://vpri.org/mailman/listinfo/fonc

Reply via email to