Year-end update 2019
This is an episode of Thoughts on Functional Programming, a podcast by Eric Normand.
I'm taking a break to retool for Season 3, which will start in the new year. I also give an update on Grokking Simplicity. I am working on Chapter 7.
Eric Normand: Hello, folks. I just wanted to let you know that I am taking a break from this podcast. I am not recording. I'm deep in the back end working on season three. I'm retooling, planning, figuring out what this podcast is going to turn into in the New Year.
Please stay subscribed if you're interested in learning about that. Otherwise, just hang on because it's coming. I want to give an update on the book. Chapter five just came out last week. Chapter five is all about...It's called "Improving the Design of Actions."
The thing that this chapter is emphasizing is that people say that functional programming is about pure functions, programming with pure functions, but that sells it short because functional programmers have a lot to say about actions.
We've identified them. We know what dangers lurk inside. We know how to work with them a lot better. We've developed tools. As an example, we would talk about whether you have a transactional state. If you have mutable state, is it transactional? What are the characteristics of it?
We do that a lot more than object-oriented programmers. I would say. We have a lot of tools. Because you can't get rid of actions, you should at least have them somewhat well-designed. The idea behind chapter five is that...In chapter four, we extract calculations from actions. You do that by identifying the inputs and outputs to the function.
What are all the things that this function uses to produce an answer? What are all the answers it produces? A pure function, calculation will only have arguments and return values as its inputs and outputs. I'm calling those the explicit inputs and outputs. That's thanks to Chris Jenkins for this idea.
Then there's all these implicit and explicit ones that exist in actions. If you just replace all the implicit ones with explicit ones, then you've got a calculation. Another thing we do is even if we can't get rid of that last explicit input or that last explicit output having fewer or, sorry, implicit.
I said explicit. We can't get rid of last implicit input. Having fewer implicit inputs is still better. It doesn't cross the line into calculation. If you have an action that only has one implicit input, it's better than an action with two that does the same thing. That is the idea in chapter five.
We go through. We have the code examples. We systematically look for implicit inputs and output and try to reduce them. The code is getting more and more functional as we go along. Little secret, this is an exclusive. Don't tell anyone. The chapter six is already written. It's ready.
There's a schedule. The publisher has a schedule for when chapters go out. At some point, they're going to decide I don't have any. I have no idea how it works. I have some ideas, but it's the kind of thing where some people are like, "Hmm, I think it's about time."
I don't know what's going on in there, but chapter five just came out. Chapter six is ready to go out when Manning, the publisher, decides. Chapter six is all about immutable data. We go through in great depth how to do copy on read and copy on write. It's a good chapter.
It talks a lot about why this is important and when to use each one. Now, I'm working on chapter seven. This one is tough because it's more of a design chapter. It's the last chapter in part one. When I've finished this one, the whole first part will be done, the first third of the book.
I'm excited about that, but I just want to tell you chapter seven is about stratified design. It's all about looking for layers of meaning in your code and if the layer structure doesn't look very neat and organized, how to go in there and manipulate it so that it is neat and organized.
It's designed in the sense of...One thing that we have to deal with, since we don't write programs once and never touch them again — we maintain them for the life of the business — you need to arrange things so that the things that will change frequently, because you're experimenting, you're learning how does free shipping work, you want to be able to change those things.
You want those to be easy to change. Then some things, you want to say, "OK. This is good. It's done. Let's make it so that we don't have to change it so much." You're going to have stuff like that other stuff is built on top of. How do you arrange that? It's all about the call graph. What functions call? What functions? You just draw that all out.
The stuff at the top, the stuff that nothing calls, the very top, since nothing relies on it, can change very easily, very cheaply. You can just rewrite it. You don't even have to have the same contracts and stuff because nothing calls it.
Now, this stuff at the bottom can't change that easily because all this other code is built on top of it. If you change it, even if there's a possibility of introducing a bug — maybe there's some contract that you're now violating — it just might be a bug. You just made a mistake.
All of that has consequences. That stuff should be harder to change. Now, you have this nice stratification of going from easy to change at the top to hard to change at the bottom. You can choose where things go, which is great for maintenance.
The other thing we talk about testing, where would you want to spend your testing budget if you have a limited budget? Of course, you could say yes. I want to test everything, but come on. What do you test first?
If you have all this code, what's the best bang for your buck? The tree kind of guides you there. The answer is at the bottom of the tree, because so much stuff relies on it. You want that to be more robust.
Your tests aren't going to change. They're going to change just as frequently as the stuff at the bottom. When you write that test, it's going to last a long time. Whereas if you write tests for stuff at the top, the advantage of writing tests for the stuff at the top is you are testing a lot more code.
You are exercising a lot more code because the stuff at the top is calling stuff below it which is calling stuff below it. It's exercising more code, but it's also going to change more frequently. You spent two hours writing that test. Now you're going to have to change the test too. It's probably better to focus on the bottom of the tree.
Then reuse. The stuff at the bottom it's just more reusable. It's already being used multiple times. The stuff at the top is not being used. Again, stuff at the bottom, it's more reusable. It can be used more easily by other systems that weren't anticipated.
That's what I'm working on now. It's all about cleaning up your code, making it more organized, designing your system so that that works. It's a preview of things to come. Every part, all three parts have a design chapter at the end.
Part two ends with the onion architecture. Then the part three ends with reactive design, reactive architecture. This chapter is setting up a lot of things that will be useful later. The whole of part three is about domain modeling and data modeling and stuff.
We're going to get to that idea of, "How do you build this stuff that's at the bottom?" The stuff at the bottom is usually your domain model. How do you design that? This chapter is not about, "OK, let's get in there and make some domain model that's going to last a long time."
It's mostly just about, "Let's move the code we have up and down this tree so that it has all the characteristics we want, maintainability, reuse, that kind of thing." That was just a little update. Just a reminder, the podcast is going to go on hiatus until the New Year.
Just so you know, it's me planning, diving deep, figuring out what this podcast could be. Every year, I seem to go into a cocoon and emerge as a new butterfly.
Awesome. My name is Eric Normand. This has been a thought on functional programming. Thank you for listening and rock on.