The Joy of Building Together

Blog Cover

A Reflection on Growth, and 15 Years of Hands-on Software Development at HyperIn.

At HyperIn, software development happens in relatively small teams, and there are is very little
hierarchical structure inside a team. Even a junior developer may be responsible for the
implementation of entire features. On the other hand, junior developers also get to have a say in our
planning meetings. Involving everyone in the design discussions and code reviews is how we
ensure that information isn’t siloed, good ideas get heard no matter who they come from, and we all
develop as software developers together.

My job title at HyperIn is Chief Software Architect, but mostly my daily work still consists of the
same kinds of software development tasks as any other software engineer, and I wouldn’t have it
any other way. In a way, the main responsibility of a software architect is to make sure that even as
software evolves, there is a consistency and predictability to its design. That’s pretty boring. The
more exciting work is in the engineering: implementing new features and fixing bugs are
fundamentally problem-solving tasks. Discovering implementation that produces the desired
outcome in an optimal way, diagnosing a misbehaving piece of software, even rewriting existing
code to be more elegant and extensible – these make the work feel like being a detective figuring
out the solution to a murder mystery, and that’s what keeps me motivated.

Of course the importance of the Chief Software Architect role can’t be overstated. If that job is done
poorly, it makes it more difficult for everyone to experience the satisfaction of a mystery solved.
With already 15 years behind me in the company, it may seem obvious that I should have that role,
but it’s something that I have had to learn how to do while on the job – then again, so are most of
my other responsibilities.

When I started working at HyperIn, it was only my second job as a professional software engineer.
Earlier, I had been a researcher at the Helsinki University of Technology, which has since become
part of Aalto University. My university studies had included computer programming, but not
software development.

As research assistant, and later as researcher, I used whatever languages and
tools I needed to get the job done, without any semblance of software development processes.
Having learned programming in C and C++, it was relatively easy for me to transition into a career
in developing software in Java – my earliest programming experience using Commodore BASIC on
a VIC-20 was of course essential, but less directly applicable – but I had to learn all of the finer
points of software development on the job.

Based on my own experiences, I firmly believe that programming languages, software development
processes, and all of the tools and techniques related to them are things that can and will be learned
as you work. In fact, you have to learn them as you work, and continue to learn them – you
shouldn’t think that your skillset is ever complete. The only thing that you have to have when you
walk through the door for the first time is a facility for algorithmic thinking. You have to be able to
imagine how the behavior of the software will change with each line you write. You have to be able
to understand the differences between two algorithms that produce the same output, so that you can
choose which one is the more optimal one under the prevailing circumstances. While languages,
processes and tools evolve, these are the fundamentals of computer programming that will never
change.

Speaking of evolution, one of the most interesting things to happen in computing during my
professional career has been the rise of generative neural networks, which have become
synonymous with AI in common parlance. When I worked as a researcher, the neural networks we
used could be used to classify images or text, but their ability to produce those things was severely
constrained. One of the most impressive tricks I was taught as a student was how to take multiple
blurry frames of a video showing a car’s license plate and use them to train a model that could
produce a slightly less blurry image of the license plate! Now we take the generative abilities of
GANs and LLMs almost for granted.

However, one thing has become clear as we have begun to integrate AI tools into our daily practices
in software development: an AI assistant is no substitute for a software developer who knows what
they are doing. Even the most state of the art AI assistants, enhanced with significant domain
specific workflow engineering, are still capable of generating absolute nonsense, and it takes a
competent software engineer to review the output and separate the useful from the nonsense.

Nevertheless, a competent software engineer, who has a clear idea of what they want to see, can use
an AI assistant to accomplish with relative ease tasks that would otherwise be time consuming or
tediously repetitive, especially in codebases with a lot of legacy code. There is clearly still room for
improvement in the underlying implementations of AI assistants, but it’s just as clear that they
aren’t going to go away. Then again, neither are human software developers.

Only human employees can take responsibility for the quality and correctness of the code that we produce.

Rami Rautkorpi