Hi, my name is German, and this is my first article. I am a professional software developer since 2015. I am also a regular reader and productivity geek. At least I am the top 1% Todoist user for the last five years.
For the last 12 years since my first year in university, I’ve been looking for ways to become more organized: to forget less, to cope with more. This constant strives to discover a way to productivity lead me to some treasures in my bag of cognitive instruments. This bag became big enough to share with someone else.
Also, when thinking of my practices a while ago, I’ve coined a term to describe me: turbobureaucrat. It reflects two things: I am for sure a bureaucratic person comparing to others. But, on the other hand, I want my bureaucracy to be fast, and here is why “turbo” comes in.
Usually, when discussing how actual coding happens, it sounds like a famous meme about drawing an owl.
As the first step of coding, you need to touch your keyboard, and then, voilà, you open the pull request. I’ve read a couple of books about coding practices, and they tell us about the good and the bad, but much less often about how I can structure my coding activity. So how do I make sure that I don’t miss something important?
The lack of visible approaches and some of the problems and questions I faced led me to introduce a helpful and flexible checklist. It fosters me to keep a high level of quality of my code. It takes a significant part of the cognitive load off my brain and lets me concentrate on low-level details. At the same time, I am sure that the high level is covered. This assurance in your external memory is essential for famous productivity practice: GTD or Getting Thing Done.
Now to the problems and questions I faced at the time of the checklist’s creation:
At this point, it is necessary to say that there is a pre-condition for the described process. First, you need to have a well-defined task that you are approaching. It could be Jira or YouTrack ticket, Trello card, etc. Or at least you need to discover the unknowns and find the information about them. We’ll do so during the upcoming approach demonstration.
Here is how my checklist looks:
1. Put
<task id>
to “In Progress”<task id>
<task id>
<task id>
<task id>
to “Review”<task id>
to “Verify”<task id>
on different environments<task id>
to “Done”Let’s look closer at the steps. First, there are essential and documentary parts of coding. Steps 1, 7, 9, and 11 are all about documentation. They help others see my progress and make my manager happier.
Steps 3 and 4 are about Git practices. You might see another interesting thing here: I need to write the commit messages before coding. This unusual practice limits the scope of your commits and makes them granular. It helps you avoid the delivery of 1000 lines of code without meaningful explanation. I discovered preliminary commits practice in the “Git Essentials” book by Ferdinando Santacroce and found it so helpful that I decided to include it in my checklist.
Steps 2, 6, 8, and 10 are the parts where coding and verification happens. They are the core parts of this process.
What about step 5? Why is it empty? This one is the place where you put your understanding during step 2.
The checklist above is a practical tool, and now we’ll put it into practice to see how the action happens.
The list above covers different software practices, and during the step-by-step demonstration, I would need several instruments:
As said above, there is a pre-condition of having a well-defined task, so here it is. The goal would be to implement a simple Card component for our React application. I am a front-end developer, and this is the reason for choosing the UI development example. However, the approach is perfectly applicable for server-side development.
The requirements are the following:
Basic Card
Emphasized Card
Are these requirements sufficient for us to implement what’s needed? Not yet, we also need to cover the edge cases of the displayed data:
At first, you might think that these questions take us away from reaching business goals. There are too many of them, and the analysis is too massive for a simple problem, and so on. If you need to move fast and break things, then your suspect is valid. Don’t take this approach. Instead, implement the most straightforward way and verify your hypotheses as soon as possible to uncover working business strategies.
Once you have working business strategies and ready to increase your product quality, please welcome the detailed investigation of the possible edge cases.
How do I make sure that all of them are covered? I use a pinch of combinatorics. For the title, we have three meaningful cases:
For the textual part of the Card component, the cases are similar:
Using a table help discover all mutual cases.
Are there any other edge cases that we didn’t cover? Sure! I can think of words too long to fit the available width for text or some mysterious UTF characters. The more understanding of the input values we have, the more edge cases we can imagine.
Also, there is an implication that the size of our card is static. But it could appear in such a situation where the screen is too small. We can cover some of the risks using modern approaches to components’ styling, but we couldn’t cover them all. You cannot make your component perfectly fit all the devices. At some point, you need to stop. And the decision to stop is not technical. It’s a business decision.
Now it’s time to decide that the extra edge cases with long words or UTF aspects won’t receive attention in the upcoming solution. The goal of this post is to present the approach and not to develop an all-threats-proof card component.
This section covers two steps: mechanical putting of task into progress (step 1) and documenting the understanding of the actions required to achieve our goal (step 2).
The Card moved to “In Progress” stage
The task moves to “In Progress,” and thus, we’ve covered the visibility to the manager part. Here is how our checklist looks after completing the first step:
1. ✅ Put Task #1 to “In Progress”
2. 🔲 Understand the actions required to implement Task #1
3. 🔲 Write the commit messages for Task #1
4. 🔲 Create a branch for Task #1
5. 🔲
6. 🔲 Verify the correspondence of the implemented solution to Task #1
7. 🔲 Move Task #1 to “Review”
8. 🔲 Pass the review of Task #1
9. 🔲 Move Task #1 to “Verify”
10. 🔲 Verify Task #1 on different environments
11. 🔲 Move Task #1 to “Done”
Phew, one task less, cool! Not so soon. Our list will now grow as understanding comes. 😈
1. ✅ Put Task #1 to “In Progress”
2. 🔲 Understand the actions required to implement Task #1
3. 🔲 Write the commit messages for Task #1
4. 🔲 Create a branch for Task #1
5. 🔲 Implement card basis
6. 🔲 Implement title in basic style
7. 🔲 Implement title collapsing when its size is 0
8. 🔲 Implement title cut with an ellipsis when it is too big
9. 🔲 Implement text in basic style
10. 🔲 Implement text collapsing when its size is 0
11. 🔲 Implement scrolling when text is too big
12. 🔲 Ensure card collapsing when both title and text are missing
13. 🔲 Implement emphasized styles for card
14. 🔲 Verify the correspondence of the implemented solution to Task #1
15. 🔲 Move Task #1 to “Review”
16. 🔲 Pass the review of Task #1
17. 🔲 Move Task #1 to “Verify”
18. 🔲 Verify Task #1 on different environments
19. 🔲 Move Task #1 to “Done”
Now we documented the understanding of the path to complete the Card component. We also profoundly felt why front-end development and programming, in general, are complex. It’s because of the options that you can’t see but need to imagine.
The list contains 19 items after we did the documentation of the understanding. It’s OK to be overwhelmed — we started working on a simple component, and things turned complex. This complexity is a tradeoff that we pay for a lowered number of omissions and bugs in the end. I once used the method for the feature accompanied by colossal refactoring. I’d changed 100 files and then passed my update to the QA department. They were testing it for two weeks, and it never came back to me. My team leader and I made a bet, and I won a pizza in the end! 😄
This approach also makes you think of component creation as of investment. Thus, the temptation to accidentally reimplement something in an ad hoc way gets blown away. From this point, it’s easy to start thinking of a components library or a design system. Before navigating further, let’s update the list:
1. ✅ Put Task #1 to “In Progress”
2. ✅ Understand the actions required to implement Task #1
3. 🔲 Write the commit messages for Task #1
4. …
We did a great job documenting what we need to do. But, to spoil it all, just hide it. No, don’t do this. Doing so is meaningless. Now put the checklist somewhere where it’s always visible. It now represents the visible path to the desired point. Trying to remember it will break the whole idea of utilizing external memory to free your cognitive power.
Please, keep it always visible.
Writing good commit messages sometimes is a trick. You’ve done a bunch of stuff, some updates here and there. So how to characterize them in a single commit message?
You need to understand something to name it well. If you do not know what you’ve just accomplished, then you cannot characterize it meaningfully. But we have everything we need, and here are our commit messages:
We have step 12 missing as we don’t know yet if we need to add something to ensure the component collapsing. We’ll see when we come close to it.
These commit messages do not represent what we can call the diverse literary language. They are monotonous and dim. These messages are the bureaucratic side of our multidimensional programming coin. The price I propose to pay for getting robust results.
1. …
2. ✅ Understand the actions required to implement Task #1
3. ✅ Write the commit messages for Task #1
4. 🔲 Create a branch for Task #1
5. …
Coming up with the branch name is also straightforward once we know what we plan to do in general. I would use the following:
git checkout -b task-1-create-card-component
2. …
3. ✅ Write the commit messages for Task #1
4. ✅ Create a branch for Task #1
5. 🔲 Implement card basis
6. …
We are ready to write the code, hurray! Let’s open the code editor and create the component we need. The theme of this post is the approach to coding so that I won’t dive deep into React, TypeScript, HTML, or CSS. We’ll go through as many details as needed to feel how the described approach works, but no more.
4. …
5. 🔲 Implement card basis
6. 🔲 Implement title in basic style
7. 🔲 Implement title collapsing when its size is 0
8. 🔲 Implement title cut with an ellipsis when it is too big
9. 🔲 Implement text in basic style
10. 🔲 Implement text collapsing when its size is 0
11. 🔲 Implement scrolling when text is too big
12. 🔲 Ensure card collapsing when both title and text are missing
13. 🔲 Implement emphasized styles for card
14. …
Our little application will have a single card element centered on the main page. It will include background color, shadow, title, and text. Code structure will remain as simple as possible, with no sophisticated folder structure or layered CSS architecture.
The basis of the card consists of its box, background color, and shadow. So, let’s start with this. Some React, some TypeScript, and CSS, and here we are, with the card component basis.
It’s time to do some administrative work: create a new commit and mark this task as completed. And we already have the
commit
message for our accomplishment.git commit --message "Task #1: Implement the Card component basis"
4. …
5. ✅ Implement card basis
6. 🔲 Implement title in basic style
7. …
The card title is the first part where we applied additional analysis. All the required variations will appear under the same commit. Do you remember that the checklist should always be visible? We see the following in it:
5. …
6. 🔲 Implement title in basic style
7. 🔲 Implement title collapsing when its size is 0
8. 🔲 Implement title cut with an ellipsis when it is too big
9. …
First, let’s implement the basic title. During its creation, I noticed that I do some actions related to the whole project, not to the single Card component. For example, I added the following CSS rules to make the
border-box
box-sizing
style the default one::root {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
Doing so is OK. At the beginning of a project, the solutions that we might call architectural occur very often, and at this point, I don’t see a good reason to move them to a separate commit. My commits are not conceptually pure, and I accept this. However, they still aim at a very specific goal. Also, if you always accompany your development by refactoring, you can’t avoid this impurity. This side effect is the unavoidable part of the “Leave it better than you found it” approach.
Here is our naïve implementation of the title:
5. …
6. ✅ Implement title in basic style
7. 🔲 Implement title collapsing when its size is 0
8. 🔲 Implement title cut with an ellipsis when it is too big
9. …
We don’t commit now, and we move forward. Our next goal is to have the title collapsing for zero length. It turns out that this already works. We still have the element in DOM, but we don’t see it. I don’t have enough knowledge or information to decide if this is appropriate or not. The future will help us to resolve the ambiguity. Or not.
5. …
6. ✅ Implement title in basic style
7. ✅ Implement title collapsing when its size is 0
8. 🔲 Implement title cut with an ellipsis when it is too big
9. …
Title cutting won’t happen by itself as the title collapsing. We need to apply some additional styling. After making the necessary update, here is the result:
Congratulations, we’ve finished the title! 👍
5. …
6. ✅ Implement title in basic style
7. ✅ Implement title collapsing when its size is 0
8. ✅ Implement title cut with an ellipsis when it is too big
9. 🔲 Implement text in basic style
10. …
It’s time for the second commit:
git commit --message "Task #1: Implement the Card component title"
The second major part of the Card component is text. It can also be of zero, standard, and too big sizes, but we’ll approach them a little differently this time.
8. …
9. 🔲 Implement text in basic style
10. 🔲 Implement text collapsing when its size is 0
11. 🔲 Implement scrolling when text is too big
12. …
Creating the text in basic style turned out quite straightforward. I’ve added a
<p>{text}</p>
to Card’s code and this is all. I’ve also added a short Lorem Ipsum so it doesn’t overflow and represents the ordinary case.8. …
9. ✅ Implement text in basic style
10. 🔲 Implement text collapsing when its size is 0
11. 🔲 Implement scrolling when text is too big
12. …
Collapsing for empty text works out of the box here, as for the title. We’ll notice that we have a zero-height paragraph and margin around it if we dive a little deeper. Should we do something about this? I do not know. What risks do we face? I don’t see any. Maybe my colleague can share the perspective during the code review.
8. …
9. ✅ Implement text in basic style
10. ✅ Implement text collapsing when its size is 0
11. 🔲 Implement scrolling when text is too big
12. …
The approach to the overflowing text is different from one with the title. Its introduction made me significantly rethink the relation between the Card container and its kids. I converted the container into flex, updated margins. I didn’t make this transition to flex because everybody does it, but I needed to do one.
8. …
9. ✅ Implement text in basic style
10. ✅ Implement text collapsing when its size is 0
11. ✅ Implement scrolling when text is too big
12. 🔲 Ensure card collapsing when both title and text are missing
13. …
Our card is even closer to completion!
It’s time for the third commit:
git commit --message "Task #1: Implement the Card component text"
During the analysis stage, I assumed that a card would collapse when no title and text are present by the time I reach this step. My assumption was wrong. We need to make extra effort to achieve this. It requires a single line of code added at the beginning of the Card component:
if (!(title || text)) return null;
Also, here we need an extra commit message. I know a place that can inspire us.
11. …
12. ✅ Ensure card collapsing when both title and text are missing
13. 🔲 Implement emphasized styles for card
14. …
It’s time for the fourth commit:
git commit --message "Task #1: Ensure card collapsing when both title and text are missing"
Properly formulated tasks and properly formulated commit titles have much in common.
The last part of our coding activity is adding the emphasized styling to our card. Before this point, we had only two properties accepted by the Card component: title and text. Now it’s time to add one more Boolean property: emphasized.
Making it Boolean makes it not scalable. We have only two options. Isn’t it better to use enumeration? I am not sure. We do not know if we plan to add additional styles. If we would, the refactoring won’t take too much time. These arguments allow us to stick to the chosen way.
The emphasized card won’t differ too much. We’ll double its width and increase the title size.
12. …
13. ✅ Implement emphasized styles for card
14. 🔲 Verify the correspondence of the implemented solution to Task #1
15. …
It’s time for the fifth and the last planned commit:
git commit --message "Task #1: Implement the Card component emphasized styles"
You might feel the joy of accomplishment now, but don’t be too careless. We still have some work to do.
Don’t jump on it right after finishing coding. Instead, take a break, do a little walk so that your focus can relax, and you are ready to see a broader perspective.
Now reread the original task. Didn’t we miss something?
The requirements are the following:
For verifying purposes, I’ve created a deck of cards showing all nine possibilities of basic style. We came up with them during our analysis. One card is invisible due to the requirements of collapsing the card for both missing title and text.
We’ve found a minor bug with an extra margin. It’s hardly visible but still present.
Notice the yellow margin highlight
I’ve written considerations about things close to it two times above and faced the actual problem only during the verification!
We apply a fix but do not do the commit. Now we need to retest everything once again.
Looks good. Let’s move to the testing of the emphasized styles. Lots of vertical space is in use here.
I don’t see any problems. Let’s do the cleanup and commit our fixes. During verification and while trying to show all the variants of the Card component, I faced some general layout problems and fixed them, thus avoiding future issues. Let’s commit our changes:
git commit --message "Task #1: Fix layout problems"
We did a lot of verification here. Do we need to do it whenever we introduce even the minor changes? The short answer is yes, and I am sure that you won’t do this. I hope you’ll start thinking of the automatization ways. Structurization of the intellectual work like the one we do by applying our checklist and analysis results is good but a little bit not human. So let’s limit it to avoid the rise of inner anger.
I think the most relevant automatization approach here is automated screenshot testing. It also allows you to set your testing against different browsers, which manual resolution would heavily increase the amount of work required. There is always a tremendous amount of work when combinatorics come into play.
13. …
14. ✅ Verify the correspondence of the implemented solution to Task #1
15. 🔲 Move Task #1 to “Review”
16. …
You might not have this step in your process if you work on the project alone. On the other hand, if you wish, try creating a PR and see your code in the interface of a code hosting platform like GitHub. Even different colors and limitations of navigation might give you a fresh look.
The Card moved to “Review” stage
14. …
15. ✅ Move Task #1 to “Review”
16. 🔲 Pass the review of Task #1
17. …
I don’t have much to say about the review stage. Wait for the feedback and act on it reactively. Sometimes I set notifications reminding me that I should wait for the review to be completed by my reviewer by some time. If no actions happen from their side, I send a reminder message.
14. …
15. ✅ Move Task #1 to “Review”
16. ✅ Pass the review of Task #1
17. 🔲 Move Task #1 to “Verify”
18. …
Great to see you here, dear reader. We are almost done. This step is crucial because it allows your efforts to meet the actual data and gives you additional thoughts or even work. I am not a big fan of seeing my work breaking after deployment, but I must admit that there is always a risk for this.
The Card moved to “Verify” stage
If you see your solution failing, go and fix it.
16. …
17. ✅ Move Task #1 to “Verify”
18. ✅ Verify Task #1 on different environments
19. 🔲 Move Task #1 to “Done”
My congratulations to you! Here is the Card we were working on:
It’s time to move our Trello card to the Done column.
The Card moved to “Done” stage
18. …
19. ✅ Move Task #1 to “Done”
The approach you’ve just read about helps you prevent many different bugs, which is a positive side of it. But humanity doesn’t value the action of prevention but adores heroes extinguishing big fires.
The other side is that it makes you look worse in a naïve approach to estimating your productivity. The described process is slower than the dominating intuitive way of coding, and it lowers the number of bugs you can produce. In other words, it eliminates your future occupation!
I would call mine approach business-oriented for the case when your business has already discovered its niche and is ready to invest in software quality. Its main problem is the conflict with basic management metrics. Moreover, it requires additional engineer’s patience and courage.
Thank you for reading!