PurelyFunctional.tv Newsletter 293: Design, deps.edn, Type Inference
Sign up for weekly Clojure tips, software design, and a Clojure coding challenge.
I have an important announcement. Though it pains me to say it, there will be no Clojure SYNC 2019. There are more details here.
PS Want to get this in your email? Subscribe!
I have a couple of spots open for client work. I'm currently offering two specialized services. These are open for remote or on-site:
Clojure Kickstart is training to get your team of programmers productive in Clojure. Get the skills, the tooling, and the workflow you need to make the most of Clojure.
After the Prototype is where I and your team workshop a powerful core abstraction and come up with a plan for refactoring it into your codebase.
If you or someone you know are interested, please reply to this email.
Tony Hoare's Turing Award Lecture from 1980.
I have regarded it as the highest goal of programming language design to enable good ideas to be elegantly expressed.
Even in those days and even with such a simple language (ALGOL 60), we recognized that a subset could be an improvement on the original.
But I was not satisfied. I did not see why the design and implementation of an operating system should be so much more difficult than that of a compiler.
If our basic tool, the language in which we design and code our programs, is also complicated, the language itself becomes part of the problem rather than part of its solution.
The price of reliability is the pursuit of the utmost simplicity. It is a price which the very rich find most hard to pay.
I'm sorry to say it, but it won't be happening. This post talks about why, and the future of Clojure SYNC.
Embracing Simpler Tools YouTube
David Nolen talks about the relatively new Clojure command line tooling and deps.edn in the context of using simple tools.
As part of writing my book, I was coming up with a good definition of actions (also known as effects in some circles). Actions are notoriously harder to test than calculations (aka, pure functions), and I realized that the definition could explain why.
Cult member echo chamber FTW Podcast
Dmitri Sotnikov on the defn podcast. Definitely a great discussion.
Mike Fikes interviewed on The REPL podcast. Great discussion.
While I've never programmed in Ruby, I have always been a fan of Sandi Metz's talks. After seeing her speak at OSCON this year, I dove into her book.
I've always been skeptical of the term "design" applied to code. For instance, as it is applied in "Design Patterns". The first chapter of this book addresses the question in a way that I've never seen before. Design, in this context, is all about developmental concerns (as opposed to functional or operational concerns). It's not about correctness. It's about how easy it is to make your code correct, especially as requirements change and you learn more about the domain.
The book shows lots of manipulations you can make to existing code to make responding to changing requirements easier. It all looks great. Then it ends with testing, which seems a little scarier since it shows tests that are correct and passing, but that could easily become incorrect and still pass. It really makes it difficult to believe in the magic of TDD after reading that. Even with a full test suite, you still need to spend time designing your tests.
It was a good book, well worth a read. Sandi Metz is one of a handful of Object-Oriented aficionados who were forged in the days of Smalltalk. That experience gave her a much different perspective than we often see from those who grew up with Java, C#, or C++.
In the end, I was left wondering: can incremental refactorings, guided by simple design principles, make serious changes in your code? Sure, it can clean it up, but would you ever be guided to change a core abstraction into a superior one? For example, if my calculator software were written using roman numerals internally, would these design principles and refactorings lead me to discover decimal numbers?
If so, this is an amazing advancement for human knowledge. Write software, keep adding features, and keep refactoring it incrementally to make adding those features easier, until you've found a better abstraction. We could apply this in any field of human knowledge. There's actually some evidence for this. For example, Gerald Sussman has shown how programming notation can clarify physics notation. Or a program can reveal corner cases in a business process. These anecdotes are in the right direction, although these aren't completely new abstractions, merely better representations of them.
The possibility remains: maybe you can't follow design principles to come up with better abstractions. In that case, there must be something parallel to manipulating the code. We can, of course, refactor code to replace an abstraction, but we must already have that new abstraction in mind. Without the new abstraction, refactoring is just moving code around. Design principles can tell you where to put the code for calculating epicycles. But can it put the sun at the center of the system? Imagine how "clean" your code would be after getting rid of those epicycle methods!
Like I said, it's a good book. It made me think. And I'd love to have a similar book in the functional programming community.
Clojure Collections Currently recording
I'm back to recording this course that is all about the heart of the Clojure language: Clojure's persistent collections.
They're more than just fast implementations of useful data structures. They also capture essential access patterns in terms of Java Interfaces (or, in the case of ClojureScript, Clojure protocols). I've finished recording all of those access patterns. Learning these patterns is essential to coding in Clojure, and I wish I had known these when I first started.
I've also started in on recording the usage patterns. These are the common ways that the collections are used in everyday Clojure code. These are actually harder to identify. I've found and named a bunch, but I'm sure there are more.
New lessons this week