YOU GET TO DECIDE
Yesterday I got my hair cut. The hairdresser was rather chatty and told me all sorts of things. When her friend came in they went on to lamenting about how bad it is for them. Both dislike their jobs, the payment is bad and they‘d rather do something else. But they don‘t know what…
This made me again realise how great your and my job are. We get to do what we love. We can be creative, get lost in the details and sometimes even improve the world—if just a tiny bit.
Or we can do bad and support totalitarian governments, implement censored search engines and track people‘s behaviours.
It‘s up to you to decide what to do with your gift.
Yours, Holger
THE INNER-PLATFORM EFFECT
“The Inner Platform Effect is an anti-pattern that occurs when a software system is designed to be so customizable that it ends up being a poor imitation of the platform it was designed with.”
Matthew has started a new series on anti-patterns in software development.
He starts with the Inner platform effect. This is an anti-pattern I did now know before but was able to recognize once I read his explanation and examples.
What about you? Can you find examples for it? Tell me about them!
You can read his article here.
Yours, Holger
WHY ARE OUR ESTIMATES OFF, ALWAYS?
As I previously mentioned I freelance for a nice client right now. I am embedded into a great team and like working with these people. Summer came and our project manager was about to take his vacation. (He cycled from Finnland to Hamburg in Germany with a friend, in case you were asking. I think that’s great as I am a cycling maniac myself…) Before he started his vacation we groomed the backlog in Trello and scheduled various tasks for me and the other freelancers. I had the seniority in the project during his absence, so I took on the load to manage the others. After scheduling a few tasks we looked at each other and decided to schedules some more, because it felt like these were too few during his three week leave. Then we scheduled some more “just in case” we were super fast.
In the end, we did manage to complete a lot of work. But these were only the first batch of scheduled tickets. We couldn’t fully complete those even! How could it be that we were so much off with our estimates? No harm was done and we are still really good on time, but it was strange.
In this light, please enjoy this oldie/goldie about project estimates… Why are software development task estimations regularly off by a factor of 2-3?
What are your experiences giving estimates?
Yours, Holger
FORMATTING DATES
When was the last time you needed to display a formatted date somewhere in your applications? Since I work a lot on React (or generally JS) apps these days, I recently had the “pleasure” to format dates in JS. After receiving them from a Ruby API. Which in turn takes the (Postgres) db timestamps and converts them into Ruby (date)time objects. Oh the fun we had. “Of course” standardizations saves your ass in this situation. Usually at least.
What I did not run into (because of my luck working with Ruby and JS) is the nice little thing, Peter Hosey describes in his article “Unicode date formats, YYYY?!". You should click that link, if only just to see the url of the article. It’s not the title I’ve mentioned above…
Short summary: There is this thing called “year for week-of-year”. You probably know that sometimes at the end of the year the calendar week 1 already started—but we’re still in the old year. If you print a date of that range, say December 31st 2018, you have to pay attention how your date-formatter-function actually formats the date. If you use the wrong pattern, you could end up with the wrong year!
Go ahead and click the link “Unicode date formats, YYYY?!" 😉
Happy 2018!
Yours, Holger
PS: If you want to display the year for week-of-year in Ruby/Rails, you’ll need to use the pattern %G
or %g
:
ISO 8601 week-based year and week number:
The week 1 of YYYY starts with a Monday and includes YYYY-01-04.
The days in the year before the first week are in the last week of
the previous year.
%G - The week-based year
%g - The last 2 digits of the week-based year (00..99)
%V - Week number of the week-based year (01..53)
READING CODE
_ This is another email I am sending while being happily busy with our newborn._
Two days ago I linked you to an article about Livable Code. Today it’s about reading code. While learning software development I often heard the phrase that you should read other people’s code because it makes you better.
I have to admin, I never purposely did so. Well, one time, I followed through the Rails framework to understand how an HTTP request is handled. But that was the exception. It turns out, I am not alone:
Most programmers agree that we don’t read enough code. The interviews in Peter Seibel’s book, “Coders at work” highlight a comical contradiction: almost all the programmers interviewed by Seibel recommend that others read code for fun, but none of them routinely do so themselves.
This is the opening paragraph of a post by Stephen Malina titled Reading Code. Please click that link and read that post. It will leave you thinking. I promise.
Yours, Holger
SURPRISES WHEN STARTING OUT AS A SOFTWARE DEVELOPER
_ This is another email I am sending while being happily busy with our newborn._
My first job was as a software developer at Ericsson in Montreal, working with the mobile switching center that handles calls in a cellular network. There was a lot of code controlling call set-up, hand-offs, roaming etc, but I was pretty disappointed to see that it was all done with quite basic data structures and algorithms. The most interesting part I found was the code keeping track of roaming subscribers currently in the system. It consisted of one thousand binary trees, where the last three digits of the subscriber number determined which tree a given subscriber belonged to. To find a subscriber, you picked the tree based on the last three digits of the number, then traversed the tree to find the subscriber. Apart from that, it was pretty much only linked lists or simpler.
Today I want to link you to Henrik Warne’s blog where he tells us about a few surprises he had when starting as a software developer earlier in his career.
I will get back to this topic and talk about mine, once things are back to “normal” here.
Yours, Holger
BIG NERD RANCH
This is another email I am sending while being happily busy with our newborn.
Sometimes things don’t always go as planned. Code breaks, servers crash, or a product doesn’t work – you know the story.
As a Product Manager, developing a deep understanding of the root problem is critical to helping you save time and money before writing code. On the rare (cough) occasion these things happen, it’s important to have processes in place for you to evaluate and prioritize these problems for your team quickly.
I know not everyone of you is a developer. And it makes sense to broaden one’s point of view. So please enjoy this article from Big Nerd Ranch blog
Yours, Holger
LIVABLE CODE
First of all, sorry for not writing to you yesterday. I spent the day in the hospital with my wife. Our second daughter was born on 1:20pm yesterday and we couldn’t be happier. Mother and daughter are both very well. This is the reason why I won’t be able to continue writing my usual emails for the next few days. But I will continue sending you emails. The content will be mostly “written” by other people though. 😉
Today I want to share a recent article by Uncle Bob: Too Clean?
According to Mei, in order to be “livable”, the organization of a software system should lie somewhere between the extremes of the horrific tangled mess of code hoarders, and the antiseptic cleanliness seen in the pages of interior decorating magazines and home sales brochures.
This is not something I had considered or expressed before; though it has always been something I’ve sheepishly practiced.
Can a system be too clean? Is it possible to focus so much on cleanliness that no one can practically work in the system?
In this article Robert references a talk by Sarah Mei that he saw and shares his point of view. Have a read.
Yours, Holger
MY AUTOMATED PUBLISHING WORKFLOW
A week ago I mentioned my Automation project: Factory 0.1. During the last week I managed to get it to a point where it works. Today I wanted to tell you a bit about it. This will be a lengthy, nerdy post about details and automation.
Writing the article
The first thing to do is to write my article/email. This is where it all starts, and this is what I look forward to doing. Writing happens for me in the application Ulysses. I used to write in other apps like Simplenote, IA writer or more long-form in Scrivener. For a few months now, I use Ulysses exclusively for all my writing and notes. It feels good to have everything in one place and not scattered throughout more apps.
I write in Markdown. All the time. I just got used to it over the years and I like the simplicity. Of course that comes in handy when writing Issues, Pull Requests, Wiki entries or Readme for GitHub powered repositories. Since GitHub uses (or supports) Markdown for all these, I can easily write for that. So if you never really got into Markdown, I can really suggest trying it out some more.
I start my articles with the date of the current day or the date when I plan to publish the article. Sometimes I write a few days in advance—if I know I won’t get around to doing it on the day in question. The next line will hold the title. I mention it in this detail because it’s important in a later step. Then the body of the article will begin.
I aim for a length of about 2 minutes reading time. Earlier in my career I wrote really long articles (like this one 😉). But I noticed that people tend to not want to read such long articles. And since I write every week-day, I try to keep it short and on-point. This is usually harder than it sounds. Ulysses helps me reach the 2-minutes-marker with a visualisation of the goal.

