Reflecting on my First 2 Years of Software Engineering
I’ve been working full time at Hologram for 2 years now. This gig happen to also be my first out of college, and I’ve learned quite a few good (painful?) lessons along the way that I would like to share in section below. Let’s get to it, shall we?
Good Engineering Practices Go A Long Way
Finding the right balance between moving fast and still building strong, clean and maintainable code has been challenge. Just ask him:
Aim to have better Devops processes. Moore’s Law has brought us engineers great productivity benefits, and if you’ve not been in a cave for too long, I’m sure you probably heard of concepts like continuous integration (CI) and containerization. It may or may not work for you depending on the team and size, but in most cases, they do at some point. Having a simple yet rapid build, merge, test and deploy loop is the best way to ship code fast and reliably.
Aim for smaller + more frequent pull requests! It’s hard to read big ones, making them prone to the LGTMs cause nobody gives a shit as long as the code “looks like it works”. By submitting smaller code changes / deltas, people can narrow down on what the code is actually trying to do. You’ll get better constructive feedback and the reviewer(s) will thank you later for not having to maintain a huge mental context introduced in the pull request.
Don’t check in/version control your API keys in your main application repository. There’s a reason for why empty config files are version controlled. It is a huge security risk. You should be injecting them via your Devops workflow anyway.
Watch for environment specific values when you’re checking in code. Make sure it plays well with all other developers working on the same project. You may have a ~/cute/pony/my/dear/fairy/run-me-if-prod-is-down.sh
, but some developers aren’t so cute. Make your application robust to relative paths, so other developers can change those configs on the fly and it’ll just work the same way as it does on yours. Better yet, use something like Docker.
Try to use properly vetted 3rd party packages that have more traction and support. Proper planning and making good software design decisions are key here. One of the things that I learned the hard way back in my early days were to use old PyPI packages that were not well maintained. Heck, they might even be vulnerable! Spending an extra 30 minutes researching and figuring out better packages with an active community can bring huge productivity gains to your project in the long run. It’s way better than being too dependent on one of those packages, and then giving yourself a massive headache over the technical debt introduced if it no longer works for your product/solution.
Clean Code and Proper Abstractions
Writing clean code is an art of itself.
Sure, technical debt isn’t going to sink your product/startup, but it sure is hell for your engineers to be living it every single day.
I’d shorten this post, spare you the boredom and just point you to these books:
Here’s a quick tweet I made:
alright moving on…
If you haven’t heard of SOLID and DRY principles, go and read them now.
Proper code abstraction makes the codebase:
- Easier to navigate.
- Easier to understand.
- Decreases the risk of bugs being introduced.
Of course, don’t be that abstraction astronaut too. Have due diligence and apply the 80/20 rule.
Engineering + Product + Business Team Synergy
Synergy: The interaction or cooperation of two or more organizations, substances, or other agents to produce a combined effect greater than the sum of their separate effects.
Understanding the Why for the product you’re developing is extremely important for its success. Good software abstraction is a step forward in the right direction, but proper communication and cooperation with the product and business team goes a long way. They are ultimately out in the front lines talking to customers, or working on how to close a deal where technical (engineering) details are being ironed out. Don’t get trapped by the engineer’s disease. Work with them and help them understand the ins and outs of the product.
Tooling, tooling, tooling
Know your way around a UNIX shell
Learn to be comfortable in this environment. Pick up a book or two on this topic. Maybe read a few more here.
grep
is your friend. You’ll find this extremely useful for figuring out the first clues on which part of the codebase you’ll need to change based on just the sprint task name alone.
For example, if you have a task that says add permissions check to Devices
endpoint, you’ll know some combination of Device
source files will require changing.
Another one that I’ve been using recently is called ripgrep
, or rg
, for faster output.
Have a Python package with a requirements.txt
file and a small OCD for having the package names sorted alphabetically? Use sort
to solve it for you rather than doing it by hand:
sort requirements.txt -o requirements.txt
Heck, why not give these commands a shorter alias?
Here’s what I do for git
as well:
I type
g cob <newbranch>
, cause that’s shorter thangit checkout -b <newbranch>
Learn shortcuts in the tools that you use. If there’s anything positive that comes out of gaming addiction during my teenage years, it has to be the in game shortcuts. I write a lot of code in vim
these days, but occasionally pull out a directory/project in Sublime cause the codebase is huge and have enough moving parts. I’m not here to debate on why tool X is better, but I trust you to know what works best for you. Once you’ve used it enough, and with strong muscle memory for shortcuts, you’ll be flying around making quick edits and changes before you even know it. Remember:
Every key that I don’t type is more time spent elsewhere.
Script it up
Write scripts if you know you’re gonna use multiple commands over and over again. In this case, I was running into stale .pyc
files affecting the correctness of my software. This was the hack I did, and it worked like a charm:
I’ll just run them every single time. It works pretty well for my use case. I’m not a Python expert, but I’m sure I’ve figured out a better way to do this now that I wrote this down. Think of how many times I won’t have to run all the commands manually during development.
Makefile
s, cause make test
or make install
is a lot faster and easier to remember than python setup.py install; <more commands>; <moarrr commands
.tar.gz
, .zip
, .gz
, .tgz
…wait what?? I need gunzip, gzip, zip, tar -cdoi@#!*$!?!! …
How did this become so complicated???
So I tuck this function into my .bashrc
config file and type extract <something>
when I see one of these tarballs.
Think of how much time you’ve shaved!
Conclusion
One major takeaway I have for the software engineering career track is that it’s one that guarantees lifetime learning. Learn fast and learn how to make yourself learn faster.
In a world where we celebrate our failures, I’d go against the grain to say that failures suck. It’s always nice to be successful, and I choose to win than to lose every single time. However, more importantly, life generally doesn’t have rules/limits on number of attempts you can make. Learning to strike faster and more frequently might just work.