The Freedom of Restrictions
One of my great joys when designing things is when I discover that I can lift a restriction and make something both simpler and more powerful at the same time. This can happen at all levels, from something like changing a function signature to make it more generic, right up to unifying high level system components. The more generic something is, the more situations you can use it in, and the more value it can provide.
    But there comes a point where something can be too general—goto statement. Edsger Dijkstra wrote about its dangers
    in 1968 in his letter The Go To Statement Considered Harmful, and Donald Knuth wrote
    in his 1974 paper Structured Programming with Go To Statements about how the
    majority of the dangers can be avoided by adding some restrictions to
    its usage.
  
    As we now all know, there are a handful of control structures that
    the goto statement was used to simulate which are
    perfectly safe and well understood—if,
    switch, for, while,
    break, return, function calls, etc.
    Anything else was usually too complicated and error prone. The
    problem with using raw goto statements was that it
    wasn’t always clear which of the good structures the author was
    intending to use, and it was easy to make subtle mistakes that went
    unnoticed and caused huge problems. And so we all agreed that despite
    the fact that a single statement is more general and can do all the
    work of the other handful of control structures and more, we’d be
    better off without it.
  
By restricting ourselves to using only well understood control structures, we free ourselves from the possibility of writing error-prone, incomprehensible spaghetti.
    It’s worth thinking about whether adding restrictions to other tools
    and techniques we use could actually make our lives easier. I think
    we are starting to see that even the for loop is more
    trouble than its worth, as more and more languages embrace higher
    level, more expressive forms like map,
    filter and reduce. Much of the benefit of
    functional programming comes from restricting use of the assignment
    operator. Concurrency is another area that I think would benefit from
    some restrictions. Programming directly with threads and locks is
    incredibly flexible, but it’s also fraught with potential race
    conditions, deadlocks and data integrity issues. Restricting
    ourselves to well understood abstractions like the actor model
    would free us from the hassle of dealing with these problems.