DEV Community

Miyuki Tuisku
Miyuki Tuisku

Posted on

Human-Friendly Programming

Some believe that we programmers decided to do what we’re doing, because we don’t have to interact with other humans.

meme about being a programmer

But is it so?

I believe not.

Background

As a developer of a SaaS product, I have been thinking about why reviewing some of the Pull Requests (PRs) has been more difficult or demoralizing than others and this is the conclusion I've come to.

I would like to call the concept Human-friendly programming.

It is nothing new, super flashy nor shiny. But hopefully more powerful than you think.

What is Human-friendly Programming?

The basic idea is really simple.

Your programs are FOR HUMANS.
Enter fullscreen mode Exit fullscreen mode

A darker and cynical version of that would be:

Your colleagues ain't your therapists.
They ain't bothered figuring out what you think.
Enter fullscreen mode Exit fullscreen mode

Your codes will be read, reviewed, and maintained by people (including you). Duh.🙄

“The Art of Readable Code”, one of the go-to programming books of all time suggests:

The code should be easy to understand.

Here’s another quote from Martin Fowler.

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

Yeah, yeah. We already know that, right?

But yet, I’ve seen many fairly experienced programmers work like they aren’t bothered by that.😢

So what exactly are we supposed to do?
I’ve come up with some suggestions, and I’ll explain them in the next chapter.

What are the Practices of Human-friendly Programming?

  • All of the code examples are written in Javascript and React. But I believe the essential concept would be universal.

The following is a list of some of the fundamental key rules I would like to present to make your PRs human-friendly. I’ll explain each with an example.

1. Name It Like You Mean It

🥶 Non-Human-Friendly Way

const onClick = () => {
  const data = getData();
  clickCallback(data);
}
<Button onClick={onClick}>Hooray!</Button>

Enter fullscreen mode Exit fullscreen mode

Let’s say your colleague asked you to review their PR, and you find these lines of code.
Do you get what happens when you click the button?

😶‍🌫️ What I See

const whatever = () => {
  const thing = getSomething();
  youFigureItOut(thing);
}
<Button onClick={whatever}>Hooray!</Button>

Enter fullscreen mode Exit fullscreen mode

When I see codes like that, what I see in my head is this. (I know I’m being cynical here. But I’m just trying to make my point.)

😍 The Human-friendly Way

const createTodo = () => {
  const blankTodoData = generateBlankTodoData();
  setTodoInServer(blankTodoData);
}
<Button onClick={createTodo}>Hooray!</Button>
Enter fullscreen mode Exit fullscreen mode

This looks MUCH BETTER to me. I can clearly see what happens when you click the button, and the setTodoInServer is trying to set blank data in the server. You can tell if the code is not behaving that way.

2. Use Comments to Explain What the Code Can’t

Ultimately, self-explanatory and understandable code without any comments are the best, so people should work on them first.

But sometimes you have to make some completely random implementations in completely random places.
And the chances are, your future self let alone your colleagues will have no clue why you had made such exceptions.

Except for, if there’re comments about it.

🥶 Non-Human-Friendly Way

const addTodo = async(todo: Todo) => {
  setInLocalState(todo);
  const todoData = await saveInServer(todo);
  setInLocalState(todoData); //NOTE: set saved todo data in local 
}
Enter fullscreen mode Exit fullscreen mode

😶‍🌫️ What I See

const addTodo = async(todo: Todo) => {
  setInLocalState(todo);
  const todoData = await saveInServer(todo);
  setInLocalState(todoData); //It's a complete mystery why it is setting the local state again
}
Enter fullscreen mode Exit fullscreen mode

The Problems

  1. It does not give any information
    The comment exists for no reason. I’d know what the code is doing by the name of the function by looking at the code. We want to know why you did it. It makes the code confusing and difficult to understand.

  2. Makes the code more vulnerable to be broken in the future
    If people don’t understand why the code is doing what it’s doing, there is a chance that they will modify the code and break it. Trust me, it happens. I’ve actually done it myself and learned a lesson (that time actually there were no comments, so it’s even worse).

  3. Codebase gets messy
    Not only it is useless, but it is violating the cleanliness of the code. Codes should be simple and clean.

