Architecture principles and methodologies are a set of rules and guidelines that help developers create maintainable, scalable, and understandable code. According to TIOBE Index (2025), projects following architecture principles have 40% fewer critical defects. In this article, we'll cover SOLID, GRASP, DRY, KISS, YAGNI, and other principles, as well as discuss technical debt and Code Smell.
Key Takeaways
Architecture principles are the foundation of quality code. SOLID is an acronym introduced by Robert Martin ("Uncle Bob") describing five principles of object-oriented design. Following SOLID makes code more flexible, testable, and resilient to change. Violating architecture principles is one of the main causes of technical debt.
Let's examine each principle. Single Responsibility Principle (SRP) — each class should have only one reason to change. Open/Closed Principle (OCP) — classes are open for extension but closed for modification. Liskov Substitution Principle (LSP) — subtype objects should replace base type objects without breaking logic. Interface Segregation Principle (ISP) — many specialized interfaces are better than one general interface. Dependency Inversion Principle (DIP) — depend on abstractions, not on concrete implementations.
According to SonarQube analysis (2025), violation of SOLID principles occurs in 68% of commercial projects. The most common issues are SRP violation (35%) and ISP violation (22%). At IT Sectr, we implement SOLID at the architecture review stage — this helps identify problems before they grow into technical debt.
SRP (Single Responsibility Principle) — the most important and simultaneously the most frequently violated SOLID principle. It states: a class should have only one reason to change. If a class does too much, it's difficult to test, modify, and understand.
A typical violation is a class that simultaneously processes data, saves it to the database, and sends email notifications. The example below shows an SRP violation in Kotlin and how to fix it.
// SRP violation — class does three different things
class UserService {
fun registerUser(email: String, name: String) {
// 1. Data validation
if (!email.contains("@")) throw IllegalArgumentException("Invalid email")
// 2. Save to database
val user = User(email, name)
database.save(user)
// 3. Send notification
emailService.sendWelcomeEmail(email, name)
}
}
// Fix — split into three classes
class UserRegistrationService {
fun register(email: String, name: String) {
UserValidator().validate(email)
val user = User(email, name)
UserRepository().save(user)
NotificationService().sendWelcome(user)
}
}
In the fixed version, each class is responsible for its own task: UserValidator — for validation, UserRepository — for saving, NotificationService — for notifications. This makes the code testable and reusable — you can replace the database implementation without changing the validation logic.
GRASP (General Responsibility Assignment Software Patterns) — nine architecture principles for assigning responsibility between objects, described by Craig Larman. Unlike SOLID, GRASP answers the question "which class should contain this method?". Key patterns: Information Expert, Creator, Controller, Low Coupling, High Cohesion, Polymorphism, Pure Fabrication, Indirection, Protected Variations.
Law of Demeter (LoD, principle of minimal coupling) — a simple rule: an object should only communicate with its immediate neighbors. You shouldn't write a.getB().getC().doSomething() — this creates tight coupling between classes. LoD improves reusability and simplifies testing.
At IT Sectr, we check LoD compliance during Code Review. If a method "goes through" three or more objects, it's a signal that the architecture needs simplification. LoD violation is one of the most common Code Smells in large projects.
DRY (Don't Repeat Yourself), KISS (Keep It Simple, Stupid), and YAGNI (You Ain't Gonna Need It) — three basic architecture principles known to every developer. Despite their simplicity, violations occur constantly.
DRY — don't duplicate code. If the same logic appears in two places, extract it into a common method or class. Duplication is the main source of bugs: a fix in one place is forgotten to be applied in another. DRY doesn't mean you can't have similar code — the important thing is that business logic is not repeated.
KISS — simpler is better. Complex solutions with many abstractions and inheritances are often excessive. Start with a simple solution and make it more complex only when necessary. YAGNI — don't write code for functionality that might be needed "someday later." This leads to codebase bloat and increased maintenance complexity.
DRY — it's not just about the absence of copy-paste. It's a principle according to which every piece of knowledge or logic should have a single, unambiguous representation in the system. Duplication can be explicit (copied code) and implicit (same logic in different layers).
At IT Sectr, we use code analysis metrics to detect duplication. Tools like SonarQube and Detekt show the percentage of duplicated code. A value above 5% is a reason for refactoring. However, it's important to remember: DRY should not be achieved at the cost of wrong abstractions — sometimes two similar pieces of code are better left as is if combining them would complicate understanding.
Separation of Concerns (SoC) — an architecture principle where a system is divided into independent parts (concerns), each solving its own task. A classic example is layer separation: presentation, business logic, data access. Each layer depends only on the one below it.
Modularity — the degree to which a system can be broken into modules. A module is a logically related group of classes with a well-defined interface. Modules should be loosely coupled (low coupling) and highly cohesive (high cohesion).
Cohesion — a measure of how much elements within a single module are related to each other. High cohesion is good: a class does one thing and does it well. Low coupling — a measure of how much modules are independent of each other. Low coupling is good: changing one module doesn't break others.
Ideal architecture is high cohesion and low coupling. In practice, this means: a class contains methods that work on the same data (cohesion), and depends only on abstractions, not on concrete implementations (coupling). An imbalance leads to "God Objects" or "spaghetti code."
Technical Debt — a metaphor introduced by Ward Cunningham describing the "interest" a team pays for suboptimal architecture decisions and violation of architecture principles. Like financial debt, technical debt can be intentional (we decided to do it fast, we'll redo it later) and unintentional (poor architecture due to lack of experience).
Code Smell — superficial signs of deep problems in code. The term was popularized by Martin Fowler in the book "Refactoring." Typical Code Smells: long methods, large classes, long call chains, code duplication, excessive use of comments (instead of clear code).
At IT Sectr, technical debt is tracked in Jira as separate tasks. Each sprint, we allocate 20% of time for refactoring and debt repayment. Systematic work with technical debt is the only way to avoid a situation where adding a new feature takes longer than developing it from scratch.
Frequently Asked Questions
Single Responsibility Principle (SRP) — the most important, since its violation automatically leads to violation of other principles. A class with multiple responsibilities is difficult to test, extend, and maintain. Start with SRP — the rest will follow.
Cohesion — the connection within a module (the higher, the better). Coupling — the connection between modules (the lower, the better). Good architecture strives for high cohesion and low coupling.
No, principles are guidelines, not absolute laws. In small projects or prototypes, excessive adherence to SOLID can lead to overengineering. It's important to find a balance between "good enough" architecture and development speed.
Use static analyzers (SonarQube, Detekt, ESLint), Code Review, and code metrics. Signs of debt: code is difficult to test, changes in one place break another, the time to add a new feature increases from sprint to sprint. Regular refactoring is the only way to control debt.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.