Friday, November 15, 2024

The importance of readability

Software has to meet several goals, some of which may conflict with each other.
  • It has to work.  Performing a function is the entire point.
  • It has to be efficient.  This may involve using less time, memory, power, etc.
  • It has to be maintainable.  80% of programming is debugging and updating.
To be maintainable, your code must be readable.  The trade-off between readability, writability, functionality, and efficiency is why there are so many different programming languages.  Well, that and fashion trends in the industry.

What is readable code?  That's partly opinion, partly experience, but also partly objective fact.  "GOTO considered harmful" isn't just a meme, it was a real wake up call for the industry 56 years ago.

XKCD


Spaghetti code may sound delicious, but it's a toxic mess for others to try to clean up.


That brings me around to one of the main points of my programming language, Listack.  I have been fascinated by stack based languages ever since I read a book on Forth way back when I was a teen.  I even implemented Forth in BASIC.  It was incredibly slow, but it worked.  And then, a few years ago, I discovered Factor.  It's a modern stack-based language.  Factor lead me to Joy about the same time I discovered the False esolang.  Joy has (for a programming language) a relatively large amount of well written theory behind it.  False is an extremely minimal language, but it shares a lot of conceptual space with Joy.  I enjoyed learning a bit about all these languages.  I even implemented a False interpreter in Python.

The problem is that, like Forth, these are all write-only languages.  They're efficient, they're fun, they're concatenative, and they're terrible to try to read a program of any complexity at all.  But hey, at least they're not APL.

And then I started learning to program in Nim.  It's a more-or-less standard high level, compiled language.  It has Python-like syntax with significant whitespace (no curly braces or semicolons needed).  And it has uniform function call syntax.  That was a revelation for me.

That's where I got the idea for Listack.  I could make a more readable stack-based language.  Like most stack based languages, it would be concatenative.  It would make heavy use of first-class functions and combinators.  And it would be my creative contribution to the art of programming.  Note how handy the immediate block (code blob) makes things.

Compare these code snippets.  They all do the same thing.

style                    simple                                complex    
Call:          +(1, 2)     func1(data1, func2(data3, data4))
Prefix:         +: 1 2      func1: data1 (func2: data3 data4)
Infix:          1 + 2       data1 func1 (data2 func2 data3)
Postfix:        1 2 .+      data1 data2 data3 .func2 .func1


Concatenative style aids readability.  It's easier to follow the logic when it's written left to right than when it is inside out.

inside out:      func3(func2(func1(data1), data2), data3)
concatenative:   data1 .func1 data2 .func2 data3 .func3


Then I added one more thing that may be genuinely unique - the single word comment.  One of the major problems with powerful and efficient languages like Factor and Lisp is that they have almost no syntax.  That helps the language designers and talented macro programmers, but it significantly reduces readability.

Compare these code snippets.  They all do the same thing.

(truth test) {good branch} {bad branch} .if
(truth test) if {good branch} {bad branch}
if: (truth test) {good branch} {bad branch}
if: (truth test) #then {good branch} #else {bad branch}

Syntactic sugar is important for code readability.

easier to follow                                  harder to follow
if: (test one)                if: (test one)
#then {if: (test two)             {if: (test two)
    #then {good good}                 {good good}
    #else {bad good}                  {bad good}
    }                             }
#else {if: (test three)           {if: (test three)
    #then {good bad}                  {good bad}
    #else {bad bad}                   {bad bad}
    }                             }




5 comments:

  1. So very long since I've programmed.

    ReplyDelete
    Replies
    1. I was away from it for thirty years before I started back up. I collected and read a few programming language books along the way. I recommend "Seven languages in seven weeks". The first version had a concurrency theme. The second focuses on newer and more exotic languages.

      Delete
    2. It's a fun hobby and a boring job unless you're really into puzzle solving. If you want to get back into the hobby, I 'd recommend getting a beginner's book on Python.

      Delete
    3. I'm trying to think of the last one I wrote - I think it was a finite element model (from scratch). And 2-d, at that. A *lot* of matrix manipulation.

      Delete
    4. I'm a language geek. I learn different programming languages, and use them to write other programming languages.

      Delete

I reserve the right to remove egregiously profane or abusive comments, spam, and anything else that really annoys me. Feel free to agree or disagree, but let's keep this reasonably civil.