Shad's Musings

A Review Of My First Year As A Software Engineer

Today marks a month to my one year anniversary as software engineer.
I began working for a local startup in Nairobi without ever doing a
software engineering internship. I am forever thankful to my manager
for taking a chance on an unproven, fresh out of college kid who
barely took enough computer science classes to really understand
what's happening under the hood of a computer.

The opinions in this piece are shaped by my experience working in
a startup, therefore some readers may relate, others may not.

A little background...

Disclaimer: This section may have little to do with actual software engineering
but I thought I would open up about my journey leading up to this point. This
section mainly details my self esteem issues, and it's the first time I am opening
up about this to anyone. Feel free to read this or skip to the next section.

I have to admit the lack of internship experience was entirely my fault.
I was fortunate to attend a school where the largest tech companies in the
world would show up begging for people to apply, however I never took
advantage of this opportunity because I had a strong case of impostor syndrome.
I had a rough start academically in my freshman year and it took me up to up to
spring of sophomore year to get back on track.
However, by then my self esteem was so low that I could never muster the courage to apply for an
internship.

I took a handful of computer science classes in college and I built some really
cool stuff for final projects. I was quite good at coding assignments but
sucked at proof assignments (to this day I wonder why there was a chasm between
the two assignments yet the former built on the latter).
I would help a bunch of my friends out with these practical assignments, and it reached a
point where they would prefer to see me instead of seeing the teaching assistants.
This was a great self esteem boost and it encouraged me to do an even better job of
helping others with their coding problems, but it wasn't enough of a boost to deem
myself worthy of a shot at a big tech company.

The height of my impostor syndrome was in Fall 2018 when a good friend
recommended me to a Facebook recruiter. The recruiter looked at my pet projects
on GitHub[^1] and decided to give me a chance. However, my mind conjured all
manner of excuses to avoid the interview. I sent an email to the recruiter that
went along the following lines:

Hey, thanks for the interest, I am honoured. However, at this stage I have
not taken the requisite class so I think I will fail the interview, can I
check in again at the end of the semester?

Some of you will cringe after reading that email, and I feel you. The requisite
course referred to in the email was a DS and algos course. My university split
DS and Algos into two courses, and I had only done the first course, which
focused on implementation over proofs. The second course was where proofs met
implementation, and it introduced concepts like space-time complexity.
In retrospect, I think the first course was enough to power through FAANG
interviews with maybe a month of preparation to touch up on space-time complexity.
The fact that boot-camp graduates land in big tech without taking a rigorous DS
and Algos course vindicates my opinion. However, the first thought in my mind
when the recruiter reached out was "I am not good enough to interview".

(Reader warning, more cringe to follow...)

One of the hidden motives of my email response was that by asking for time,
the recruiter would move on to find other candidates, and save
myself from eventual rejection during a phone screen. To my surprise, the
recruiter was perfectly fine with my request, and she actually waited. In
January 2019, I got an email from the recruiter saying the position was no
longer available. It is at this point I realized ... I am a complete joke.
This email response weighed heavily on the rest of my senior year, and I
was so crushed by how poorly I thought of myself that I could not get myself to
apply for anything else.

It was time to graduate, but I had nothing to show for it. I had an
average GPA, no serious leadership positions in college, one half-assed
extra-curricular activity, and no internship. I knew that finding a job was going
to be hard. With my back against the wall, I decided to move out[^2] out of my
comfort zone and do two things:

  1. Apply everywhere.
  2. Accept that rejection is a part of life, embrace it. I will try to limit
    it's occurrences, not by shutting myself out of opportunities but making it
    harder for someone to say no to me.

I decided to return to Kenya, and begin my job search there. I felt confident
in the decision to go back home because I knew there was a bustling start-up
scene so there won't be a dearth of opportunities. I landed two interviews
within a week of getting back home. After two weeks, I had secured a job.

Initial Thoughts Of The Profession

I really believed that a software engineer only creates applications and that's
the end. I thought that software engineers never interacted with the business
side of a company. Software engineers lived in this bubble in their office and
their only worry was making something run faster, or release a new feature
so that users are happy and will continue using the product.

The Reality

Software engineering is one of the components of the business' machine. Depending on
the size or the culture of your organization, you may actually never speak to the business
team. On the other hand, you may find yourself very involved in the business side of things.

