Granted, software houses offer you a lot of room for growth. 📈 📈 📈
They expose you to a wide array of projects that’ll help you explore and grow as a developer.
That being said, they have their own set of challenges and bottlenecks.
Having experienced these challenges first hand, here are some of the most notable lessons I learnt over the years.
1. Expect changes. Lots, and lots of changes.
Clients rarely know what they want. If they’re from the public sector, they’re probably even more clueless.
I’ve had plenty of experiences where I’d work for a whole month on an entire module, end-to-end, only to be told that the entire module was being scrapped or changed drastically.
In the early days, this used to bother me quite a bit.
After all, shouldn’t all the stakeholders agree on the requirements and workflows before work starts? Turns out this isn’t always the case.
Boutique software houses don’t really have a long list of clients. Hence, the more ’boutique’ your software house is, the more desperate your company would be to keep the client happy and satisfied. As a result, they’ll end up running an “Agile” project on a fixed budget.
If you work for such a company, the chances of scope creep are going to be incredibly high. And you’ll definitely be stuck making enhancements and changes on the same module for a long time.
Which brings me to my next point…
2. Emotionally detach from your work
Frequent and unnecessary change requests can get very frustrating.
However, this is not something you can’t run away from especially at a software house. So it’s very important that you learn to cope with this mentally.
A good way to do this is to emotionally detach from your work. Here’s how I did it.
Every time a new change request came in, I first had to stop myself from getting defensive about my work. My natural impulse was always to think about how much time I already spent on the module, and how much more I need to do.
I had to stop doing this.
Then I switched my focus to think from the end-user’s perspective. Honestly, this took me a while to do. But it’s something I really had to do. How?
Well, I’d run through the proposed flows either on InVision or on paper. Then, I’ll try to spot the different ways it could make the end user’s life easier. So, I’d look out for things like fewer clicks to get something done, fewer form inputs, fewer screens, etc. Basically, I’d see if the user can get something done in fewer steps or not.
Finally, I also started a practice where I’d assign a personal goal to each change request. Some of my goals would be to use a new tool, pattern, or package. The idea here would be to rewrite the feature in a different way.
Which brings me to my next point…
3. Implement something new in your workflows
Not only does this keep things fresh but it also helps you discover better ways of doing your work.
I made it a habit to try different design patterns, different tools, or at times even different code editors. Anytime I see myself getting frustrated with work, I’d take that as a cue to implement something new & different.
This way, I could continue to grow as a developer even though I was still working on the same thing day-in and day-out.
Along the way, I also discovered fun and quirky tools that I’d use for a short time. For example, I came across a command-line tool called “TheFuck“. It’s a command-line tool that corrects errors in your previous console commands. It was fun to use for a short time.
Learning new things is a great way to deal with stagnancy, and even developer burn-out. It can also help you to take up new career opportunities as well.
However, regardless of wherever you go, you have to…
4. Managing and maintaining badly written codebases
One thing I can tell you about software houses – they write bad code.
Things always start off well. But they quickly collapse as the deadlines get tighter, the task list longer, and the budgets slimmer.
Unless they have a really strong CTO on board, the codebase is likely to end up a mess.
During my career, I’ve had to work with jQuery files with over 13k lines of code with no comments in sight. Laravel controllers with over 4k lines of code, and routes files that just don’t have an end in sight. 🤯 🤯 🤯
Having a strong technical skillset will help you navigate such cesspools of bad code, and you’ll be more confident with changes that you make.
Also, having a strong understanding of the framework that you use will make life much easier. So make it a habit to watch tutorials frequently, and do spend some time going through the official documentation as well. It’ll help you a great deal!
From time to time, you might have strong urges to drop entire classes and rewrite all the code in a clean way. A word of advise, ignore this feeling.
Focus only on what you need to do, and keep it moving.
5. Spotting other people’s bugs, and fixing them
If it wasn’t for my experience working at a software house, I’d probably wouldn’t have picked up this skill at all.
A good chunk of your work at a software house would involve fixing or extending someone else’s code. Usually, with little to no documentation.
So you should accustom yourself with the Chrome Dev Tools, following the stack trace in log files, and adding breakpoints in your backend code.
As you get comfortable with the above, you’ll come to enjoy the process of actually finding and squashing bugs. I know I do. This only happens over time though. Keep in mind that the more error screens you repeatedly see, the better you’ll get at solving the bug the next time around. #ExperienceCurve.
Pro-tip ✌️ : Log out the inputs & outputs of each function as you follow the bug. Logs are a major 🔑 when it comes to spotting a bug.
6. Think more like a user than a developer
When I first started working as a developer, I was always concerned with writing clean code.
Most of my clients however, were rarely concerned with this. They were almost always focused on the end user’s experience.
This taught me a very important lesson. Everything starts and stops with the end user.
The end user doesn’t care about how well structured your code is. They’re only interested in whether or not your app helps make their lives easier.
Learning this lesson helped me empathise with my clients better.
I stoped arguing on how technically complex incorporating their change request was or how long the said change would take. Instead, I’d learnt to focus more of my efforts in finding a best-fit solution for all parties involved.
7. Technical debt isn’t always a bad thing. Borrow when you need to!
Early on in my career, I believed that I had to build everything from scratch.
I’d be afraid to include third-party libraries into my code because of performance or maintenance issues. Also, I felt using libraries wasn’t the “scalable” way of doing things.
Looking back, it wasn’t the smartest way of to go about things. Popular open-source libraries help save a lot of dev time, and they’re usually well maintained by the community. Making use of such resources is the smart thing to do.
Instead of taking this approach, I spent days reinventing the wheel just for the sake of scalability and purity of the codebase.
At the end of the project, the codebase would be far away from ever being “pure”. Also, most of the modules I worked on never had enough users to actually get to a stage where we could “scale”.
That’s why, managing technical debt as a developer is very crucial. It’s even more important if you’re a team lead.
As a team lead, you’ll constantly need to balance business needs with technical requirements. Sometimes, cutting corners to meet a tight deadline might be in the best interest of your company and the users.
Other times, you might need to double down and spend time making sure the code is properly structured so that maintaining and managing it is easier for your team.
Managing these two dynamics is where you’ll make most of your money.
8. Balancing the urgency of shipping products vs writing clean code
Being a passionate developer, I sometimes get really carried away with writing clean & well structured code. Sometimes, to my own detriment.
I’ve had plenty of times where I spent hours and hours obsessing over how the code should be structured rather than shipping it out in time.
It was quite common for me to spend half the week refactoring over and over again, only to realise that I had very little time left to build out the rest of the functionality, and then I’d have to pull a couple of all-nighters just to make up the difference.
The only way I learnt to combat this was to resist the urge to refactor code unless I hit a certain milestone.
In cases where I’d have to work within a tight deadline, I’d focus fully on building out the functionality first before coming back to refactor the code.
For this to work, you need to complete the module at least a day or two before the actual deadline. You can then use the remaining time to refactor and properly structure your code.
9. Writing logs can save you a couple of sleepless nights!
I never understood the importance of writing logs until I had to integrate one of my modules with another vendor’s API.
This was one of those APIs where you have to call multiple endpoints in a sequence just to get something simple done.
If something went wrong with one of the API calls, it would affect the subsequent API calls, and it was quite difficult to debug an issue especially on production.
What made it even worse was that there was no official documentation that I could refer to either.
The only way to debug the issues properly was to test it out locally with the help of Laravel’s die and dump method to see the results of each API call.
Eventually, I got smarter, and I decided to write out the request parameters and the response of each API call to the log files instead. This way, I could easily refer to the logs to figure out if I was passing the right data to the endpoints, and if I was getting the right response back.
This experience taught me a valuable lesson, something that I practice to this very day.
Always log out the inputs (omit the sensitive ones of course) and the outputs at various points in your app.
This way, you can quickly figure out where the breakage is, and you can work your way backwards. Trust me, doing this might help save you from a couple of sleepless nights!
10. Rest from time to time
A software house that’s doing well will always have new projects, new list of modules, features, enhancements and bugs for their developers to work on. If you happen to work for such a software house, you’ll have periods where you’ll experience a burn-out.
There’s no escaping it. It’s just part and parcel of being a developer.
You’ll either burn out because you’re being overworked, bored, underpaid or unappreciated. It’s all part of the game.
You have to learn to deal with it and more importantly manage it.
One way I started dealing with burnouts was to incorporate smart hacks into my workflows.
For starters, I moved my weekly update meetings from Fridays to Mondays.
This way I have enough time over the weekend to make up for any of my slack during the week. Plus, Mondays usually suck so it wouldn’t bother you much if the meeting does end up going sideways.
Taking more frequent breaks while I work. During these breaks, I’d usually watch fun, non-work related tech videos (E.g., Sentdex). Else, I’d go for a short walk to get some fresh air.
Rest is important.
So don’t hesitate to take a proper break before you start on your next big task.
Disclaimer: I worked for a boutique software house for 2 years in Malaysia as a Laravel & VueJS dev. Since then, I’ve been helping startups, software houses, and corporates work with freelancers & contract developers at TribeHired. As such, the lessons & experiences I’m listing down here are limited only to my experiences with software houses. I’m sure there are plenty other companies that offer a different experience.
Do let me know in the comments if you had a different / unique experience.