Have you always had a problem that you knew could be solved by writing an app but it was always eluding you because of various reasons: too low level programming to achieve this, too much hacking, no information on anything similar?

Let’s assume that you have managed to find this holy grail app that solves that problem of yours and you’re also so lucky it has it’s source code attached to it. You run it and it kind of does what you would expect but it looks to be way out of date so your only chance is to code it up to date your self.

You open up the source code and you notice it’s in a familiar programming language, the entry points look fairly robust so you are now happy and assume that everything will be as easy as that to find. You dig and dig around the code base and notice the variable names start to morph towards a distorted language. Soon enough you find the point where you no longer understand anything as it switched languages mid way through the code you think you have to change.

Python App Memory Reader

This happened to me fairly recent with a c# app that handles memory reading from another app and acts upon the data it scrapes. The interesting bit is, as you thought, the memory reading part: the app it reads from is a Python application so it’s fairly tricky to get it right, hence the “magical” problem.

The source code could tick all the boxes of a legacy app: hard to understand, no documentation, no tests, no design patterns etc but this wasn’t what made it particularly hard - I have enough experience with legacy apps to not be put off by their age. The language towards the start of the application was in plain English with hints of typos. Those typos looked to be changing more and more towards German the more I dug into the code. Soon enough I reached the memory reading module and everything was plain German with a lot of acronyms and domain knowledge that I could not fathom to understand.

The dilemma

I was now faced with a huge dilemma: how could I go about and change anything in there where everything looks gibberish?

I even asked myself if I wanted to learn German at one point… this idea faded the moment I tried translating some bits but realized it’s impossible without being familiar with German programming domain knowledge.

Learn by hacking

I’ve decided to approach this the usual way I go around with legacy apps where I want to do some changes - very small refactor steps and incremental changes - but taken to a whole new level.

  1. Loosen up coupling of components by introducing dependency injection and extracting interfaces. I started up at the entry point - a WPF component - and worked my way towards the memory reading module. I’ve cleared up duplicated code and untangled the spaghetti references along the way by carefully sticking to just refactoring towards DI. I knew I was safe from breaking functional changes as all I was doing was replacing references of concrete classes with their interfaces.

  2. Safety net - I knew very well I had to create a net of unit tests to prevent myself from breaking things as anything could go very wrong when handling data straight from memory. Luckily the first step I’ve done revealed some other goodies in the source code - one of which could take a snapshot of the memory and save it. This meant that I could write a Golden Master test that would take input as many snapshots as I had available, replay them and assert various states of the memory.

The “solution”

After preparing the ground I was in a very good position to do experiments and changes to the memory reading library knowing that there is almost no chance I could break the old code.

Even if it was still German and cryptic code, making changes to any part of the application was easier than ever: I was able to read new bits from the memory that were added after the app was deprecated and with that knowledge I went back and manage to “translate” part of the code journey thus enabling me to dig deeper than before and add even more functionality.

I can safely say I’ve saved myself many headaches and a lot of time by taking the preparation steps instead of fudging straight into the code I wanted to add.