In my experience, a big part of them share a set of practices that continuously slow them down. Here, I want to address one that relates to how they view and use version control systems (VCS) such as git.
Whenever it is you start to use git (and if I may, try and start ASAP) one very simple question arises:
When should I commit code?
Most developers, specially those starting their careers, commit very rarely. From what I can tell, they mostly commit:
- When a given change is “finished”
- At the end of the day as a way to back up code
To put it other way, they commit (as in `git commit`) when they feel ready to commit (in the literal sense of the word) to that code. For example: they’ve done the tests and/or they feel comfortable enough calling that code “finished”.
I think there are several problems with this approach:
For staters, you can easily find yourself in a situation in which you’ve changed several files, changes were flowing, but now you broke something. Now you’re unsure about what to rollback. Is it this file or any of the other 50 that you changed/created? Or maybe it’s a combination of this change and the other? We’ve all been there. There’s no easy way to know, you basically have to review each change in every file. Try different combinations and what not. This slows you down. You’re basically chewing more complexity than your brain can swallow at once. There’s only so much cognitive load anyone of us can burden at the same time.
Secondly, you can easily find yourself in a situation in which you’re running in circles. Changing some bits here, other’s there. No direction, no purpose. Changing code around until suddenly it works. We’ve all beed there too. We’re like Alice, any direction works. Again, this slows you down. You’ll have to come by and read/understand the same code several times. Once for every turn you take. This is rather similar than the previous scenario: the problem you’re tackling has more cognitive load than your brain can carry at a given time. So, naturally, your brain has to put some of it down when you switch to a different part of the code. And you have to put it back up again when you come by those pieces of code again. And you will.
Finally, and what in my opinion is worst: when you’re working on a hard enough technical problem and you come by any of the two scenarios I described earlier, you could easily feel overwhelmed. Suddenly, it’s a great moment to check Twitter for the 57th time in the last hour. Suddenly, it’s a good time to question your life choices, the meaning of it all. What if front/back end code is easier (spoiler alert, it’s not)? What if I move to a different team? What if I just make empanadas for a living? Good luck finding the will to look at the editor and getting things done again.
You might not fall pray to mild existential crisis as easily as I do, but if you start to feel overwhelmed you’ll have an emotional price to pay before you get to a productive state again. This emotional response is way harder to overcome than lower efficiency.
I think this approach to commits, comes from the meaning the word “commit” carries. If you try to define “commit” you’ll get something similar to:
be committed to/be dedicated to (something)
pledge or set aside (resources) for future use.
be committed to/be in a long-term emotional relationship with (someone)
Pretty serious stuff there, right? When you commit to something you’re thinking long term. You feel sure you won’t change your mind. Or at least you’re ready to try to stand by your commitment.
I also hypothesize, based on numerous conversations with said developers, that this might also come from a general idea that one should not pollute the git history with intermediate, non working states. That git history should be as linear and simple as can be.
Naturally, I’m not simply writing this to state a problem but to propose a different approach to commits and layout the potential benefits it might yield to you, my fellow software developer. So here it is:
First, think of commits as checkpoints. When you create one you’re saving your progress. Think of commits in a less definitive way.
Second, you need a direction. Progress only makes sense if you’re moving towards an objective.
Here’s what that would look like:
First, you start by understanding the functionality that you need to implement. You need to understand the big picture of what needs to be implemented. What the external visible behavior that a user of your application will see after you’ve done your work. This might sound obvious to you. If it does, good, you’re half way there.
Now, you you need to enumerate:
- every condition the functionality is expected to meet
- every visible behavior/data the functionality is expected to output
- every piece of data the functionality is expected to store internally
You’ll get a list of individual “parts” that need to be built for the functionality to be implemented. Focus on what pieces need to be implemented not in how they will. I’d advice you to start implementing the items on the list starting with those that have the most uncertainty but the order mostly depends on the specific feature and the context. What information should be taken into account to define the order? The dependencies between each item, the complexity each one might involve, how risky each item is or how much certainty you have of how the item is to be implemented.
Then you start to work, one item at a time. Once an item is implemented, you commit.
Chances are, you’ll want to implement part of an item while you’re building another. Resist that. Try to remain focused on an item. Implementing two items at once is how you lose direction. It’s also how you progressively add cognitive load to your brain until it’s too much. And then you’re back to square one.
Let me try to illustrate with an example: let’s say I need to build a login page. The list of items to be implemented that I’d write would be something like this:
- the email and password need to be matched against the local db
- the users need to see a web form in which they write their credentials
- users needs to be redirected to page X if login succeeds
- users needs to be redirected to page Y if login fails
- validations need to be made against the written information
- users needs to be redirected to login page if there’s any error
For each item in the list I’d create a commit.
As with most things in life, there is a balance to be found here. You don’t want items in the list to be VERY specific and small. You also don’t want them to be too big. If they’re too small it’s impractical to work and separate them into different parts. If they’re too big you’ll lack direction and you’re right back where you started.
The goal is that each item in the list carries the same cognitive load as the rest. Ideally, each item should take more than less than 4 hours to complete. More than that it it might get too big. Less than an hour and it get’s impractical
If all goes according to plan you’ll feel more productive because you’ll be more productive. Finishing work, however small, is good for morale.
You’ll be more efficient, too, because you’ve reduced the amount of times you need to switch contexts to build a feature.
It’ll be harder to feel overwhelmed. When you have to work on small simple tasks it’s easier to find the will to keep at it. You don’t need to understand the whole thing. Just the very next item on the list.
You’ll also have a safe place to go back to in case you break something. Suddenly the db code started to fail? no problem, reset to the previous commit and to the previous until it works. You created a commit when it worked, right?
Lastly and I can’t stress enough how important I believe this is, you’ll have more information to share with the rest of your team. So instead of being “in the middle” of some feature, you can say you’ve solved X part of the problem and are still working on Y. That Z parts are still pending implementation. I’m sure the rest of the team, specially those managing it, will greatly appreciate the information and the decisions they can make based on it.
tl;dr commits are not definitive, create as many as you want as long as you have a direction