Once I am done with the article, it’s time to proof-read.
Then on to
Publishing the article
I use Jekyll a static site generator for my website. I used to use Wordpress but I didn’t really use Wordpress and the constant necessity for updates was annoying. Also I do not use PHP and have little experience. So I was always dependent on external themes and plugins for anything. But I wanted to be able to develop/hack on my own website. Since I do know Ruby very well it made absolute sense to use that as my website technology. Hosting is done via GitHub pages. So that’s one more thing I do not have to worry about. The hosting, the SSL certificate and all “updates” are handled by GitHub. Of course updates to Jekyll are made by me. GitHub offers security monitoring for repositories, so I am always aware if a dependency it outdated or has a leak. Another convenience is the ubiquity of GitHub. It’s available in many automation tools' stacks, so I can easily use it if needed.
To publish my article, I use my iPad. I love the iPad’s form factor (it’s a 12.9"), the tactility and using it. I look for ways to use it more. With the apps Workflow, Drafts and Working Copy I have everything I need.
Breakdown of the steps for publishing
To have a new article published with Jekyll, I need to do the following things. I used to do them manually:
- Write in Ulysses
- Create a new file in site/_posts folder with the naming convention
_posts/${year-month-day}-this-is-the-title.markdown
- Format the front matter (configuration for this specific post/article in YAML) with
- date
- title
- layout
- categories
- Insert the contents of the article from Ulysses
- Commit the file/changes
- Push to
origin/master
The first two steps involved more work than I’d like to do for publishing. After automating this process, this is the remaining procedure:
- Write in Ulysses
- In Ulysses: Sharing -> “Preview in Text/Markdown” ->
…
-> “Open in another application” - Tap “Drafts” (version 5, it might also work in version 4), then in the Drafts-layer tap “Open”
- Inside Drafts, I access my “Publish article to www.holgerfrohloff.de” action
The rest happens automatically and I am left with an open Safari browser tab pointing at my website.
Another thing that happens: IFTTT watches my site’s RSS feed and publishes new articles to LinkedIn automatically.
At the end I show ideas for further reducing the amount of steps that I will probably explore.
The Workflow workflow
Before going into the actions for Drafts, I want to make a quick detour to Workflow.app. Using Workflow is actually the very first step that happens in the Draft action and I want to show what I am doing there.
As you saw in the original procedure in step 1, I needed to create a file with the title of the article as part of the filename. In Rails you call this a parameterized string. Workflow creates it for me:
It gets the document’s title as input. This is the first line in a Drafts document. It returns the parameterized title. I will then use that output inside an action in Drafts.
The Drafts actions
I actually have and use three Drafts actions:
- Publish article to www.holgerfrohloff.de (the main one I manually start)
- Commit-in-Working-Copy
- Push-in-Working-Copy
The latter ones are run by the first one.
While experimenting and trying to make it work I ran into a problem with Drafts, that I didn’t know how to get around: I could not chain two x-callback-url action steps. If you do not know what x-callback-urls are, I will get to that in a minute.
I researched how other solved that, and stumbled upon this article Automating iOS: A Comprehensive Guide to URL Schemes and Drafts Actions. It’s from 2014 and targets Drafts 4 (the previous version), but the concepts still somehow applied to my problems. The author presents the necessary workaround:
Use an x-success
x-callback-url to call another Action in Drafts, with the runAction
action. Puh. Here’s the docs from Drafts.
What happens is essentially this: Once the action is finished it returns to Drafts (specified so in the x-success
callback) and executes the action runAction
with its given parameters. In URL this looks like this:
working-copy://x-callback-url/commit/?repo={{5minpause.github.io}}&limit={{3}}&message={{broadcast}}&key={{secret-key}}&x-success=drafts5%3A%2F%2Fx-callback-url%2FrunAction%3Ftext%3D%26action%3DPush-in-Working-Copy%26allowEmpty%3Dtrue
The start is the x-callback-url for Working copy app. I execute the commit
action on the repo
5minpause.github.io (my website) with the limit
of 3 (only changes with three files get committed) a message
that serves as the commit message and the secret key
needed to do this at all via x-callback-url. This is a requirement and safety mechanism by Working Copy.
The value passed to the x-success
parameter is url-encoded. This is needed for Drafts to be able to run it. Without encoding it would look like this:
drafts5://x-callback-url/runAction?text=&action=Push-in-Working-Copy&allowEmpty=true
Again, drafts://x-callback-url/runAction
just opens Drafts and tells it to use the runAction
action. The param text
is left empty (but it is required!). You could specify text to be included in your document (that is created as part of the action). I do not need that. action
has the name of the Action I want to run in Drafts. You noticed, that is the name of one of my actions from above. The last param allowEmpty=true
is decisive. It allows me to leave the text
blank and essentially leads to the action being executed just on any document that happens to be active in Drafts. Since the “Push in Working Copy” action is document-agnostic that’s exactly what I want.
But this was already the last step in the chain. I used that because it was easier to describe. The first step actually looks like this:
working-copy://x-callback-url/write/?repo={{5minpause.github.io}}&path={{_posts/}}[[date]]-[[workflow_result]].markdown&text=---%0a{{layout: post}}%0a{{title: "}}[[title]]{{"}}%0a{{categories: "newsletter"}}%0a{{date: }}[[date]]{{ 15:00:00 +0200}}%0a---%0a[[body]]&key={{secret-key}}&x-success=drafts5%3A%2F%2Fx-callback-url%2FrunAction%3Ftext%3D%26action%3DCommit-in-Working-Copy%26allowEmpty%3Dtrue
It starts with Working Copy and the write
action. I specify the path
. Notice the [[date]]
value. This is Drafts-magic, as it automatically replaces/interprets certain values in the URL. The other one is [[workflow_result]]
that is provided by an earlier action step in this action, the Workflow “parameterize text” workflow. The value for the text
param is the contents of the document. It starts with the YAML front matter. Everything written in {{ }}
is put like that into the document, including spaces, without escaping/interpreting it. %0a
means line-break.
At the end you see the “Commit in Working Copy” action being called as x-success
parameter.
The last step is opening the Safari browser at https://www.holgerfrohloff.de and that is simply another x-success={{https://www.holgerfrohloff.de}}
parameter. Since Safari is registered as the receiving app for http/https protocols, it gets used to open that URL.
And that’s the thing about x-callback-urls. There is probably a lot to say about it, but the essence is that apps can register for a certain protocol. Working copy registered for the protocol working-copy://
, Drafts for drafts5://
. Numerous other apps offer this as well. This website offers the spec for app authors to implement and shows a comprehensive list of x-callback-urls for different apps.
This is how it looks on my iPad:
Automating publishing to a Jekyll website using iOS
## Next stepsI have some ideas/things I’d like to try out:
- Automating the removal of the date. If you looked at the video, you saw that I manually remove the date from the beginning of the article. This could be automated.
- Wrap everything into a workflow that I can access/start from the share sheet on iOS. This would essentially remove everything after Ulysses. I would only need to call the action from the share sheet in Ulysses and I would be done.
- Try to improve usage of callback-urls in Drafts. While searching for ways to chain actions in Drafts, I created a topic on the forums: https://forums.getdrafts.com/t/chaining-x-callback-urls-does-not-work-as-expected/2157/2. The support then pointed out that using
Call URL
action steps might not be the optimal way. I should change those to use theCall Callback-URL
action steps inside Drafts. - Support drafting of articles. Sometimes I write these articles a few days in advance. I cannot, currently, publish them without running through the pushing to
origin/master
step.
The big thing remaining is publishing to Drip. Since I use Drip to send these articles as newsletters to my readers, I have to create the on their website and schedule them. Drip offers a REST API that I could probably use from within Workflow app. An alternative would be to use Zapier to create these POST requests after pushing to GitHub. That might also work.
BOOKS I ENJOYED READING
Since I love reading I thought I switch things up for today and share a small list of books I enjoyed (and why I enjoyed them).
All links are no affiliate links.
Principles by Ray Dalio
I mentioned the book before in one of my emails. Reading this book I had the feeling of finding something that speaks to me, more than once. The situation like there was a light bulb lighting up, because you see connections between things you were blind to, before. I know I’ll re-read that book a few times, because I am certain that there are more lightbulbs hidden in it.
Confident Ruby by Avdi Grimm
I read the book too early in my career. I wasn’t ready for it. I put it down. A few years later somehow I remembered it, perhaps I found the ebook on my computer somewhere. I started reading it again. And I couldn’t put it down. Please let me quote from its website, because I definitely couldn’t put it any better:
Confident Ruby is, first and foremost, a book about joy. It’s about the joy I found when I first discovered how elegantly and succinctly I could state problems in Ruby code. It’s about the joy I gradually lost as the “real world” snuck in and cluttered my code with distracting edge case scenarios, error handling, and checks for nil. And it’s about how I came to recapture that joy, by employing small patterns and stylistic choices to make each method tell a coherent story.
Sapiens by Yuval Noah Harari
I picked this up in a book store on Gatwick airport near London. I was heading home from the Isle of Ruby conference and I felt like I should buy a book. It was marketed as a bestseller on some list. Usually I do not pick up books like that. But something made me take it. Perhaps it was Bill Gate’s quotes on the back?
“I would recommend this book to anyone interested in a fun, engaging look at early human history…you’ll have a hard time putting it down.” (Bill Gates)
I honestly don’t know. But I am glad I picked it. I read most of it laying at the pool on Rhodes island. It’s not heavy literature. But it’s a fun read if you are looking for something during the summer. It does answer several questions I didn’t formulate for myself before. Like, how religion evolved and what came before it. Sure there’s the bible, Qur’an, Torah and other texts but did people believe before that? And how did sapiens spread across the world?
Deep Work by Cal Newport
I read that over a year ago. Open office floor plans and their negative impact are discussed a lot these days. An important part of the discussion is people’s inability to concentrate on their work in an open office with many co-workers. This books doesn’t really talk about that. It talks about the opposite of that. It shows you how establishing a deep work ethic helps you produce better results and do more intense work—during your working hours. The author shows you 4 rules you could/should follow to reach a new height of productivity and just work better. While it’s sometimes a bit too much and he takes things a bit too seriously, I honestly applaud the idea behind it. Finding the focus to work better and more concentrated does help me and perhaps that’s something for you as well.
Alright. Are you disappointed because you expected more programming or software development focused books? Ok, then I’ll give you two more of those: Anything by Sandi Metz Both books are great and applicable even if you don’t work with Ruby. They just use Ruby as a simple, accessible example language. But in their essence they teach you the most important aspects of object-oriented software development.
In case you do like one of these books or especially if you completely disagree with me on something, please tell me by responding to this email. And if you have any book recommendations you’d like to share, please also tell me.
Yours, Holger
MAINTENANCE AND JANITORIAL ACTIVITIES
You walk into a room. You haven’t been here before but you need to find something. Your friend told you, that you’ll find it there: “It has to be there somewhere. Please just take a thorough look around!”. You find old snack boxes , papers upon papers and stuff that you wouldn’t want to touch because it looks like it might already be alive. A distinctive smell permeates the room. You don’t want to be in here for too long. But you want to find the thing…! After looking around for 10-15 minutes you notice that you lost track of where you’ve already searched before. The whole mess is just too much for you.
Do you know that feeling? I hope 🤞 you don’t experience that too often. But that’s what I felt the other day when I had to look into an older code base that I worked with a while ago. These are the distinctive characteristics of a code base that wasn’t looked after enough. A code base where refactorings did not happen consistently. Where technical debt was piled sky high and where things were just left how they always were. Because the cost of cleaning up was thought to be too high.
This is what happens, if a team doesn’t have a policy they consistently follow. Every team needs that policy and it’s name is something like this: “Clean up your own mess and clean up anybody else’s. And avoid making a mess in the first place.” Admittedly that’s a bit clunky. 😂 But still. You have to make regular refactorings. Usually the best point in time is, when you reached a new understanding of the business case that you are replicating in your software. When you are writing code you have a certain knowledge about the thing your are building. And this knowledge evolves and grows over time. It’s common to look back at code and notice that the application has outgrown the old code.
Example:
We have Company
s in our application. When we want to import new data into the app, somebody (who’s authorised, but that’s another story 😉) sends an email to a certain email address with e.g. an Excel sheet attached. Whe then parse the sheet and import the data into the app. But only, if the email address is known. How do you test if an email is known? We created an EmailAddress
model and set things up in a way, that a Company
can have many EmailAddress
es. That way we could be certain that different people of the company in question could initiate imports, but we didn’t need to know who it was in the specific case.
Later on we noticed that the companies usually have email addresses with the same domain. It did not happen at all, that employees of a company had email addresses with different domains. So we deleted the whole email address model and all records in the database. And we created a new attribute for the Company
model: domain
(of type string). So now we only check the domain (and tld) of the email and can see if it’s whitelisted.
Simple example? True. But image what that picture could look like if we just added a domain
attribute without deleting the EmailAddress
and the association. People wouldn’t know what they were supposed to use, or which would precede the other.
So cleaning up makes sense. With that in mind, look through your code base. What old entities, things or concepts should you rework, delete or improve on?
Yours, Holger
PS: Another thing you should clean up? Your mom would probably say “your room”. But what about your OAuth authorisations for apps you tried out but don’t use anymore? Have a look at Twitter, Github and other providers you might have used earlier. Some people use this thing called Facebook, I hear. Perhaps you used it to log into things?
PREMATURE OPTIMIZATION
Yesterday I told you about our struggles with the new door bell. While, sadly, this state is still unchanged, there’s another story there that relates to software development: The new door bell needed some power. The old one did not need this much power (230 volts), so there were no appropriate power cables laying around. That’s why we cut a different cable that lay in the vicinity but usually powers the automatic gate for the car. The plan was to have something like a t-shaped connection between the cables. So the gate would still have power, but a new cable would lead to the door bell and everything would be fine™. So I cut the power cable to the gate. What I did not know at the time was, that there are literally t-shaped connectors for power cables (not an affiliate link, just for reference. Don’t buy it! 😉).
Now that the project “door bell” is off the table, I had to connect the underground power cable for the gate again. Which, in the meantime, was missing a bit in the middle, where I made the cut. So I couldn’t just put it together anymore. I needed to insert a new piece of underground cable and connect everything on two sides. Here’s where today’s title fits perfectly: When connecting two cables with a new self-cut cable in the middle. DO NOT, I repeat, DO NOT estimate the needed cable length before connecting the pieces. Just use something that is way longer than you need. Do not try to half-measure everything so it’s just perfect. Otherwise you might be as “lucky” as me: The self-cut piece of cable for connecting everything was too short. Of course I noticed this after I already connected 3 of the four parts, and only had the last part remaining. Did I mention before, that it was already dark outside and the mosquitos swarming around me—squatting and sweating there—with my pregnant wife sitting next to me holding a flashlight, so I could see while holding my face near the soil just to be able to screw the connection-screws into the connection thingy? WTF. The thing was, we needed the gate to be operational so we had the safety of being able to drive the car. Because my wife could give birth now any moment and we need to be in a hospital for that… 🎉
So, enough off my stories. To bring this around to software development: Once again, trying to optimise things before you have the complete picture of the situation, might not lead you to victory and success, but to soil on your face, mosquito bites on your whole body and more swear words than I’d like our daughters to hear. Take care.
Yours, Holger
SPAGHETTI WIRINGS NO-ONE KNEW ABOUT
Over the course of the weekend we tried to install a new door bell for our house. The old system is really old, falls apart and works only some days. So we bought something from a respectable German engineering company named Gira. They make high quality products and we had prior experiences with their parts. We also happen to really like their clean design language. The reviews online spoke about easiness of installation, “connect just a few wires”, nothing can go wrong there.
So… how hard can it be?! (Queue picture of Jeremy Clarkson here, before he got old and rich 😉)
Turns out, we spent large parts of Saturday and the whole of Sunday, more than 8 hours, and achieved nothing. We got the help of my father-in-law as well. He lived in this house before we bought it from my parents-in-law, so he knows his way around the conduits and everything. But! somehow somewhere there are some electrical conduits lying underground here, no-one knows where they are, how they are connected and frankly, how some things are even working at all in the house/garden. Because everything is a mess. Image a junior developer trying to build a complex system that gets things patched onto from other juniors. Then along comes an intermediate trying to improve things, without fixing the underlying mess. Well perhaps you have an idea in your head how it might feel to operate in such an environment. It’s a horror show.
I haven’t felt so much frustration in a long time. One thought lingered in my head throughout the weekend: If only there was some documentation about this electrical chaos! Back, when this house was built and the wiring installed, and than patched onto, and things were modified, the people responsible…well they probably didn’t think much about documenting stuff. Because it was all in their heads, and fresh and “they knew what they did”. But nobody thought about 20 years down the road, when no-one remembered anything. We could have easily installed everything and worked around all the edge cases if only we had some written (or painted, or recorded — I’d take anything by now) documentation.
In my job I am lucky to build applications and software for my clients. The documentation usually revolves around elaborate ReadMes, Wiki texts and images. I’d like to admit, I never had a mentor or teacher who showed me how to properly document software. It was all learning by doing. If you don’t mind, I’ll take some future episodes of this newsletter to document (see what I did there? 👅) my findings and further thoughts about this topic.
What about you? Do you regularly document? Would you mind sharing your horror stories about incidents where docs where missing and you severely felt it?
Yours, Holger
PS: Did you do some weekend programming, some Katas or somethings different? I came across this resource after already writing to you: https://programmingpraxis.com/
LET'S PRACTICE TOGETHER
Where I sit writing this email, today is Friday. So tomorrow the weekend starts. Do you already have plans for the weekend? Perhaps we’ll go to the lake, because it’s scorching hot in Europe these days. But I will also continue with my “Automation project: Factory 0.1”.
Just a short detour what that’s about: I have my website at holgerfrohloff.de and it’s built using Jekyll, a static site generator. I write my newsletters on my Mac or iPad (or sometimes iPhone). I want my writing to appear as an email, sent to you. But it also should appear on my website, without me having to copy and paste markdown files, commit them and deploy it. Then it should ideally be distributed to LinkedIn, Xing (that’s a German LinkedIn 😉) and perhaps Twitter. All automatically. I am building this with three iOS apps and a bit of IFTTT and perhaps Zapier. I’ll tell you about it in detail once it’s finished. It’s a lot of fun for me.
Now to what I wanted to tell you about in this email: I love to have small projects like that. Projects where I can tinker and explore at my one pace. Where I do not have to keep track of the hours spent and where I can just have fun. I believe projects like that keep my relationship with coding healthy, because I can enjoy other sides of the profession as well. I also believe that you might benefit from having small projects yourself. Michael Tsai wrote about Kindling projects in 2015. But it’s still relevant. A small step into this direction (because not everyone might have a project at hand) could be Code Katas:
How do you get to be a great musician? It helps to know the theory, and to understand the mechanics of your instrument. It helps to have talent. But ultimately, greatness comes from practicing; applying the theory over and over again, using feedback to get better every time. But in the software industry we take developers trained in the theory and throw them straight in to the deep-end, working on a project. It’s like taking a group of fit kids and telling them that they have four quarters to beat the Redskins (hey, we manage by objectives, right?). In software we do our practicing on the job, and that’s why we make mistakes on the job. We need to find ways of splitting the practice from the profession. We need practice sessions.
Have a look around at the website (linked above). Perhaps that’s something you’ll try over the weekend? Anyway, have a great one!
THE BULLSHIT WEB AND OUR RESPONSIBILITY
My home computer in 1998 had a 56K modem connected to our telephone line; we were allowed a maximum of thirty minutes of computer usage a day, because my parents — quite reasonably — did not want to have their telephone shut off for an evening at a time. I remember webpages loading slowly: ten to twenty seconds for a basic news article.
At the time, a few of my friends were getting cable internet. It was remarkable seeing the same pages load in just a few seconds, and I remember thinking about the kinds of the possibilities that would open up as the web kept getting faster.
And faster it got, of course. When I moved into my own apartment several years ago, I got to pick my plan and chose a massive fifty megabit per second broadband connection, which I have since upgraded.
So, with an internet connection faster than I could have thought possible in the late 1990s, what’s the score now? A story at the Hill took over nine seconds to load; at Politico, seventeen seconds; at CNN, over thirty seconds. This is the bullshit web.
Do you also build products and things for and on the internet, like me? I do not necessarily want to make quoting people a regular thing here, but the article “The Bullshit Web” makes the rounds on the internet these days. And it spoke to me. You see I do build websites and web apps. And I built them for bigger corporations. And integrating trackers and ad-networks and all this nasty things that slow down the web-experience for our users and makes the web slow and bad…well I included some of them during the last years. Of course it seems like it isn’t always easy to say no to requests like that. The executives of your clients want to have these things, because that’s what their “business models” forces upon them. And most of the times, if you don’t include them, somebody else will. Perhaps you risk the well-being of your employer and the other employees, if you do not do that. Because BigCorp™ will just go somewhere else instead. But perhaps we’ll have to find a way. At least in Germany right now, the market for developers is a sellers-market. That means we as developers can almost freely choose where we want to work. Everybody is looking to hire new devs, the salaries went through the roof and it’s easy to find new work if you accept the many recruiters' offers. So losing your job might be possible, and it’s a hassle to have a new one even if finding one is easy — I know. And still. If anybody has the means to change things and habits like that, it’s us as developers. Along with the companies we work at and the colleagues we work with. I know I am a bit idealistic, I was with the GDPR before, and I am again now.
When discussing with clients who want to have all these trackers and beacons… I was thinking about how one could argue that getting rid of them is in their best interest. One thought that came to my mind is, that these models aren’t as successful for (e.g.) newspaper companies, as they’d like them to be. A few of them (New York Time for example) try to make a subscription model work. You pay them a monthly or yearly price and get access to more content. I believe that users are more willing to pay if their experience is better, I they enjoy the product more than the alternative of not having it. And their target audience is people who value quality-news enough that they are willing to pay for it. And they have the choice between many on-surface similar offers. Couldn’t an offer that separates itself from the others because it values the user’s experience, the speed of the offering, the low barrier for entry, the usability for disabled users more than anything else? Doesn’t a crowd, that’s composed of these millions of users, who stand behind this description I just made, look large enough to be able to finance an online-venture like that?
I am not sure. But I’d like to find out if it’s possible. And that starts with saying no to requests for trackers, beacons, advertisement-networks etc and offering an alternative and a healthy discussion about the pros and cons.
With my clients, I’ll certainly do that even more now. So thanks for the article and the initiative, Nick Heer.
What will you do? Do you care about that?
WHEN DO YOU KNOW ENOUGH?
“When did you reach the point where you didn’t need to read another research report, didn’t need to absorb another scouting analysis, didn’t need to stop by the bookstore… because it simply wasn’t useful or efficient to learn another thing about your field?”
This question was posed by Seth Godin. Seth is big in marketing and entrepreneurship. Perhaps you already know him.
This question is a deep one.
As I already told you, I am an Architect personality. One of my traits is the constant urge to improve, to learn more and to get better. So my impulsive answer to this question is “never”. This is only half the truth though. Of course it reads better if I tell you that I never stop learning. But it would be a lie.
I’ve worked as a professional software developer for over 10 years now. I started as a novice, not even junior level, developer. I learned and evolved into a senior and now I am at a level where I can work as an independent consultant with my clients. I thought about going back to university to get a Master’s degree. But I do not want to. I believe the trade-offs are not worth it for me. I am glad I do not need to sit somewhere anymore and learn or absorb some knowledge from someone.
That said, just yesterday I had to research something with testing async functions in my Redux action creators. I use fetch for querying the API, and wanted to test the action creator that dispatches the other actions.
(This is the code I wanted to test, but simplified)
export const fetchApiData = (productId, params = {}) => {
return (dispatch) => {
dispatch(requestApiData(productId))
const url = `/api/v2/products/${productId}`
return fetch(url, { credentials: 'include' })
.then(response => response.json())
.then((json) => {
dispatch(requestApiDataSuccess(productId, json))
})
.catch((error) => {
dispatch(requestApiDataFailure(productId, error))
})
}
}
The test was supposed to make sure, that the correct action was dispatched on success and on failure. But I have to admit I couldn’t do it. I spent around 2 hours trying to use the library fetch-mock
like in their example. But my BabelJS setup wasn’t able to transpile the code. So async
and await
always produced syntax errors. Node v6 just can’t handle them properly.
I tried different plugins and presets for Babel always without success. If Google offers it as a solution and if StackOverflow says to try it like that, I did…
In the end I postponed this and will try to debug it with a colleague once he comes back from vacations. I read, I learned, I tinkered, I tried. But with no success. Just a lot of frustrations.
So to answer to initial question: In our field we never really stop learning. We might pause for weeks or perhaps sometimes months at a time, where we just use our knowledge to create things. But in the end there will always be problems and tasks where we must learn something new.
That’s one to the things I love about my work. Do you have similar experiences?
Holger
PS: If you happen to know a solution for my Redux problem or have sample code that I can adjust, please don’t hesitate to share it. 😉
PROFESSIONALISM
This morning I was visiting the hospital with my pregnant wife. She’s in the 39th week and over the course of the weekend we had some concerns regarding the health of the baby. So we went to the hospital to have everything checked. They made a CTG for the heart and vital signs of the baby.
This feeling when you’re worried about something mostly out of your control… feeling helpless. And then the doctors and midwifes help you and take care of you… This is a very strong feeling and emotion. The professionalism that they show in calming you down and making sure you’re alright.
If you ask me, that’s what I aim for with my clients. They don’t have to worry about our project, because I am there and taking care of everything. That’s my mantra.
What’s yours?
THE 4-DAY WORKWEEK
In this enlightening article from the New York Times, Charlotte Graham-McLay reports about a company from New Zealand that tried something out. They switched all their employees to work only 32 hours per week instead of the regular 40 hours. All of them still received the same salary for 40 hours though. What they found was that their productivity increased and the employees got the same amount or work done. Sometimes even more. To reach this level of productivity, they reduced meeting times, didn’t leave early or took longer breaks.
This experiment was studied by two researchers, one of them said:
They worked out where they were wasting time and worked smarter, not harder […]
There are so many interesting takeaways from this article. I will definitely come back to it and talk about topics like billing time for work done (a topic of interest to me as I am working as a freelancer since January) and finding motivation and smart-working.
For today I would like to think about the topic productivity. How can I do more work in less time? My wife will give birth to our second child in a few days. As a result I will reduce my billable time by quite a lot, to have more time available to spend with the family. Still I want to be able to charge my clients enough money so I do not experience a drastic cut in revenue. So this makes me look for ways how I can be more productive. If you want to improve some condition, you need to measure it. Otherwise you don’t have any way to find out which actions improve your condition and which worsen it. So now the question is: How do you measure your productivity, when you are writing code, creating features, delivering software (pieces) to your client? One simple, almost obvious, measure might be how much you code. So this could be the lines of code, that you are producing. I feel like this might be a delusive metric though. I like brevity. I do not favour brevity over explicitness/clarity, but I try to write less code. In the sense of coding smarter, not harder. Equaling more code with more productivity makes no sense for me in that way.
I also like to commit early and often. My commits are usually small and concise. In so far it could be a metric to count my commits. Now I think I could increase my productivity by committing even more. Without changing anything else! It would also put others in a bad situation, if they just happen to commit less, with bigger commits. Regardless of whether I’d like that way of committing, they would appear to be less productive than me, even if the weren’t. I guess counting commits does not make any sense then, for me.
Then I thought of another metric: The number of opened pull requests. I believe, now we are getting somewhere. Every open pull request tries to improve the status quo of the software. It could be a new feature, or just an addition. It could be bugfixes. It would be work-in-progress branches or just spike solutions where things are tried out. But every new pull request you open shows that you did real work, for the benefit of the project. So I do hope your team is doing pull requests, and I do hope you have a good review process. Because I think this really is a nice metric of productivity. Perhaps we should only count merged pull requests, not opened pull requests? Because a merged PR shows that your changes were accepted and really brought the project forward.
I do not have a better metric to measure my productivity than merged pull requests. I think it’s still not the perfect metric—what happens if your team partners are on vacation, or sick and the review process hangs? This makes your PRs stale… But this metric will be the one I’ll keep an eye on during the next few weeks. For now I’ll just count the PRs by hand and keep track of them in a spreadsheet. If it turns out to work well enough for me, I might use GitHub’s API to automate that.
Please tell me about your metrics. How would you track your productivity? Perhaps you already do?
Holger
SORRY TO SAY, BUT YOU’VE BEEN HACKED
Please excuse this email’s subject line. Did you receive an email like that before? As I wrote a few days ago, I did.
More than a few times. That’s why I see that I use two-factor authentication for every service that offers it. If you do not know U2F (Universal two factor), this means that after providing a service with your login and password, you’ll also need to provide a one-time password (OTP) from a trusted source. This makes hacking into your accounts (for instance through social engineering) way harder. The OTP usually is in your hands and cannot be easily stolen, since this OTP only has a lifetime of a few seconds. Afterwards it’s invalid and a new one is needed.
This works because you can have an app on your phone, that presents you these OTP for your different accounts. This is the way I have done it the last few years.
- Navigate to website or open an app
- Use Password-Manager integration of my OS to access my credentials
- Paste credentials and confirm
- Open app on phone (Google Authenticator) that presents me the OTP
- Copy and paste the OTP into the form field
- Access my account
Well, it’s no wonder only few people use that! It’s a hassle and no fun.
Ok, but there’s a better way. I always try to do things better and more efficiently. And this process surely needed some improvements. What can I say, they were there all along, I just didn’t know! There are hardware devices that can act as your U2F and provide you with the OTP right on time. They come as USB, USB-C and NFC compatible devices (not all in one, though). They can be used with your computer and with your phone (through NFC even with new iPhones). Chrome supports these devices for a few years already. Firefox does support them as well, although you have to enable it yourself!
The steps now look like this:
- Navigate to website or open an app
- Use Password-Manager integration of my OS to access my credentials
- Paste credentials and confirm
- Tap hardware usb key and have it automatically enter and confirm my OTP
- Access my account
Ok, but there’s an even better way! 🤓 I do use 1Password as my password manager (and you should too!). 1Password supports OTP-fields when entering credentials. You can scan the barcode using 1Password when setting everything up. Now 1Password completely takes over the second factor:
- Navigate to website or open an app
- Use Password-Manager integration of my OS to access my credentials
- Paste credentials and confirm
- 1Password automatically copies the OTP to my clipboard and
- I just paste and confirm again
- Access my account
While this seems like on step more than the hardware key thing, I do like it very much. It syncs across your device, works on all OS’s and you don’t have to fiddle with a small USB/NFC device. You can’t forget it somewhere, because that would endanger your accounts very much…
The U2F devices have other benefits as well though: You can use them to sign your Git commits with them to make it cryptographically unfeasible to tamper with them. This shows as “signed commits” on GitHub.
If 1Password isn’t your thing, there are other managers as well. I bet they implement it in very the same way. If you have other recommendations or experiences, please let me know.
Now go forth and U2F all the things!
Holger
THINGS HAPPEN FOR A REASON
I am currently reading a very interesting book: “Principles” by Ray Dalio It was recommended to me by several sources, most notably by Sebastian Marshall. Sebastian focuses a lot on personal improvement in his work. I value his ideas and ideas very much. So it made sense to me to follow his recommendation to read this book.
Ray Dalio writes about his personal journey towards being one of the most influential and successful investors in history. On his way he made several mistakes, but he often recovered and eventually found his way to success. His work and life principles made all the difference for him. He evaluated himself in several psychological tests, as well as all his partners and employees. This way they could find out how this group of people was “wired” and how they could best work together. Ray encourages the reader to take some of these tests as well, to find out how you, the reader, thinks. What are your weaknesses, what is against your personality? Where do you excel at?
Once you identified your weaknesses you have at least three options for dealing with it :
- Ignore it
- Get better at it
- Delegate to people more capable than you
The first is the easiest and shouldn’t really be an option. The third might be a good solution for a few situations. If you know about this weakness, you are in a situation to find a solution because it’s not a blind spot anymore. So delegating this topic really might be the best option. The second option is the hardest, but might also offer the greatest reward. To get better at your weaknesses you have to constantly work on them.
Here’s one of my weaknesses that I found out about: I like to do high-level planning, create great strategies and execute on them. When it comes to the lower-level details of implementation I often get bored. I am a perfectionist in my work, but once things are at ~80% I tend to lose interest. This is a general trait of my character. I tested as an Architect.
I believe this sometimes shows in my work as well. I do not generally procrastinate, but I do not like to do repetitive tasks or more low-level stuff. I am thinking about writing all kinds of variations of tests, for example. I surely write the happy-path and the 80%/necessary tests, but I would rather take on the next task than bring test coverage up to 100% with all these tiny edge-case-tests… Also waiting on tests to complete… I’d rather continue reading my book! I believe I am not alone in that, but anyway.
Because I am feeling confident that “escaping from repetition or boredom” is a weakness of mine (just to give it a name 🙃), I devised a simple strategy for dealing with it. This email is rather getting long, so I will write about my strategy (and how well it worked) another time.
What about you? Did you take any personality tests? Do you know about your weaknesses (and strengths! These are also important to know)?
Holger
TEST DRIVEN DEVELOPMENT
Test-driven-development. There’s no other way to do this.
Always write tests first! Always have failing tests before writing the code! Write code in small iterations.
Write the next failing test once the first iteration passes the test. Repeat until finished.
That’s how you do it.
Or not.
You can write your feature, your code. And write a test afterwards. Like a regression test. Sometimes that’s what you do, when you use snapshot testing for React components.
Either way it’s your decision as a professional to make what way you want to develop and test. You get paid to make the right decision, but it is your decision to make. Not somebody else’s. Please don’t forget that. Don’t run around and blindly spread the gospels of our software dev gods. You get paid for thinking and without thinking we could have a machine write the code for us.
Holger
SOFTWARE DEVELOPMENT ON CONSTRUCTION SITES
A few days ago, a friend told me about the construction site that is located right outside the window of his living room. He was, understandably, complaining about the construction workers starting their shifts at seven in the morning. They make all kinds of noises and it’s costing him his nerves.
While I couldn’t do anything to improve his situation, I absolutely understood what he was going through. And after a couple of days I happened to be on my way to passing the construction site. I was doing some running and it was convenient to just pass along there. I thought, I should really check out this site. After all, they must’ve already finished a lot, if they’re always building and doing things. When I passed the site, it was empty. It was quiet. There was nothing going on. My run was in the morning, I passed the site at around 8:30am. Well so much for that! 😅
This made me think: I had heard a generalization from a trusted source and had assumed it was true. I had made further (innocent and unimportant) choices based on that generalization. Do we do that a lot? Do I do that a lot?
Turns out, probably more often than I thought.
Example: In my current project, I am building a BI dashboard for my client. My latest task was a new widget displaying numbers about some products in a nice chart. It was actually a different way, displaying slightly different numbers, for another widget that was already present. The new one took the same numbers and looked at them from a different angle. At least that’s what my client told me in the initial briefing. The name of the new widget and the sketches and wireframes that I based it on all told me the same thing: The widget’s source data is the same as for this other widget.
Only, it wasn’t… Once again I took a “simple fact”, trusted it and noticed later that the source of the fact was wrong.
In the end that wasn’t a big deal. It was easy and quick to correct and the client even noticed that he was the source of this. But! I could have noticed it sooner, if I had asked more questions. (More of the right, important questions. Which these are is a topic for another email, though…)
Do you have situations like this as well?
Holger
DID YOU JUST CLICK THE LINK?
perhaps you remember one of my last newsletters, back when I wrote them from the 5minutenpause.com domain. I told you that I switched the content format to plain text and that I do not track click and open rates anymore. Well I do again.
Change your opinions, keep to your principles; change your leaves, keep intact your roots. — Victor Hugo
I write lots of text in English. These are mostly texts like this, or documentation for software I’ve written or discussions on Pull Requests, stuff like that. But I also write German, in the texts with my wife, in emails to other Germans etc. When writing software code, I tend to use the U.S. keyboard layout. It just so happens to be easier to use for development with its placement of characters necessary for development. But I also need the umlauts when writing German words. So I switch a lot of times between the layouts. It’s fairly easy on Mac OS, I just press the shortcut Ctrl-Option-Space (you can set this in the System Settings). But since I switch between different apps a lot during the day it always incurs a small overhead for me to see if I have the right language selected and change it if necessary. Or it happens that I just begin typing, only to notice mid-sentence that it’s the wrong layout. So I automated that!
Whenever I switch apps now, the computer automatically switches to the (most of the time) correct layout. My IDE, editor, terminal and other dev things have the U.S. layout, most other apps have German. My browser (Firefox) is a standout as it depends on the tab that’s open which language I need. I tried to automate that as well, but it isn’t perfect yet—tab titles change all the time… If you’re wondering how I did that, I use Keyboard Maestro for that. It is a really “not so pretty” interface, but it works alright.
The other automations/shortcuts I created recently involve my keyboard launcher Alfred. But that’s a topic for another day.
Holger
GDPR, OR: HOW I STOPPED WORRYING AND LOVE MY USERS
A few days ago I received an email from my bank where I keep my business account (n26 if you want to know), informing me that my personal details including email address, first and last name and telephone number were stolen during a hack that occured at Typeform.
This marks the latest installment in a series of emails and events that date back to around 2009. Since then I received emails about hacks at companies that kept my data almost yearly. I am fed up with that. But there is little I can do myself. Gladly the EU has my back, well more or less…. The GDPR came into force on May 25th and now things will change? Depends on the people! Everywhere you could hear developers screaming and cursing about this regulation and the amounts of work they had to do to appropriately deal with it. While I do understand them (I had to do the same work on my business and websites and on my clients’s) my standpoint is a little different. I am an optimistic person who always sees the light and tries to find ways to optimize or at least improve situations. And the GDPR represents on of those. You see, you have to deal with these things required by the regulation anyway. You can’t escape them. So let’s take the opportunity and do the work necessary to fulfill the requirements, and then some. The regulation offers enough single points that you can take and make your systems more secure. It offers you ideas that you can take to your manager to get the clearance the implement them, that reduces the risk for your customers if you ever get hacked. And for many of these points you have to implement some simple version anyway. Why not go the extra mile and take care of the important stuff. Like, treating your customer’s data with the same confidentiality and importance as your own business data?
Okay enough rambling about that. Because I really like that topic I even gave a talk about it at the Isle of Ruby conference in April. You can find my slides here: https://www.slideshare.net/5minpause/gdpr-or-how-i-stopped-worrying-and-love-my-users
If you want to talk about that some more, please feel free to write me an email.
Holger