😍 The Human-friendly Way

const addTodo = async(todo: Todo) => {
  setInLocalState(todo);
  const todoData = await saveInServer(todo);
  setInLocalState(todoData); //NOTE: setting id generated in server, which is required for updating
}
Enter fullscreen mode Exit fullscreen mode

I don’t know if there is a case like this realistically, but at least you know why setInLocalState is called twice.

3. Write Git Commit Message for Documenting

Bad commit messages.
This is one of the things I run into the most. And I have to admit, I find it very difficult to get it right myself.

🥶 Non-Human-Friendly Way

  • quick fix
  • add button
  • fixed because of review comment

😶‍🌫️ What I See

  • something was wrong
  • what the button is for, is for you to figure out
  • someone pointed out there is something wrong with my code

The Problems

  1. It does not give any information
    Like the useless comments, the message does not explain why you’ve made the change.

  2. Makes the code more vulnerable to be broken in the future
    Again, like the bad comments.

😍 The Human-friendly Way

  • 🐛 hide deleted todos from todo list
  • ✨ enable creating todos from todo list page
  • ♻️ use common utility function to create blank todo

One tip I read in this article(Japanese) is that commit messages should explain what the program does instead of what the programmer did. So instead of (the programmer) added button , write **(the program) **enabled creating todos from todo list page .

Having your own rule for prefixes to categorize the commit type is handy. Emoji prefix helps you understand what the commit is about at a glance. For example, if you see ♻️ then you know that the behavior should not have been changed. Our team is highly inspired by gitmoji, but you can have your own rules. Conventional commits is also a powerful way to make your commits sorted automatically and make it readable for humans.

4. Make Pull Requests With Care

This one is also one of the most common and most difficult ones.

🥶 Non-Human-Friendly Way

  • Hundreds of lines of code in a single pull request
  • The pull request is doing too much shit (e.g. creating, listing, and deleting todos)
  • This is what the pull request cover looks like: Image of pull request cover

Ugh. There is nothing more demoralizing than getting this kind of review request.

😶‍🌫️ What I See

  • You don’t care about how difficult and time-consuming it is for others to go through the entire codes
  • You are not even bothered to explain how this PR’s supposed to affect the program
  • No specification about how it’s supposed to work whatsoever

The Problems

  1. More risks for overlooking mistakes
    The more codes you have to check, the more likely the reviewer will miss mistakes in the code. Moreover, it doesn’t help if you don’t give them any information on how it’s supposed to work.

  2. Takes more time
    Some think combining pull requests and having them reviewed once will save time. I really doubt that. Because firstly, it takes time to go through, so the feedback cycle takes a longer time. Secondly, you’ll have more chances to get more comments, so it takes longer to modify the code. Commenting on multiple topics (in this case about creating, listing and deleting) at the same time makes the communication super cumbersome. You should always stick with smaller feedback cycles.

😍 The Human-friendly Way
Luckily, we can make a template with GitHub and many other git management services.
Here are some part of the template we use in the team.

# Why
- Some users want to see only todos that aren't completed and some wants to see all of the todos including completed ones

# Summary
- Create a toggle button to switch between "show allevery todos including completed" and "hide completed todos"
- Set default as "hide completed todos"
- Exclude completed todos when "hide completed todos" was chosen

# Test 
(Ideally this should be automated...)
- Completed todos DO NOT appear on the list when "hide completed todos" is chosen
- Completed todos DO appear on the list when "show alevery todos including completed" is chosen

# Related Links
- Link to the UI design file
- Link to the conversation about the specification

# Screeenshot
(Screenshot to show a grasp of what has changed) 
Enter fullscreen mode Exit fullscreen mode

Conclusion

These practices are just a few examples. I believe there are loads of ways to make your code more human-friendly.

But the main point is again:

Your programs are FOR HUMANS.
Enter fullscreen mode Exit fullscreen mode

Whatever you do, if you answer these questions with a “Yes”, then that is the human-friendly way.

  • Would you understand your code a year later?
  • Did you explain what the code does in your commit messages?
  • Would you understand what the PR is about without context?
  • Can the reviewer finish reviewing within 10-20 mins?

Top comments (0)