When I started building applications, I used to have a fairly simple definition of success:
𝐈𝐟 𝐢𝐭 𝐰𝐨𝐫𝐤𝐬, 𝐢𝐭'𝐬 𝐰𝐨𝐫𝐤𝐢𝐧𝐠.
And honestly, that mindset makes sense when you're learning.
You build a feature.
You run it.
It works.
You fix a bug.
You run it again.
It works.
You add another feature.
It still works.
So you move on.
But as I've spent more time building and maintaining applications, I'm realizing that "𝐰𝐨𝐫𝐤𝐢𝐧𝐠" 𝐢𝐬 𝐨𝐧𝐥𝐲 𝐨𝐧𝐞 𝐩𝐚𝐫𝐭 𝐨𝐟 𝐠𝐨𝐨𝐝 𝐬𝐨𝐟𝐭𝐰𝐚𝐫𝐞 𝐞𝐧𝐠𝐢𝐧𝐞𝐞𝐫𝐢𝐧𝐠.
An application can work perfectly and still be difficult to maintain.
It can produce the right output while having an architecture that becomes painful to change.
It can pass a few manual tests while having almost no automated protection against regressions.
It can look polished while handling user input poorly.
And it can work today while making tomorrow's development significantly harder.
That's a distinction I'm learning to appreciate.
The questions start changing
Earlier in my development journey, I was mostly asking:
"𝘏𝘰𝘸 𝘥𝘰 𝘐 𝘮𝘢𝘬𝘦 𝘵𝘩𝘪𝘴 𝘧𝘦𝘢𝘵𝘶𝘳𝘦 𝘸𝘰𝘳𝘬?"
Now I'm increasingly asking:
- Can someone else understand this code?
- Can I change one feature without breaking three others?
- Are the important parts tested?
- What happens when an external service fails?
- Is user input handled safely?
- Can I diagnose a problem when something goes wrong?
- Are responsibilities separated properly?
- Will this architecture still make sense as the application grows?
Those questions don't necessarily make an application look better.
But they can make it last 𝐥𝐨𝐧𝐠𝐞𝐫.
And I think that's where engineering starts becoming different from simply writing code.
I experienced this while building
I recently found myself confronting this while working on a developer tool.
The application worked.
There wasn't some massive bug forcing me to stop everything.
The problem was subtler.
As I added features, responsibilities started accumulating in the same places.
Application state was mixed into the main application logic.
External integrations were living alongside UI behaviour.
README generation was becoming part of a large application file.
Again, nothing was necessarily broken.
But the code was becoming harder to reason about.
And that was enough of a problem.
So I started refactoring.
I extracted application state into its own module.
I separated the DEV.to integration.
I moved README generation into its own generator module.
I added tests around important behaviour.
I introduced security helpers for things like URL validation and output escaping.
And suddenly, the goal of the refactoring became clearer.
I wasn't refactoring because the application stopped working.
I was refactoring because I wanted to make it easier to keep working.
That's a different way of thinking about software
There's a temptation, especially when you're building quickly, to think about engineering quality as something you add later.
First:
Build it.
Then:
Make it work.
Then:
Maybe we'll clean it up.
But I'm starting to think some of these concerns aren't really "cleanup."
Testing isn't cleanup.
Security isn't cleanup.
Good separation of responsibilities isn't cleanup.
Readable code isn't cleanup.
A structure that makes future changes easier isn't cleanup.
They're all part of the product.
Maintainability is a feature
This is probably the biggest lesson I'm taking away.
When we talk about application features, we usually think about things users can directly see:
- authentication
- dashboards
- search
- notifications
- integrations
- reports
But maintainability is also a feature, just one that developers experience rather than end users.
A maintainable application makes it easier to:
𝙪𝙣𝙙𝙚𝙧𝙨𝙩𝙖𝙣𝙙 → 𝙘𝙝𝙖𝙣𝙜𝙚 → 𝙩𝙚𝙨𝙩 → 𝙙𝙚𝙗𝙪𝙜 → 𝙚𝙭𝙩𝙚𝙣𝙙
And that has a real impact on how quickly a team can build.
I'm still learning this
I don't think I've suddenly figured out what "good software engineering" means.
Far from it.
I'm learning by building things, breaking things, refactoring things, reading other people's code, and occasionally looking at something I wrote a few weeks earlier and asking:
"𝙒𝙝𝙮 𝙙𝙞𝙙 𝙄 𝙙𝙤 𝙞𝙩 𝙩𝙝𝙞𝙨 𝙬𝙖𝙮 😂?"
But that's probably part of the process.
The more I build, the more I realize that software engineering isn't simply about making something work.
It's about making something that continues to work as people, requirements, dependencies, and the codebase itself change.
And I'm beginning to appreciate that:
Good engineering isn't just about making software work. It's about making it possible for the software to keep working as it evolves.
That's a lesson I'm taking with me into every project I build from here.
If you're early in your software journey like me, don't feel like you need to understand all of this immediately.
Build things.
Make them work.
Break them.
Fix them.
Then go back and ask:
"What would make this easier to maintain?"
Because sometimes, that's where the real learning begins.
Top comments (0)