PurelyFunctional.tv Newsletter 463: What is beautiful code?
Sign up for weekly Clojure tips, software design, and a Clojure coding challenge.
Clojure tip 💡
what is beautiful code?
I've been reading Coders at Work by Peter Seibel and in the interview with Fran Allen, Seibel asks "What makes a program beautiful?" Her answer surprised me with its insight:
That it is a simple straightforward solution to a problem; that has some intrinsic structure and obviousness about it that isn't obvious from the problem itself.
I love the answer. To paraphrase: "The solution is obvious, but it isn't obvious from the problem itself."
It reminds me a lot of Aristotle's advice for a good ending to a story: both surprising and inevitable. That feeling of a suspenseful ending, yet where all the pieces come together. The ending is obvious, but it isn't obvious from the pieces themselves.
But that got me thinking. Sometimes, even a good reframing of the problem can be beautiful if it focuses on the root of the problem. And it's beautiful for the same reason: It's obvious, but not obvious when given the original problem.
Again, I'm reminded of the APL version of Conway's Game of Life and its implementation in Clojure. It reframes the problem as one of counting neighbors while the original problem implies it's about keeping track of which cells are alive.
So, the tip is: Can you reframe the problem? Try different ways to see what comes up.
State of Clojure Community Survey 📋
Please fill out this survey. The folks behind Clojure really listen. Let your voice be heard.
Just a quick reminder:
I'm migrating all of my video courses from PurelyFunctional.tv to a new platform called Podia. On Podia, you can buy the courses with either a one-time purchase or a 12-month purchase plan.
I'm also going to retire the PurelyFunctional.tv brand. Instead, I'm just going to use my name, Eric Normand. Next week, my old site will redirect to ericnormand.me.
Awesome book 📖
Idea Flow by Janelle Arty Starr is a provocative book about measuring friction in a codebase so you can systematically address it and speed up your team.
The book provokes the reader with this question: If a project is slowing down because of "technical debt", why do they continue to flounder even after large refactoring efforts? The book answers by saying that we are bad at knowing what kinds of refactoring will actually help. There's tons of stuff that could be cleaned up, but what stuff will actually make a difference?
To find that stuff, the book proposes we keep track of different kinds of "friction" while we are coding, then address the friction that actually comes up. Confused about what is happening? Record how long it takes you to understand. Looking for a function? Record how long it takes to find it. If you record all these pieces of friction, you'll see a timeline of your work. And the team can use the actual slowdowns to plan cleanups, etc.
The book also ends with a discussion of how Lean applies in software. There's quite a lot of argumentation about how software development is not a factory. We don't produce identical widgets through a fixed process. But the author makes a good case that it is more like a factory than we think, but in a different way from our normal idea of a factory.
As knowledge workers, our products are ideas. We have an idea for a feature. A bug is an idea. And we need to load those ideas into our minds (our tools), transform them into plans and code. So any time we are not spending transforming ideas into code is waste (in the Lean sense). If code is hard to understand, it takes more time and effort to load the ideas into our minds. That's waste.
She further discusses an analogue for the "supply chain", where feature requests and bug reports "pull" work through a dependency graph. That I'm not so sure about, but I think mostly because the book got very abstract at that point.
I recommend the book because it is a compelling idea that needs more testing and tooling. I would like to try it on some projects I am working on. It seems like it might put an end to endless design discussions, because the design would have a goal (i.e., remove a specific friction).
Book update 📘
More Twitter messages like this one in my feed. I love it:
You can order the book on Amazon. Please leave a rating and/or review. Reviews are a primary signal that Amazon uses to promote the book. And they help others learn whether the book is for them.
You can order the print and/or eBook versions on Manning.com (use TSSIMPLICITY for 50% off).
Clojure Challenge 🤔
Last issue's challenge
This week's challenge
I'm fond of search that is forgiving of small mistakes. If you type a few letters from the word, even if you miss a letter, you should get the word.
Here's a simple, forgiving search function.
Write a function that takes two strings, a needle and a haystack. The function should return true if the needle is found in the haystack, with a few forgiving features:
- If the needle is fully contained in the haystack, it should return true.
- If the needle would be fully contained in the haystack, but for one or more missing letters, it should return true.
- Don't match the needle across whitespace or other non alphanumeric characters.
- Otherwise, return false.
;; needle haystack (found? "abc" "dddabcfff") ;=> true (direct match) (found? "abc" "xyzannbffooc") ;=> true (add missing "nn" and "ffoo") (found? "abc" "a bc") ;=> false (don't match across whitespace) (found? "xxx" "cxccx") ;=> false (not enough x's) (found? "" "") ;=> true (trivially so) (found? "" "aaa") ;=> true (also trivial)
Thanks to this site for the problem idea, where it is rated Very Hard in Java. The problem has been modified.
Please submit your solutions as comments on this gist.