What I Found When I Opened the Hood
The forensic autopsy of a 20-year-old codebase.
For everyone. Technical terms explained in plain language.
After the crash report from Part 1, I knew the scheduler had a problem. But before I could fix it, I needed to understand the full codebase. I spent the first week reading code — not writing it.
What I found was both impressive and alarming.
01The Scale
EVEMon was not a small project:
Total code: 210,002 lines across 1,363 files
Business logic: 83,656 lines in 846 files (one massive project)
Screen code: 99,073 lines in 251 files (Windows Forms UI)
Tools and generators: 14,717 lines
Tests: 417 lines (23 tests in 4 files)Two hundred and ten thousand lines of code built by fifty-seven people over twenty years. This isn't a weekend project. This is a significant application — comparable in size to many commercial software products.
02The Good
Let me be clear: EVEMon worked. Millions of EVE players used it successfully for nearly two decades. The skill calculation engine is correct. The plan optimizer finds optimal training paths across hundreds of skills. The ESI integration handles CCP's API reliably. Peter Han's migration from the old XML API to ESI was skillfully done.
The fifty-seven contributors who built this created something genuinely useful that served a community for twenty years. That's rare in software. What I'm about to describe isn't a criticism of anyone's work — it's what happens to every codebase that outlives its original assumptions.
03The Concerning
Twenty years of accumulated decisions had created structural problems. Not because anyone did anything wrong at the time — the technology and practices of 2006 were different from today. The problems came from building on top of decisions that made sense then but became constraints by 2026.
One Project to Rule Them All
All 846 files of business logic lived in a single project called EVEMon.Common. Think of it like a warehouse with no internal walls. Interfaces, data models, networking, serialization, settings, services, helpers, threading, and UI controls — all in one room.
This meant:
- Changing how market orders display could accidentally break skill plan calculations
- You couldn't work on the data layer without dragging in the entire Windows UI framework
- There was no way to enforce rules about what code could talk to what
For comparison, EveLens splits this into seven separate projects with strict one-way dependencies. Like having labeled rooms with fire doors between them.
23 Tests for 210,000 Lines
Automated tests are the safety net that catches mistakes before users see them. The original codebase had 23 tests — for a 210,002-line application.
Here's what they covered:
- 2 tests: Scan the code for dangerous threading patterns
- 6 tests: Can you compress and decompress data?
- 15 tests: Can you convert EVE time formats correctly?
That's it. No tests for characters. No tests for skills. No tests for plans. No tests for settings. No tests for market orders, contracts, industry jobs, mail, or any of the core features players actually use.
This is why the crash at sixty characters went undetected for years. There was no automated check that would have caught it.
The God Object
One class called EveMonClient was referenced by 150 out of 1,100 source files — over 13% of the entire codebase. It had 929 total references and held 69 static events that every part of the application subscribed to.
Imagine every announcement in an office building going through a single PA speaker. 218 rooms had their speakers turned on, but only 212 remembered to turn them off when they left. The other six leaked resources quietly, every time.
I'll go deep on this in Part 3. For now, just know that this single class was the reason the scheduler couldn't be fixed in isolation — everything in the app was connected through it.
18,072 Lines of Dead Code
This is the part that surprised me most. The codebase was carrying eighteen thousand lines of code for things that no longer exist:
| Dead Feature | Lines | Why It's Dead |
|---|---|---|
| In-Game Browser web server | 1,091 | CCP removed the IGB from EVE in 2017 |
| Certificate Browser | 4,986 | CCP removed certificates from EVE in 2014 |
| Logitech G15 keyboard LCD driver | 1,668 | Hardware discontinued in 2008 |
| Cloud storage sync | 2,612 | Deprecated SDKs, dead feature |
| Mineral price worksheet | 1,525 | EVE-Central shut down in 2016 |
| 3D pie chart renderer | 4,299 | Windows-only, can't work in modern frameworks |
| Hammertime structure API | 420 | API shut down around 2020 |
| Osmium/BattleClinic loadouts | 223+ | Both sites shut down by 2019 |
| Market price fetchers | 783+ | EVEMarketer shut down around 2020 |
| Watchdog process monitor | 357 | Hardcodes "EVEMon" process name |
| Windows 7 feature detection | 108 | Windows 7 reached end-of-life in 2020 |
The In-Game Browser server contained code for a JavaScript API call that only existed inside a game feature CCP removed nine years ago. The Logitech G15 handler rendered to a 160x43 pixel monochrome LCD on a keyboard discontinued eighteen years ago. The Certificate Browser operated on game data CCP removed twelve years ago.
Every one of these lines was compiling, loading, and using memory — for things that haven't existed in years.
No Way to Run on Linux or Mac
66 files in the business logic project directly imported Windows-specific UI libraries. The character models had Windows-only image types baked into the domain layer. The settings system showed Windows dialog boxes directly from service code.
There was no path to Linux or Mac without untangling all of this first.
No Automated Build Pipeline
Zero continuous integration. No GitHub Actions. No build scripts. No automated anything. The project was built entirely through Visual Studio with no pipeline to catch regressions.
04What This Meant
None of this was anybody's fault. EVEMon was built when .NET Framework 2.0 was current and Windows XP was the target platform. It was upgraded incrementally to .NET Framework 4.6.1, but the fundamental architecture stayed the same.
The result was a codebase that:
- Worked for most users but had a ceiling that Ansza's sixty characters hit
- Could not be tested because everything was tangled together
- Could not run on Linux or Mac because Windows was in the DNA
- Could not be themed because the UI was welded to the business logic
- Was carrying 18,000 lines of dead weight from services that died years ago
To fix the crash — really fix it, not just patch the symptom — I would need to address all of this. Not because I wanted to rebuild an entire application. Because there was no way to fix the scheduler without untangling the event system, and no way to untangle the event system without splitting the project, and no way to split the project without separating the business logic from the Windows code.
One thread pulling another. Again.
Previous: Part 1 — One Thread Pulled Another