I'll go a little in-depth on some key areas that stood out to me during this past year.

Software vs Business

I started thinking more about business, and how my work directly impacts the
bottom-line. I have seen how a bad data model can slow down or potentially ruin
a business opportunity. I have come to appreciate the importance of understanding
the problem that you are trying to solve for.

I have wrestled with the idea that you shouldn't go asking customers for
requirements, even though conventional thought suggests that "The customer is
always right"
. I have learned that you should not ask developers for
requirements because they tend to operate in a bubble and their suggestions
could be far from the users' reality. I am not saying that you shouldn't listen
to the users and developers, rather, their opinions and experiences should inform product development

Tools and Frameworks

If you go to any programming/tech related website, you will find discussions
on the next new thing, or some strong opinion about an existing tool or
framework. Initially I was drawn to such content because I could learn the new
in thing or have something cool to say when I meet other
people interested in software development. A year later, I have a different
reason for consuming this content. I now read to see if the new tool/framework
addresses a problem that I am facing at work, or if the cost of switching over
to the new tool will pay for itself down the line.

I have learned it is more important to select the right tool for the
task at hand e.g. you would use C or C++ for embedded systems programming or
something where every millisecond counts, or you should use Python for data
science stuff since it has a robust ecosystem in that area. There are more
examples and use cases I could jump into but that's not the point here.

This does not mean that you should not read up on the new stuff or test new
tools. I'd now attach a target outcome when reading about this stuff e.g.
does this tool address a problem I am facing. However, sometimes you just want
to stay in the know and that is absolutely fine too!

Trade-offs and Thinking Fast

I went into software engineering thinking that the environment/expectations
would be the same as an academic setting i.e. write modular code, test
everything and you are good to go. All of these concepts carry over from the
academic realm to the professional world, but it may not be a 1:1 transition.

One of the concepts that did not map neatly was testing. Business
requirements are ever changing, which means that code is ever changing, and in
this case, unit tests may become an impediment when refactoring/deleting old code.
I remember reading an article about an engineer working in one of the Silicon
Valley pioneers (think HP, Oracle etc) who had to spend months working on a
small change because he had a test suite that run for almost 2 hours and most
of them were unit tests that were no longer relevant. The point here, is
not to condemn unit tests, but to provoke a discussion of when and where to have
unit tests, especially if the code base is changing quickly. Personally, I
don't have an answer for this yet, but someday I may be on a podium in some
conference talking about this issue, so stay tuned!

Another issue that popped up was how to deal with tech debt. There are instances
where business requires a new feature in short time frame. The feature
could be complex and may require significant code overhaul, but the folks
in management want the thing shipped as soon as now. In that case you will have
to make some tough decisions with respect to your code, and possibly monkey
patch some things and add feature flags here and there and add something like this
:point_down:.

  // TODO: please refactor this block of code.

Voila! Tech debt. The managers are happy that a customer is happy with a new
feature, but as a developer, this TODO block is an eyesore every time you come
across it. It could be that the block of code is hard to understand for other
developers, or it could be that the block of code is demonstrably slow for some
operations e.g. database calls. The code base will be littered with these TODOs
unless the team schedules a regular clean up. However, business needs to keep
innovating and meet investor demands so the rate of clean up might be slower
than the rate of TODOs popping up in code despite going through rigorous code
reviews.

The Next Steps

As I head into year two, the main thing I want to focus on is to get better
at thinking on my feet. This is not to say that I have achieved perfection in
terms of coding style or testing or even the fundamentals of computers. I am
still learning as I go, and they will get better with applied effort
and experience. However, I have learned that this career is full of trade-offs,
and having a good nose for the right trade-offs is really valuable.

I also want to dive deeper into the inner workings of computers. How does my
JavaScript code move from a .js file into the V8 compiler and finally into
machine code? I have some understanding of how this works, but I think it would
also be nice to know these hard concepts.

[^1]: Since then I have deleted these projects because they were one-off
projects and I am currently working on more involving projects for my
own use.
[^2]: Note the use of the term move out as opposed to step out. I feel like
step out implies that I am still close to my comfort zone. I am a firm
believer that language is a manifestation of your thoughts, and in this case
I really wanted to move out of my comfort zone