
Programming Languages are the Least Usable, but Most Powerful User Interfaces - newgame
http://blogs.uw.edu/ajko/2014/03/25/programming-languages-are-the-least-usable-but-most-powerful-human-computer-interfaces-ever-invented/
======
AdrianRossouw
Yeah. I've come to realize that the hard way.

It is also what it comes down to w.r.t. code-over-config.

To make a system sufficiently configurable, you end up having to re-invent a
turing complete language inside it's configuration files, so it starts looking
more like lisp.

This is due to the [1] Inner Platform effect.

The only interfaces I know of that's expressive enough to drive a turing
complete language is either flowcharts, or actual code.

This is kind of why I feel that systems like gulp are just superior to grunt,
because ultimately the config format can never be expressive enough to solve
all the problems, and there's just so much less work to write-what-you-mean,
the first time. properly.

This also relates my newly adopted philosophy w.r.t. software complexity. [2]
Simple vs Easy.

[1] - [http://en.wikipedia.org/wiki/Inner-
platform_effect](http://en.wikipedia.org/wiki/Inner-platform_effect)

[2] - [http://daemon.co.za/2014/03/simple-and-easy-vocabulary-to-
de...](http://daemon.co.za/2014/03/simple-and-easy-vocabulary-to-describe-
software-complexity)

~~~
ericHosick
> To make a system sufficiently configurable, you end up having to re-invent a
> turing complete language inside it's configuration files...

Isn't source code basically a configuration file for the compiler/interpreter?

> because ultimately the config format can never be expressive enough to solve
> all the problems

And if so, I don't think this statement is quite true. Source code is
expressive enough.

Configuration files give us flexibility but not expressiveness. Source code,
as it exists today, gives us expressiveness but not flexibility[1].

This disparity should be a big red flag that we are doing something really
wrong.

This disparity, in my opinion, is caused by the abstraction we use to
communicate information between systems within source code: parameterized sub-
routines.

A programming language that doesn't use parameterized sub-routines is
basically a configuration file. This gives us both expressiveness and
flexibility.

[1] Flexibility is within the context of config-vs-source code and ops post.
Programming languages are very flexible when you know them.

~~~
Goladus
_Isn 't source code basically a configuration file for the
compiler/interpreter?_

Source code is input, not configuration. Every time you run the compiler, you
give it different source code. The whole point of the compiler is to transform
source code.

Configuration is "input" that is not expected to change very often, but that
the application developer can not guarantee will never change. Configuration
falls into a few categories:

1\. Context-specific inputs that can not be predicted or discovered
automatically by the application. (For example, the DNS zones the process is
expected to host - named.conf)

2\. Inputs that are not expected to change very often, but should be easy to
change if necessary. (ssh client or server settings)

3\. For applications with interactive user interfaces, customization and
changes to the default interface.

For the vast majority of applications, a text file capable of expressing
simple data structures is more than sufficient. Others advocate using only a
database, but only to make configuration dynamic so explicit reloads aren't
necessary, not to make it more like a programming language.

The source-vs-configuration question is usually only be an issue when dealing
with large, complex applications with very general specifications.

~~~
ericHosick
> Source code is input, not configuration. Every time you run the compiler,
> you give it different source code.

Interpreted languages (JIT) re-interpret the same source code every time they
are run (though they don't have to).

What about monkey patching
([http://en.wikipedia.org/wiki/Monkey_patch](http://en.wikipedia.org/wiki/Monkey_patch))?
An example usage is altering behavior (the source code) based on running the
code in a testing environment -vs- production (as one example).

How about dependency injection? How about lambda expressions?

What about best known practices like favor composition over inheritance? If we
hard code a solution using inheritance that is input but if we build out a
solution using composition that is a configuration?

These are all tools available to programmers that provide ways of changing
behavior at the source code level even though that behavior may not change
very often.

This is starting to look like a real gray area to me: input -vs-
configuration.

I guess we can try and distinguish between the types of input a system
consumes (based on the static nature of the input) but I don't know how useful
that is as an abstraction.

~~~
Goladus
Monkey patching is 3rd-party modification to the application itself; or
specially modified inputs that simulate such a modification. It's not
configuration.

Dependency injection is a software design pattern. There's no point calling it
configuration.

A lambda expression, from a programming perspective, is just an anonymous
function, a function so trivial it does not need an associated identifier.

    
    
        > If we hard code a solution using inheritance that is
        > input but if we build out a solution using composition 
        > that is a configuration?
    

No, a solution using composition is not configuration. Maybe it might help to
think of the intended audience:

Configuration is intended for end-users or system administrators, NOT
programmers. Configuration specifically refers to inputs that you _remove from
code_ and place somewhere that is (a) easily modified by anyone and (b) very
hard to break.

All of the tools or techniques you list are targeted at programmers (and
programmers doing programming, not configuring their text editor or IDE).

    
    
        > This is starting to look like a real gray area to me:
        > input -vs- configuration.
    

Of course it's a grey area. Configuration is ultimately a type of input. But
there's still a semantic distinction to make, just like there's a semantic
distinction between a desert and a grassland even though the border between
the two isn't distinct.

Also, I should make it clear there's an assumption we're talking about
application configuration, not configuration in the ITIL sense, where it has
an extremely generic meaning.

    
    
        > I guess we can try and distinguish between the types
        > of input a system consumes (based on the static nature 
        > of the input) but I don't know how useful that is as
        > an abstraction.
    

Primarily, the distinction informs decisions about how access to various
options and features are provided. Do you require the code itself to be
modified? Do you make it a compile-time flag? Do you have the application load
it from a default file in a standard location (like /etc/myapp.conf) or do you
read the input from stdin? It's possible to have a solid understanding of
where to put things without actually using the word "configuration" but why
not just use the term since it is already there?

~~~
kyllo
Code vs config is not _supposed_ to be a grey area, but it quickly becomes one
when you try to make the application so configurable that you're actually
moving business logic to the config files. That's why that is an anti-pattern.

~~~
Goladus
I upvoted your comment, but the reality is that the grey area is easy to find.

Consider apache's httpd.conf. It includes support for fairly advanced features
like conditionals, scopes, and sub-configuration of 3rd party modules. In some
environments, for example, it may be quite sensible to include some bits of
what might technically be considered "business logic" in something like URL
rewrites.

Consider DNS records. Not named.conf, but the actual zone data itself. Is that
configuration or is it data? Do you check zone files into a configuration
repository with your other files, or do you treat them more like a database to
be modified on the fly and just back it up periodically? It probably depends
on how dynamic the records are expected to be.

Consider emacs: it uses lisp as its configuration language.

On the other end of the scale, you have very small single-purpose scripts that
are easily hand-editable. If you have a script that's no more than 1K, maybe
you simply put an "options" section at the top with some defaults that can be
changed by modifying the code directly. Or maybe your script is so small that
even that amount of overhead is pointless.

It's important to remember that just because there is a grey area doesn't mean
that just because you might stuck there, everyone is. But it doesn't mean it
can't be confusing sometimes.

~~~
kyllo
Yeah, at a certain point you cross over from configuration into scripting.
Emacs Lisp is definitely in the scripting zone, on purpose.

Yes, Apache has a crazy amount of configuration in httpd.conf, and supports
conditionals and scopes, to the point where they had to write a syntax checker
for it. I would actually consider httpd.conf a good example of the
"softcoding" anti-pattern.

A certain amount of configuration is good, and deliberately providing a
scripting DSL language for your program is also good if appropriate.

But when you inadvertently cross over from normal configuration into absurdly
complex configuration that resembles a crappy scripting language, giving you
the feeling that you're in this big grey area between code and config, that's
an anti-pattern.

------
jasonwatkinspdx
I think it's a massively fascinating question to ask "Why didn't something
like hypercard become the web?"

And please don't knee jerk some story about some Apple decision making. That
doesn't matter. If the hypercard model had the value I think it does, someone
else should have surfaced and gained momentum.

That didn't happen, and while I don't have the answer for why, I think it
would shed some light on why "code as a user interface" for non coders has had
only limited successes (Spreadsheets, SQL).

~~~
toby
It's arguable that Excel is the most widely used "programming language"
depending on your definition. If you've spent much time around certain
business professionals, you'll see that they really push spreadsheets to do
unexpected things to solve their problems.

I've actually wondered why there hasn't been more exploration into visual /
declarative programming since it has the appeal of being very easy to get
started.

~~~
AdrianRossouw
> visual / declarative programming ... has the appeal of being very easy to
> get started

Does it, really? I spent the last 2 years building systems that ran off of
workflows (as in flowcharts), and I think now that they don't make the big
hurdle (capability for abstract reasoning) any easier at all.

They are fine to document and communicate things, but as input they are just
flawed (except for some very very specific niches).

~~~
ericHosick
> building systems that ran off of workflows (as in flowcharts) > but as input
> they are just flawed

The flaw is to assume there is only one mental model that Visual Programming
Languages should operate under: say only workflows for example (a mistake all
VPLs I've seen have done). This is like assuming that there should only be
object-oriented programming when there are other methodologies we use as
programmers to form mental models such as declarative programming, functional
programming, structured programming, etc.

It doesn't make much sense to code out mathematical equations using flow
charts.

A VPL which supports multiple mental models is able to best represent behavior
based on specific business domains. The right tool for the right job.

~~~
seanmcdirmid
Functional VPLs have the same abstraction/scaling up problems as OO VPLs. The
problem is that we (as human beings) don't know how to communicate very
efficiently without our words, and visual embellishment is not directly
useful.

~~~
ericHosick
> The problem is that we (as human beings) don't know how to communicate very
> efficiently without our words, and visual embellishment is not directly
> useful.

To me, this sounds like someone in the literary field of the arts telling an
artist or musician that those fields of the arts are not directly useful.

Music and art? Those visual (and aural) embellishments are not directly
useful.

There was a great HN post
([https://news.ycombinator.com/item?id=7543691](https://news.ycombinator.com/item?id=7543691))
on visually stunning math concepts. What you are implying is that coding out a
mathematical equation as opposed to representing it using actual equations
([http://i.livescience.com/images/i/000/036/119/original/minim...](http://i.livescience.com/images/i/000/036/119/original/minimal-
surface.jpg?1359485766)) is a visual embellishment that is not directly
useful?

> Functional VPLs have the same abstraction/scaling up problems as OO VPLs.

This could be a problem with VPLs or it could be a sign of some root cause
problem(s) with how we code today. Perhaps, there are better programming
abstractions/methodologies that work equally well as words (source code) and
as VPLs.

~~~
seanmcdirmid
I'm all for art and music, but can you converse with it? They obviously
communicate something that is quite different than "buy eggs on your way home
from work." Could you communicate this to your SO without using words, using a
picture or music? There is a good reason why pictionary is a challenging game.
And just as well, artists and musicians are probably not very interested in
communicating such utilitarian trivialities through the artifacts they create.
Art is not meant to be efficiently communicative, but to influence us in
other, perhaps deeper, ways.

> This could be a problem with VPLs or it could be a sign of some root cause
> problem(s) with how we code today. Perhaps, there are better programming
> abstractions/methodologies that work equally well as words (source code) and
> as VPLs.

The language center of our brains evolved 50-100 thousands of years ago, which
eventually led us to technology and civilization (things really pick up after
we discovered writing at about 10kya). The reason we use words for programming
is that we are biologically evolved for that. Are you seriously suggesting
that there might be a better way for us to communicate and express ourselves
concisely?

~~~
qbrass
>Art is not meant to be efficiently communicative, but to influence us in
other, perhaps deeper, ways.

[http://upload.wikimedia.org/wikipedia/commons/e/e2/OrteliusW...](http://upload.wikimedia.org/wikipedia/commons/e/e2/OrteliusWorldMap1570.jpg)

[http://upload.wikimedia.org/wikipedia/commons/thumb/5/5e/Joy...](http://upload.wikimedia.org/wikipedia/commons/thumb/5/5e/Joy_Oil_gas_station_blueprints.jpg/800px-
Joy_Oil_gas_station_blueprints.jpg)

[http://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/Exp...](http://upload.wikimedia.org/wikipedia/commons/thumb/f/f8/Exploded_view02.jpg/800px-
Exploded_view02.jpg)

[http://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Maq...](http://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Maqueta_turbina_hidroel%C3%A9ctrica.jpg/800px-
Maqueta_turbina_hidroel%C3%A9ctrica.jpg)

[http://upload.wikimedia.org/wikipedia/commons/2/2e/Radial_en...](http://upload.wikimedia.org/wikipedia/commons/2/2e/Radial_engine_large.gif)

~~~
seanmcdirmid
I see plenty of words there. Visual notation is great for conveying spatial
relationships, no doubt about that, and spatial layouts can work well as
secondary notational aspects, there is nothing to argue about there. But would
you want to read war and peace in dataflow diagram format?

~~~
qbrass
I'd read a story written as a dataflow diagram if it made good use of the
format.

War and Peace has been made into a movie at least half a dozen times.

~~~
seanmcdirmid
How about War and Peace performed by mimes?

------
skywhopper
Obviously there's lots of research to be done on the best ways to design
programming languages and the best ways to teach them.

However, the headline presumes there can be some universal standard of
measuring what we can "usability" that's somehow separate from the practical
"usefulness" of the tool itself. Tools that do fewer things can be made easier
to use that tools that do many things. Turing-complete programming languages
can be made to do anything the computer can do, which is a lot. And so there's
going to be a hard limit on how "usable" they can be. Not to say we're even
close to reaching that limit, but you'll never make a programming language
that's as "usable" as a screwdriver, and that's okay.

~~~
joe_the_user
Well, I'll admit that a rather debatable claim. But article provides
reasonably good backup for that claim using the tools of professional user
interface design, a field that has become a lot more systematic in recent
years. Towards the end of the article, he describes a number of metric which
can be used in measurement of programming languages as task-accomplishment
tools.

------
anon4
Reminds me of the different ways the environment is set up in Windows and
Linux. In Windows, when you want to edit your environment variables, there's a
simple configuration utility with a list of them, you click and edit and it
all takes effect immediately. In Linux, there's a chain of events where
different shell scripts are ran in some way at different levels of the bootup
process depending on strange and arcane factors, so when you edit ~/.profile
that only takes effect in your terminals and not in applications started by
the DE, but also not in tmux, because it's not sourced by ~/.bashrc somehow.
And once you puzzle out the chain of command and edit everything you have to
log out and back in. And when you want to make changes to the global
environment, there's /etc/environment, /etc/profile and
/etc/profile.d/yourscripthere.sh. Only one of these is the right choice but
only for a specific distro, DE and shell combination. Oh, and if somehow you
manage to source a script twice your PATH gets duplicate entries in it. Not
technically a problem, but it kind of irks me.

------
kingmanaz
The "glue-language" philosophy underlying Tcl can strike an optimal balance
between usability and power:

[http://www.yosefk.com/blog/i-cant-believe-im-praising-
tcl.ht...](http://www.yosefk.com/blog/i-cant-believe-im-praising-tcl.html)

Shells partition away sophistication.

~~~
AdrianRossouw
Tcl is actually really powerful and fun.

Everything is a string is a bit quirky, but it's just lisp-like enough to
allow you to do some really nifty things.

I don't ever want to write anything seriously in it again though, and I can't
see myself starting a new project with it.

~~~
pjmlp
I wrote many lines of Tcl back in the early .com days, as we had an in-house
server stack based on Apache, similar in certain ways to AOL Server, but doing
ORM stuff people only discovered a decade later with Ruby on Rails.

Only used a few times later to script Websphere via Jacl.

However, nowadays I don't have any reason to touch it as well.

------
joe_the_user
Wow, there are many ways to go with this...

I would claim that natural language is the most usable and the most powerful
user interface. We humans have been relating with it for quite a while and
there's no sign of a let-up.

And most programming language either contain fragments of natural natural
language or can be translated into such fragments. Yet, the author is right,
programming languages are "least usable". Indeed, consider SQL was created
specifically to be usable like a natural language but it now considered more
unusable than even an average programming language. What gives? (I have my
suspicions but I wonder what people think).

~~~
thaumasiotes
Utterances in any natural language are always ambiguous, often hopelessly so.
It works out because the speaker and listener are cooperating towards a shared
goal; the removal of this assumption of cooperation is why contracts and legal
codes get longer and longer over time as they try to deal with the fact that
they can't actually specify anything the way they'd like to.

The computer isn't like another person, and we'd really prefer to have it do
what we say rather than guess what we want and act accordingly. Indeed, we are
not yet able to have a computer guess what we want to any respectable
accuracy.

(Think of it this way. In some languages you can provide compiler hints that
say, for example, "this variable will usually be an integer, so please
optimize for that". A natural language consists basically 100% of compiler
hints and 0% of instructions.)

~~~
joe_the_user
_The computer isn 't like another person, and we'd really prefer to have it do
what we say rather than guess what we want and act accordingly._

From the point of a view of a programmer, yes.

But isn't this kind of the division point between a "good user interface" and
a programming language.

Lots of user level system _are_ intended so the computer guesses what you want
and does that.

------
nercury
Turing-complete config files do not sound like proper config files :)

~~~
davidgerard
It's an antipattern the inexperienced frequently fall into. Just one _little_
extra bit of functionality, and ... whoops! Suddenly, you _can_ program there,
so now you will _have to_ program there.

Same applies to markup languages. TimBL held HTML back from Turing-
completeness for ages, then JavaScript came along.

~~~
jt2190

      > ... whoops! Suddenly, you can program [in the
      > configuration files], so now you will have 
      > to program there.
    

What's forcing a user to configure a system if they don't need to make
changes? Why is it preferable to use something functionally restricted rather
than a programming language to configure a system?

~~~
AdrianRossouw
you need to develop the sense to know that just because something could be
made configurable doesnt mean it should be.

what software doesn't do is often as important as what it does do.

~~~
jt2190

      > you need to develop the sense to know that just because 
      > something could be made configurable doesnt mean it 
      > should be.
    

That doesn't explain why one shouldn't use a programming language when things
are configurable.

~~~
rm445
I'll take a stab at it, please feel free to critique.

All my reasons come down to complexity. Competing against our righteous need
to make software do cool stuff, is the fact that everyone writes software that
breaks all the time. Configuration that can perform arbitrary computation can
put our programs into literally any state, making it that much harder to make
them robust and correct.

It also opens up the risk that people won't configure their software correctly
because they don't understand the configuration. And it even opens up attack
vectors - what if there's a buffer overflow in your configuration interpreter,
or a resource link that lets configuration files do arbitrary things to a
system?

But I think one of the biggest risks is fragility. Configuration files that
can do arbitrary computation will be made to do so. Software that gets used by
lots of people will end up with towers of complexity built into the
configuration, to the point that removing or refactoring them risks bugs, edge
cases, or breaking a particular feature or misfeature that someone relies on.
Better to control the complexity in the first place.

~~~
jt2190

      > Configuration that can perform arbitrary computation can 
      > put our programs into literally any state...
    

Considering that it's generally a poor design that expose the full state of an
application to all parts of the same application (think: "global state"), then
yes, it holds that exposing the entire application state to the configuration
system is also a very poor design. I would think that if a user could set
three values via configuration, then those three values would be the only
state exposed.

    
    
      > It also opens up the risk that people won't configure 
      > their software correctly...
    

We can always find someone who can't configure the system, regardless of how
the configuration is done. If we're worried about making configuration
"safer", then the system should be more careful about what configuration
values it accepts i.e. implement robust validation.

    
    
      > But I think one of the biggest risks is fragility. 
    

Systems that can't adapt to unanticipated needs of their users get replaced by
systems that can adapt. It's why many pieces of mature software develop this
robust configuration ability (often hiding under the label "api", "scripting
interface", "plugin framework", etc.)

    
    
      > Software that gets used by lots of people will end up with 
      > towers of complexity built into the configuration, to the 
      > point that removing or refactoring them risks bugs, edge 
      > cases, or breaking a particular feature or misfeature that 
      > someone relies on.
    

This is not a inevitable. Many mature systems have successfully incorporated
fully programatic configuration [1] without turning into "towers of
complexity". (It probably says something about the application's architecture
if it's so tightly coupled to it's configuration.)

[1] Unix is the poster child for this.

------
0xdeadbeefbabe
Yes, yes they are. I'm not a programmer, but a user with a refined taste for
java--hah just kidding! Clojure isn't so bad though. Java is an interesting
interface or programming language because you need an autocomplete editor i.e.
another interface to really enjoy it. Don't forget maven and ant for libs and
builds.

But some people are probably comforted by java ui maybe because it is so
structured.

Edit: remember ant and maven.

