Sitemap

Essential Knowledge for Building Software from Scratch

5 min readFeb 17, 2025
Building Software from scratch

Building an application from scratch is a challenging skill — even more so in 2025. In today’s world, most development happens on top of existing frameworks and libraries, so the foundational knowledge of designing software from the ground up is often overlooked. I’ve been a developer for a long time, and I’ve seen how our approach to software design has evolved. Here’s what I’ve learned along the way.

The Evolution of Software Design Knowledge

Why Does This Knowledge Seem Scarce?

It’s not that the knowledge is completely missing; it’s just become scattered and less emphasized. Back in the 1990s, object-oriented programming (OOP) was all the rage. The 2000s brought the Agile movement, and even into the early 2010s, many books discussed designing software from scratch. However, as of 2025, our focus has shifted.

Today, most software is built on existing codebases or frameworks. Good design often means following the principles laid out by the framework you’re using, not reinventing the wheel. Yet, there are still valuable gems hidden in older resources — even if much of the literature dates back to the 2000s. For instance, Agile Software Development, Principles, Patterns, and Practices by Robert Martin is one classic that offers timeless insights.

I believe spending hours digging through outdated books for a few useful ideas isn’t efficient. So, I’m sharing my thoughts to help you quickly get the key points.

Key Areas for Building Software from Scratch

I’d like to focus on three core areas that are essential when building software from scratch:

  1. SOLID Principles
  2. Design Patterns
  3. Evolutionary Design

1. SOLID Principles

While modern programming languages now support multiple paradigms — including functional programming — the way we structure our code in object-oriented languages remains critical. The SOLID principles help you design your classes responsibly and create maintainable code. They’re especially relevant in languages like C# and Java.

For a detailed explanation of these principles, check out this article from Baeldung:

https://www.baeldung.com/solid-principles

2. Design Patterns

Even though some argue that design patterns are outdated or even become anti-patterns when overused, many still offer practical benefits when applied correctly. Here are a few patterns that continue to be useful:

  • State/Strategy Pattern:
    Polymorphism is key to writing clean, abstracted code. Used correctly, these patterns help manage complexity — but overusing them can lead to confusing designs.
  • Template Method Pattern:
    This pattern also leverages polymorphism to allow flexible code reuse and can be very effective.
  • Factory Method & Singleton:
    These patterns are less common today since many dependencies injection (DI) frameworks (especially in C#) handle similar responsibilities. Nevertheless, understanding their concepts is valuable.
  • Builder Pattern:
    Often used in modern APIs, this pattern helps construct complex objects step by step. Even if implementations differ slightly from the original pattern, the concept is worth knowing.
  • Composite & Decorator Patterns:
    While these are particularly useful for UI development, learning them provides insight into many other design patterns by teaching you how to structure and extend your code effectively.

For cloud developers, it’s also important to study Cloud Design Patterns. Frameworks like ASP.NET come with their own design guidelines that are worth following. Ultimately, a key part of all these patterns is using a ubiquitous language — if you see a class named SomethingBuilder, you can guess its purpose without needing a deep dive into its code.

3. Evolutionary Design

In the 1990s, the explosion of object-oriented design sometimes led to over-engineered solutions. Many developers applied patterns too rigidly, resulting in overly complex systems — a phenomenon summed up by the saying,

To a man with a hammer, everything looks like a nail.

Back then, the norm was to design everything upfront and then start coding. However, this approach often resulted in designs that didn’t work well in practice. The turning point came when Martin Fowler’s article, Is Design Dead?, introduced the concept of evolutionary design.

The idea is simple: rather than trying to predict every detail of your system from the start, write your code, then refactor as needed when duplication or inefficiencies appear. This approach aligns with practices from Extreme Programming (XP) by Kent Beck, such as:

  • YAGNI (You Ain’t Gonna Need It):
    Delay adding functionality until it’s absolutely necessary.
  • KISS (Keep It Simple, Stupid):
    Avoid unnecessary complexity.
  • Red-Green-Refactor:
    Write tests, ensure your code passes them, then continuously refactor to improve design.

While evolutionary design may not be a perfect fit for every project (especially large, long-term systems like cloud infrastructure with many external dependencies), balancing upfront planning with iterative improvements can lead to more robust and flexible software.

For more on this approach, I recommend reading Test Driven Development by Kent Beck. Despite the advent of AI-assisted development, the principles in this book remain timeless.

Conclusion

I’ve shared these ideas to help you bypass the overwhelming amount of outdated information and focus on the key concepts that remain relevant. In the era of AI, you don’t have to memorize every detail — just grasp the essential keywords and let modern tools help you fill in the gaps.

Enjoy coding and keep learning!

--

--

Tsuyoshi Ushio
Tsuyoshi Ushio

Written by Tsuyoshi Ushio

Senior Software Engineer — Microsoft

No responses yet