AI has been moving at a breakneck pace. Many people are getting hooked on barking orders at AI and then discovering piles of error‑ridden code it produced (and in truth, you may not fully understand the code the AI wrote either).
If you do understand AI, sure—you know how to use prompt engineering. Still, I want to reinforce the fundamentals of software engineering.
Object‑oriented programming, design principles, design patterns, coding conventions, and refactoring.
Programming paradigms/styles
The mainstream programming paradigms/styles are:
- Procedural programming
- Object‑oriented programming (OOP)
- Functional programming
Among them, OOP remains the most widely adopted paradigm. Most popular programming languages today are object‑oriented or provide strong OO support.
Design principles
Definition: distilled practical experience for code design.
These principles often sound abstract and are described vaguely.
The hard part: understand the original intent, the specific problems they solve, and the scenarios where they apply.
Common principles include:
SOLID principles
You might wonder why SOLID uniquely comes with five additional “sub‑principles.”
I had the same question, so I looked it up.
SOLID is called the cornerstone of object‑oriented design because it offers a concrete, actionable toolkit—rather than vague ideas—for solving real problems in software development.
Each sub‑principle targets a different layer of design pitfalls. It stands out precisely because it is not a single fuzzy rule, but a collection of five specific, operable design principles.
- Single Responsibility Principle (SRP)
- Open/Closed Principle (OCP)
- Liskov Substitution Principle (LSP)
- Interface Segregation Principle (ISP)
- Dependency Inversion Principle (DIP)
KISS principle (Keep It Simple, Stupid)
DRY principle (Don’t Repeat Yourself)
YAGNI principle (You Aren’t Gonna Need It)
Law of Demeter (LOD)
Design patterns
Definition: recurring solutions or design approaches distilled from frequently encountered problems in software development.
Most design patterns are fundamentally about extensibility.
The hard part: knowing which problem each pattern addresses, recognizing typical application scenarios, and—importantly—avoiding overuse.
What’s included: there are 23 classic design patterns.
As languages evolve:
- Some patterns (e.g., Singleton) have aged poorly and even become anti‑patterns.
- Some are now built into languages (e.g., Iterator).
- New patterns keep emerging (e.g., Monostate).
The 23 classic patterns are grouped into three categories: creational, structural, and behavioral.
Creational
Common: Singleton, Factory (Factory Method and Abstract Factory), Builder.
Less common: Prototype.
Structural
Common: Proxy, Bridge, Decorator, Adapter.
Less common: Facade, Composite, Flyweight.
Behavioral
Common: Observer, Template Method, Strategy, Chain of Responsibility, Iterator, State.
Less common: Visitor, Memento, Command, Interpreter, Mediator.
Coding conventions
Definition: primarily concerned with readability. Compared with design principles and design patterns, conventions are more concrete and closer to code‑level details. Even if you’re unfamiliar with design principles or patterns, at minimum you should master basic coding conventions.
For example: how to name variables, classes, and functions; how to write comments; keep functions short; avoid too many parameters; and so on.
There are plenty of classic books to learn from—“Refactoring,” “Code Complete,” and “Clean Code,” to name a few.
Each convention is straightforward and specific. Just remember them and follow them. Unlike design principles, they require less personal interpretation.
Refactoring
As long as a project is alive and people keep working on it, the software will evolve. New features will inevitably push older code to be refactored. Refactoring is the practical way to keep code quality from decaying to an unrecoverable state.
The toolkit for refactoring includes everything mentioned earlier: paradigms, design principles, design patterns, and coding conventions.
While design patterns can improve extensibility, overuse or misuse increases complexity and harms readability.
In early development, unless absolutely necessary, don’t over‑design or apply complex patterns.
Instead, when code shows concrete issues, refactor to address those issues using the appropriate principles and patterns.
This effectively prevents premature over‑engineering.
Must‑know points
As follows:
- The purpose (why), target (what), timing (when), and methods (how) of refactoring
- Techniques for safe refactoring: unit tests and code testability
- Two scales of refactoring: large‑scale/high‑level and small‑scale/low‑level
How the five pieces fit together
The relationship among OOP, design principles, design patterns, coding conventions, and refactoring is as follows:
- OOP, with its rich features (encapsulation, abstraction, inheritance, polymorphism), enables sophisticated design ideas and is the foundation for implementing many principles and patterns.
- Design principles guide design decisions and help determine whether a particular pattern should be applied in a given scenario. For example, the Open/Closed Principle underpins patterns such as Strategy and Template Method.
- Design patterns are recurring solutions to common design problems in software development. Their main goal is to improve extensibility. In terms of abstraction, principles are more abstract; patterns are more concrete and executable.
- Coding conventions primarily address readability. Compared with principles and patterns, conventions are more specific, detail‑oriented, and directly actionable. Continuous small‑scale refactoring relies heavily on conventions as its theoretical backbone.
Ultimately, this article is about one thing: writing high‑quality code. Once you trace it back to that, how to do many things—and how to implement them in code—becomes clear.

PS: A bunch of keywords for further exploration:
System architecture principles High cohesion and low coupling Law of Demeter (principle of least knowledge) Composition over inheritance Separation of concerns Design by contract Cloud‑native design principles Resilience design principles Observability principles Immutable infrastructure Service autonomy Declarative configuration Security by design Defense in depth Principle of least privilege Secure by default Separation of duties Fail‑safe
Comments