Podcast: Play in new window | Download
I found out that I didn’t know how to read or write. This episode will show you how making a change to how I read made it much easier to write.
Links:
Podcast: Play in new window | Download
I found out that I didn’t know how to read or write. This episode will show you how making a change to how I read made it much easier to write.
Links:
On my first day at Trello, my peer mentor showed me two things. One of them ended up being the topic of my talk on Reactive Programming. The second thing he told me was, on our team, PR’s should tell a story.
Then we pair constructed a PR. To be clear, he was already in a local branch, and the code was already written and committed.
He showed me how he used git reset
and git rebase
to rewrite the commits. He explained that he was rebuilding the commits to make the PR easy to review. He constructed each commit to be atomic—to do a single coherent thing.
This was the PR style for our team for the whole time I worked there. The goal of a PR was to make it easy to review, and we expected reviewers to open each commit in a tab and review them one-by-one. We considered it acceptable to decline a PR if it was too big or hard to review (in practice, this happened very infrequently).
Other practices:
These practices helped us, but the important part is our team mindset that PRs were constructed to be easy to review.
The Liskov Substitution Principle is an Object-Oriented class design guideline that says that a sub-class should be substitutable for a super-class and that clients to the super-class should not be impacted.
You achieve this by specifying a contract for each public method of a class.
First, you specify a pre-condition/requirement.
If the caller meets the requirements, then the method makes a promise of a post-condition and result.
A sub-class is substitutable if it makes the same promises under the same requirements. It is also substitutable if it can make the same promise with fewer requirements. And, finally, it’s still substitutable if it makes more promises.
So, sub-classes can require less and promise more than the specification of their super-classes. But, they can neither require more nor promise less.
Some OO languages, like Eiffel, have ways of encoding the contract, but in Swift and many other languages, this is something usually stated in documentation.
But, substitution is not just an OO principle, or at least, I don’t only apply it to super/sub class relationships. I think it should be applied to versioning of any public library of any kind of code (OO, functional, whatever). To do this, think of vNext as a subclass of vCurrent.
So, vNext can require less and promise more. It can’t:
Unfortunately, many languages would think of some acceptable changes as a compile-time breaking change. For example, in Swift if a method returned T?
and you changed it to return T
, then callers that used guards would not compile. Strictly speaking, T
is always substitutable for T?
, but you should not do this change.
This is not how many library authors think, Instead, I think we’ve been corrupted by semantic versioning and the idea of acceptable breaking changes. Under substitutable versioning, there is no such thing as a breaking change.
Under semantic versioning (major.minor.patch), most library providers only think of patch version increases as being substitutable and for sure major version increases are not. I would say in practice, minor version increases are sometimes breaking.
In a fully substitutable versioning system, this would never be the case. vNext would always be substitutable for vCurrent. This means that:
To be clear, if clients write to implementations and not specifications, they might break with future versions, so documentation needs to clearly explain what is required and promised. The actual behavior should not be confused with the contract.
A common example of this is relying on buggy behavior. If I call a method and it has some bug, I might write code to work-around that bug. If a future version fixes the bug and my software breaks because of my work-around, that’s still considered a substitutable change as the bug was not a promised behavior.
In a talk on clojure specs, Rich Hickey called this concept accretion and railed against breaking change. I know that semantic versioning is too entrenched right now to change, but something like what Rich is describing would do a lot to relieve dependency hell.
To help new Swift learners, I’ve been going through Apple’s Swift book chapter by chapter and writing a companion article that gives you a simple exercise to do to make sure you understand the content of the chapter before moving on.
The whole series is available here.
The latest chapter is a companion to the Subscripts chapter.
I started a podcast about a week ago and the first episode was an exercise that helped me overcome writer’s block. In the episode I said that I don’t get “coder’s block”.
This is more or less true, but I want to elaborate. I don’t mean that I can instantly solve any bug or program anything I want at will. I mean that I can make progress and do something.
When I have a problem I need to solve and literally have no idea what to do next, here are a few things that help.
And, sometimes it’s right to put a hard problem on the back burner and come back to it later.
My instinct in writing is to just say what I believe to be a true or interesting in a direct way. Maybe give an argument or two why and call it day.
So, most of what I write is kind of like this: “Hey everybody, I think blah blah blah and one time I blah blah blah’ed and yada yada yada, it was great. You should blah blah blah too.”
And even as I’m doing this and re-reading my writing, I am thinking: “this is kind of boring”, but I didn’t know how to make it better. So I’ve plugged along because up to this point, I’ve decided that writing imperfectly is better than not writing.
But, today, (March 5th, the day I am writing this), is my first day as an independent software developer, writer, or whatever I end up doing. I don’t have the safety net of gainful employment to give my work meaning. It somehow has to come from me and my own projects.
And this blog is one of those projects, so it’s not enough to just write any more. Eventually, this blog has to be good, which I define as valuable to readers (as opposed to just valuable to me as a place to practice writing).
Over the years, I have seen/read/heard a lot of advice about writing, but one really stands out to me right now, and I am trying to really understand it.
It was a podcast episode of Scriptnotes (transcript), where Craig Mazin, the writer of the Chernobyl mini-series, explained what a story is. I recommend reading the whole thing, but the essential generator of story was an argument. This interests me because most of what I am writing is my side of an argument.
According to Mazin, to generate a story, you start with an argument with a true side and a false side. Then, you create a character that believes the false side and lives a stable, but imperfect life with this belief.
The story will make that stable life impossible and eventually change the character’s worldview such that they act in accordance with the true side of the argument. The details are fascinating, and I recommend you read the transcript (the back episodes are available on a paid subscription if you want to listen to it).
One way to sum it up is:
What is more interesting: “you know, if you lie to people, they might not believe you when you are telling the truth” or The Boy who Cried Wolf?
The first example is just advice (which is actually good advice, but it’s boring) and the second is a story. It has humor, it has twists, and it has an argument exemplified by a character living the opposite of the advice. It’s not exactly the same structure as Mazin’s, but it works.
Craig Mazin writes fiction, and a lot of what he’s describing is story invention. But, it applies to non-fiction as well (see his José Fernandez example). And, of course, if I think back to interesting non-fiction books I have read, they are full of stories.
But, I also know that long-winded stories (when you want actionable advice) are somewhat off-putting to me. I personally need to find the right balance.
In my own journey of “Stating advice directly, but in a somewhat boring way” to “Telling an interesting story that incidentally makes my argument”, I am really just getting started, but I will try to tell more stories of characters living the false and true sides of arguments I am making rather than just plain descriptions of the argument.
I released a podcast a few days ago. I am doing this podcast partly to improve my writing and my ability to do Professional Performances, so it is scripted.
A side benefit is that it doesn’t take much to produce a transcript. In fact, I have a pretty good one before the podcast is even recorded.
Aside from accessibility, transcripts have many other benefits. SEO is a big one, but also, it makes it a lot easier for listeners to refer back to. And if they feel inclined to quote you on social media, it makes it a lot easier.
In any case, I’m glad that my process produces the accessible artifact first.
One thing that I like about podcasts is that you can do them while you are doing other things. But, I think there’s an opportunity for a podcast to augment the other thing you are doing.
Write While True is a podcast is for programmers that want to write more. Listen to it and get ready to start writing when it’s done. Each episode is short and will describe a writing exercise you can do when it’s over.
The first episode is an exercise that will help you get unblocked.
Podcast: Play in new window | Download
I started my blog 17 years ago, but wrote about 9 posts a year. Then, I started doing something that helped me write something I could publish every day.
Links:
When I was 13, my mom got me an electric typewriter for Christmas. Luckily, it was broken, so we went back to Radio Shack to return it. When we got there, they were trying to move TRS-80 Color Computers for about $50 (the same price as the typewriter).
So my mom got me a 4k, chiclet keyboard version that hooked up to a TV. There was no storage included, but supposedly you could hook them up to ordinary tape recorders (I never figured this out).
The next Christmas, I got a Commodore 64, again with no disk drive. I finally got a disk drive for my birthday a few months later.
For a while, my home computer could literally do nothing except be programmed.
All of my personal programs lived on paper. I typed them in, played with them a bit, and then re-transcribed them back to paper. My most ambitious program in this time period was a very light Defender clone made from ASCII art.
It was like learning a musical instrument.
If I were learning piano, I would play songs over and over until I got them right. If I could compose music, I’d do it on paper and retranscribe often.
And doing this did at least accomplish the goal my mom had with her original gift. I learned how to type pretty fast.