“Accelerate the world’s digitalization by creating the next generation of digital tools that simplify and improve people’s quality of life”
This quote is the driving force and inspiration behind all the work done at the company I’ve been working at for the last 3.5 years of my life. As It is time for me to embark on a new adventure I want to take some time to reminisce about my time spent there and go over parts of my journey of experiences and valuable lessons learned.
After finishing my bachelor’s thesis I still had some lingering courses that I didn’t finish so I was originally planning to take an extra semester to wrap things up but somewhere in the back of my head, I was anxious about looking for my first job. At this point in my life, I had very little professional experience and the thought of leaving the comfort of the university and wandering into the unknown was daunting.
To ease my mind I started looking for job opportunities in my city just to see if anyone was interested in hiring me. My inbox was empty for weeks. I started growing very desperate and started questioning myself about what the reason could be. I had still not yet realized that it was still summertime and most people were still on vacation.
Luckily it didn’t last for long, I pushed on for one or two weeks with my courses and then I started to a lot of responses pouring in. Excited I responded to the first one and shortly after booked my first interview.
At my interview at Zenta, I was greeted by some cool people, this was the first time that I met people that shared the same genuine interest and passion for technology as me. During my studies, there were a few classmates but the majority couldn’t care less about the software which I still find quite odd as I was studying computer science. I was taken on a tour around the office and I was in awe as I was given a short introduction to not only the software projects but the hardware projects they were working on, one thing I remember that stood out was a pair of car doors that had their windows modified with a film that when supplied with electricity could physically change the transparency of the window. In addition to this, there was a vibration speaker installed at the bottom of the glass which used the glass surface as a speaker.
To me this was science fiction, I didn’t even know you could write code and build this type of thing. I was taught UML diagrams and design patterns and here they are building these crazy futuristic projects. I knew right there and then after learning about the things they were doing that It is no use for me to stay and finish the courses I had left and instead I needed to get a job here. The interview process went smooth as everyone working there was super interested in technology as I were and I think they felt my excitement so they hired me shortly after.
Other people’s code
Something that you do not learn while studying is to read and more importantly understand other people’s code. At university most software was developed completely by you but as soon as I stepped into the working shoes that was no longer the case, now most of the code I saw during the day-to-day was written by someone else. Since I did software consulting that meant I could sometimes work on 3-4 projects at once which all had their problem domains which resulted in very different technical problems and codebases.
In all projects, it would also potentially be different team members which meant you’d have to read and understand different coding styles. This is another very valuable part of reading code, this is great that you can learn new techniques and approaches as everyone kind of finds their way of how they like to solve problems, this allows you to pick and learn the good parts and use them for yourself.
Even though it is required many times and a very useful skill it is not that many developers practice reading others’ code as much as they should. It is very easy to get too comfortable as a software engineer and tunnel vision on your next task instead of getting a better picture of the entire project.
Something that weighs extra in is to understand what someone else wrote, this is by far the hardest part of reading others’ code as it may often depend on domain knowledge that you may not possess at this time. I think this is a problem that most developers will find in their career several times as most developers including myself are pretty bad at writing documentation or useful comments to prevent information loss when different developers have to touch the code. This is however something I have gotten a lot better at over the years, I usually have the habit of at least including comments with links or explanations when I use some solution that is not obvious, an example of this I had to do in my game engine Maraton where I load different versions on a library depending on if you’re using Address Sanitizer or not:
STN_INTERNAL void
Win32LoadXInput(void)
{
// NOTE(Oskar): Loading different XInput versions here depending on flag because of a bug in ASAN which clashes with xinput1_4.dll.
// more info can be found here:
// https://developercommunity.visualstudio.com/t/AddressSanitizer:-Execution-hangs-at-glB/1533793?entry=myfeedback&space=62
#if BUILD_USE_ASAN
HMODULE XInputLibrary = LoadLibraryA("xinput1_4.dll");
if (!XInputLibrary)
{
XInputLibrary = LoadLibraryA("xinput9_1_0.dll");
}
#else
HMODULE XInputLibrary = LoadLibraryA("xinput9_1_0.dll");
#endif
if(!XInputLibrary)
{
XInputLibrary = LoadLibraryA("xinput1_3.dll");
}
if (XInputLibrary)
{
XInputGetState = (x_input_get_state *)GetProcAddress(XInputLibrary, "XInputGetState");
if (!XInputGetState) { XInputGetState = XInputGetStateStub; }
XInputSetState = (x_input_set_state *)GetProcAddress(XInputLibrary, "XInputSetState");
if (!XInputSetState) { XInputSetState = XInputSetStateStub; }
}
}
Here I explain why I have to use macros to separate version loading because of a bug I’ve reported to Microsoft about Address Sanitizer. Not the most obvious example but it shows the idea of what I think is sane information transfer as now another developer will have the information gap of “why” actually explained to them which allows them to take better decisions when managing this piece of code. Comments like this in addition to good straight-forward solutions to a problem is something I refer to as setting up your colleagues for success and it is something I attempt to practice as much as I can.
When it comes to how I read other’s code there are three rules I apply basically every time without fail and they are:
High-level overview / scan.
Read line by line.
Ask questions.
Since I cannot show any code from work let’s attempt to apply these three rules on one of my public GitHub repositories https://github.com/brokenprogrammer/mnotify. This codebase is not very big but the basic principles are the same when I apply them to bigger codebases.
High-level scan
We first visit the page and perform a high-level scan of the repository and the code. We start with reading the description within the README and find the following important key information: “MNotify will sit in the background” which indicates that we are dealing with some background job or task and “IMAP protocol” which directly gives us the information that IMAP is a protocol which we most likely can find the specification for if we perform a quick google search.
Moving on we continue our scan by browsing into the src folder and inside it we find a set of files, some of them are source code and some of them are resources that someone forgot to move to the correct folder.
We see some files that has the format imap_*.c
and imap_*.h
and theese files my brain will instantly pattern-match to the keyword I learned earlier and I can ignore them for now. In addition there is WindowsToast.h
, tls.c
tokenizer.c
and mnotify.c
and mnotify.h
.
Common convention for C or C++ projects are that the starting point of the application will be located in a file that is called main or something that has the project’s name in it and in our case we do have mnotify.c
which sounds like a possible candidate.
I personally already know what a Toast in Windows is, TLS, and what a Tokenizer is so I can make assumptions about the contents of these files but if I didn’t know I would depending on the size of the project look at all those unknown files first if the project is of a small to medium size and if not I would try to find the application starting point and move on to step 2 of our process.
Line by line
We enter the mnotify.c
file and inside it look for the main function. Searching for “main” would take us to a function called WinMain
which happens to be the startingpoint for Win32
based applications. From this point on we will read the entire main function line by line in order to collect information.
By doing it we can create a small list of things that happens in sequence as our application boot up. Do note however that many applications will not be as straightforward and include a lot of indirection in different forms as part of object orientation which results in you having to navigate through a tree of classes and methods. The same idea still applies even though it will be a bit harder in that case. A perfect tool to aid you in this process is the debugger, this tool will help you navigate the code line by line allowing you to also inspect the state of the application as it is running which can give you an even more clear insight into how it works.
Doing this on the main function in MNotify would give us a list that looks something like:
Check if another copy of MNotify is running and if there is one we terminate this instance of the application.
Initialize “WindowsToast”.
Load icon resources.
Load the application configuration.
Create a new blank logfile.
Create a new Window.
Create a new thread and tell it to run the
ImapBackgroundThread
function.An infinite loop reading Windows messages.
This list gives us a very good understanding of what the main function does and from here you would perform this method recursively towards the goal you are interested in, for example if the goal was to made additions to the IMAP client we would continue reading the ImapBackgroundThread
which would take us to move IMAP related functions that we also read and eventually we would get to the point where we can be confident of this codebase. This also opens many black boxes within a project and help you learn a great deal.
I want to point out that in some projects this exact approach of starting from the main function will not be possible, for example, if you are working in some framework that abstracts all of the internal initialization for you, for example, Unity then you will have to skip that part and be more direct to the parts you want to read and understand and work backward from there. This also applies to a codebase that is too big for you to reach your goal from the main function, start from a known location or perhaps even your goal and work yourself recursively backward.
However, I will also mention that in this case, it is still a good habit for you as a developer to try to understand this framework or tool’s internals in the best way possible for you to be able to take better decisions later on.
Ask questions
This point is perhaps very obvious but basically if you stumble on something that’s just like a brick wall and you are unable to get anywhere the best thing is to just ask. I most preferably ask the developer that wrote the code I am stuck on, I can find this out by using tools like for example git blame
.
Getting hard things done
When I first joined Zenta I was quite arrogant, a trait I find in most people that just graduated. Even though I was about to start a new role at a new company programming in a language I had never touched before I still felt like I am the best. It wouldn’t take long however until I was brought back down to earth. As soon as I started working on my first real project I remember just looking at the list of tasks that were assigned to me and thinking “what the hell is this?”. I didn’t understand how to do any of them, I did go and ask questions but I didn’t want to feel humiliated by not understanding anything so many times I just sat and tried to understand what was going on. When this happened I had a great project manager that quickly identified the problem and already understood what I was going through, he sat down with me and went through my tasks and helped me divide them into smaller tasks that seemed more understandable and more importantly doable compared to the bigger ones. This was a game changer for me, even in my projects this is not something that I had ever practiced or done, I think back then one of the causes for my lack of productivity in personal projects had this same problem.
This application of divide and conquer on tasks is a real game changer and it can make what feels impossible feel possible instead. If you are put on a new codebase or a new project with new tech you have never heard of before. Well divide it into chunks, don’t attempt to understand the entire software in one go, instead understand what the different libraries are, that will let you know what they do and eventually, you’ll grasp why they were used and eventually the entire application.
In hindsight, I can also remember that this project manager that wasn’t a developer back then also gave me a lot of useful advice on how to conduct yourself at work as a developer. He also taught me that these tasks that I receive may be defined but not defined enough in a sense and in that case I should send them back and ask him to define them better for me to work on them. An important lesson from this was that the act of sending back tasks was not me disrespecting his work instead it is the opposite. The idea was to hold each other to a higher standard and not settle for sloppiness which I connected with. Other developers in my experience tend to take things very personally with the code that they’ve written and more so with their opinions. In the same way, I and my project manager held each other to higher standards I want the same relationship with my developer colleagues but I have met many developers that get very frustrated if they receive general advice or comments on their pull requests and even more so if it is requested for changes. I do not know why this is as I have always had the mindset that it is not my project and at the end of the day not my code anyway so I have no problems following company guidelines or “best practices”. I don’t have the best solution to these types of interactions, but for now, I have settled with applying the golden rule, which means to treat others as you wish to be treated. I want people to invest themselves in my pull requests and my code, I want to know if I made a mistake so I can learn, correct it and improve in my craft and therefore I will most likely continue doing it for others.
Very soon after becoming more comfortable within my role at Zenta, I started becoming more and more interested in some very obscure and long-running bugs in some of the projects. Working as a consultant it is quite difficult to get the time you need to write a solution that you are satisfied with, especially when you are a very self-critical person like me. The reason behind this is kind of a sane one and that is that the customer or end-user will never see your code so it doesn’t matter that it is pretty. However, they do care if you are efficient when making new changes or additions and for that, you do need to not leave a mess behind you every time you finish a task. This makes it so you have to balance everything you do with what time you have. The same thing goes for bugs if the bug is not critical enough it may not seem worth it for the customer to fix this but I would argue that this is just a ticking bomb waiting to explode. Some bugs are not critical enough.. until they do become critical enough and I have had experiences with some bugs that have been very obfuscated over time resulting in a very different debugging experience compared to what you would have during the initial development. I have yet to learn a one fits all solution for every bug in the world but something important I have learned that resonates with me and that is to be fearless when facing these hard issues. What I mean with this is that I am going in ready to do almost anything to fix the issue, if it is an easy one then good, I’m out of there quickly but if its a hard and obscure bug I will not back down and I am ready to rip apart the entire application just to find out what is causing the issue and to fix it. Just the same way I believe we should work towards opening the black boxes of software I am a believer that we should bust the ghosts in our machines. While doing this however, I find it very important to not just solve it but spend some time and understand why it was a bug, why it happened, or what caused it. Doing this will make grow within the craft and make you feel empowered, you will be the lawyer that has never lost a case and not the one-hit wonder that got lucky one time. So far in my career, I have had a lot of success with this approach.
Don’t take things personal
I kind of touched on the subject earlier mentioning other developers getting defensive around any comment at all regarding code they’ve written. The real advice regarding this is to not take things personally. I am a very emotional person and I have a very hard time following this advice many times as but you really shouldn’t take things personally, it is really good to take responsibility and care about things deeply but it is not the same as taking it personally. People that take things personally at the workplace will get very worn out quickly and to prevent that you need to put up a sort of barrier but there are different kinds of barriers and different ways of taking things personally.
The example before with developers and their code. I handle this by wanting to improve and become better at what I do. Others see comments or advice as personal attacks, they will believe that you are not criticizing their code instead you are criticising them and attacking their skills as a programmer. In addition to this many developers has a very strong emotional attachment to their code which is okay but placing your final semi-colon before submitting your pull request is not the same as that piece of code being done and complete forever and ever. Code is not set in stone and changes a lot over time so don’t treat it as something complete. Even published books get corrected and are re-published under new editions and the same will happen to your code.
To treat this start with not seeing feedback as something negative, other developers are giving you a helping hand to potentially improve your code. Be polite and lead with a good example, if someone is disrespectful to you or taking things personally then take it up with your boss or the person directly. Remember that your code doesn’t reflect you instead maybe you can think that it reflects your knowledge at a point in time. I don’t know a developer that doesn’t go back to their old written code and thinks it’s stupid. I have many times used git blame
only to find out I am the culprit.
But this was not the main thing I wanted to talk about, I have had the pleasure of also having direct contact with customers. I think it is very sane to let developers talk to customers directly, not only because they know the application and may understand problems or bugs that the customer may report better than for example a project manager would but also because it is good to go out of the code bubble and hear from people that are using what you’ve built in their day to day life. This might not be for anyone but at least in my opinion, it is a very good way for engineers to get insights into the real world.
Anyway, on to the more difficult subject. As development goes on, maybe something takes more time than expected and customers might not feel satisfied, because they of course have to pay more money than they thought. Or maybe they pay for the development and notice bugs in their production environment resulting in more developer hours to fix those bugs.
This should be fully understood, I think software engineering is the only field where we have the reality of still getting paid to fix stuff that is not working correctly. I usually make a funny little example comparing how you would react if you hired someone to renovate your bathroom and he comes back to you and says he is finished, but you later find out that there is no hot water in the bathroom, and upon contacting the guy who did the work you get a new estimate of how much it would cost to add hot water. I’m pretty sure you would be furious if this happened, so put yourself in one of your customer’s shoes. Maybe they hired you to branch out their business or they had a great software Idea that they strongly believe in and want to invest in. Working as a consultant I’ve seen most of the different customers and almost everyone who doesn’t have experience with software projects will very quickly become frustrated.
Some customers do take out this frustration on the developer that has direct contact with them and while you can tell them to go to hell your boss most likely won’t be too happy. I don’t know how true it is but I don’t feel like customers that have once become fed up or unsatisfied with a project can ever really be saved. What I mean with this is that you can talk with the customer, comfort them, or whatever but the trust they had for the team and its developers will most likely still be in shambles.
Do continue talking to this person and keep it professional, you might already have taken a step back and accessed the situation and got some ideas on how to salvage the project, most often it just boils down to keeping the customer updated more frequently than before so they feel like they are more part of the development process but something I think is very important is that during this time if it ever gets nasty enough where you are personally attacked or insulted depending on how to sever it is I think you have an obligation to yourself to say something.
I have seen many developers feeling weakened by letting this happen to them, I know developers that have been sad over the weekend from things customers have said to them. This I think is just not okay, you work as a software engineer and not a punchbag. Either stand up to the customer and be honest or if that is difficult you contact your project manager or someone from the HR team and explain that you will not accept this. And if the workplace continuously puts you in pathological situations over and over then start looking for a new job.
But I want to wrap this back into the fact that you shouldn’t take things personally. Reading all of this I do not mean for you to be an impenetrable wall that no negative feedback can ever get to but a saner one, be aware of things around you from a new third-person view instead of looking at everything with black and white glasses. Sometimes maybe it is 100% your mistake that the customer is angry, and many times the more powerful move is to take responsibility for your mistakes however do not take things personally and do not let your work make you feel weak.
I hope this was an interesting read, if you enjoyed it please consider checking out my other socials!