Mert Özen Further With Every Line

Blog

Mert Özen's blog posts on software development, backend, frontend, and DevOps.

Series
472 posts found
Comments in Clean Code: When to Write Them and When to Turn Them into Code
Software Design PART 04

Comments in Clean Code: When to Write Them and When to Turn Them into Code

Put in code what code can say (names, constants, enums, methods) and in a comment what it can't (why, warnings, external context, a public API's contract): most comments in the legacy OrderService repeat the code, two of them lie, and changelogs and commented-out code belong in Git. The post shows how XML doc comments are checked through CS1572/CS1573/CS1574/CS1591 and covers Ousterhout's case for interface comments, with real output.

7 Nov 2026 11 min 4
Naming in Clean Code: Intention-Revealing Names, .NET Guidelines and Mixed Turkish-English Names
Software Design PART 02

Naming in Clean Code: Intention-Revealing Names, .NET Guidelines and Mixed Turkish-English Names

A good name answers the questions a reader would otherwise ask the code: replacing d, tmp2, k and int t in the legacy OrderService with domain names and constants makes the pricing readable without changing behavior (same totals in five scenarios). The post covers .NET naming rules, Hungarian notation, mixed Turkish-English names and the Turkish I trap that turns Id into ıd under tr-TR, with real output.

7 Nov 2026 14 min 6
What Is Clean Code? Readability, Cost of Change and the 2025 Second Edition
Software Design PART 01

What Is Clean Code? Readability, Cost of Change and the 2025 Second Edition

Clean code is code that works and is also cheap to read and change: in Bookstore's legacy OrderService the same cart yields four different totals because of the Turkish I trap, a drifted copy of the pricing logic and DateTime.Now. The 2025 second edition rewrote the book into Code, Design, Architecture and Craftsmanship parts; this series cleans the 609-line file step by step.

7 Nov 2026 16 min 5
Critiquing the Principles: CUPID, Over-Engineering and Where SOLID Really Pays Off
Software Design PART 12

Critiquing the Principles: CUPID, Over-Engineering and Where SOLID Really Pays Off

SOLID's value depends on context: in multi-team, long-lived, frequently changing code it lowers the cost of change, while in scripts, prototypes and small CRUD apps it often just adds layers. The measured cost of adding a push channel to minimal, balanced and excessive designs of the same notification feature, Dan North's CUPID proposal and Ousterhout's deep module warning.

7 Nov 2026 11 min 5
Component Principles: Splitting a .NET Solution into Projects (REP, CCP, CRP, ADP, SDP, SAP)
Software Design PART 11

Component Principles: Splitting a .NET Solution into Projects (REP, CCP, CRP, ADP, SDP, SAP)

When splitting a solution into projects, classes that change together belong in the same project, dependencies must be acyclic and flow toward stability, and stable projects should be abstract. Measuring the cost of a Common project everyone depends on, computing instability and abstractness on a real solution, and reading the main sequence correctly.

7 Nov 2026 12 min 3
Lesser-Known Principles: Separation of Concerns, Least Astonishment, Fail Fast, CQS and GRASP
Software Design PART 10

Lesser-Known Principles: Separation of Concerns, Least Astonishment, Fail Fast, CQS and GRASP

The principles outside SOLID drive most everyday decisions: Fail Fast catches errors at startup, CQS keeps a question from changing the answer, and GRASP asks which class a responsibility belongs to. Catching a configuration typo with options validation, the Math.Round surprise, side effects in getters, Explicit Dependencies, Persistence Ignorance and deciding when principles collide.

7 Nov 2026 12 min 5
Composition over Inheritance: Fragile Base Class, Delegation and Pluggable Behavior
Software Design PART 09

Composition over Inheritance: Fragile Base Class, Delegation and Pluggable Behavior

Inheritance ties a subclass to its base class's implementation details, so a harmless change in the base class can silently break a subclass, while composition and delegation depend only on the contract. The fragile base class problem shown with real output, the class explosion when behavior grows along two axes, and where inheritance is right: Collection<T> hooks and sealed.

7 Nov 2026 13 min 3
DRY, KISS and YAGNI: Duplication, Simplicity and "You Aren't Gonna Need It"
Software Design PART 08

DRY, KISS and YAGNI: Duplication, Simplicity and "You Aren't Gonna Need It"

DRY means a single source for knowledge, not for code; merging two rules that change for different reasons just because they look alike is not DRY but a wrong abstraction. Backing out of a wrong abstraction as Metz suggests, the rule of three, measuring KISS with CA1502, and the four costs Fowler lists for YAGNI.

7 Nov 2026 12 min 3
Dependency Inversion Principle: DIP vs DI vs IoC and the Composition Root
Software Design PART 07

Dependency Inversion Principle: DIP vs DI vs IoC and the Composition Root

DIP asks for the compile-time dependency to flow from details to abstractions and for the abstraction to be owned by its user; DI is only the technique of supplying dependencies from outside, and IoC is control of the flow moving to a framework. Which project the interface belongs in, using Program.cs as the composition root, and why a service locator defeats DIP.

7 Nov 2026 12 min 5
Interface Segregation Principle: Fat Interfaces and Role Interfaces
Software Design PART 06

Interface Segregation Principle: Fat Interfaces and Role Interfaces

ISP means no client should be forced to depend on methods it doesn't use, and interfaces are cut by client (role interfaces), not by class. One method added to a 14-method IOrderRepository breaking three files, splitting into read/write/report roles and forwarding in DI, IReadOnlyList<T> and IList<T> still separate in .NET 10, single-method interface inflation and the cost of piercing ISP with default interface methods.

7 Nov 2026 12 min 3
Liskov Substitution Principle: Behavioral Subtyping and NotSupportedException in .NET
Software Design PART 05

Liskov Substitution Principle: Behavioral Subtyping and NotSupportedException in .NET

LSP requires a subtype to satisfy not just the compiler but the base type's contract: preconditions aren't strengthened, postconditions aren't weakened, invariants and the history constraint are preserved. Three real violations in Bookstore's stock module, the NotSupportedException that T[] and ReadOnlyCollection throw from IList<T>.Add, capability queries with Stream.CanSeek, and verifying the contract against every implementation with an abstract xUnit test class.

7 Nov 2026 15 min 4
Open/Closed Principle: Extending Without Modifying and the Speculative Generality Trap
Software Design PART 04

Open/Closed Principle: Extending Without Modifying and the Speculative Generality Trap

OCP means adding new behavior as a new implementation without opening existing, working code; but any code can only be closed against a particular axis of change. Closing a growing notification switch with INotificationChannel and .NET 8 keyed services, HttpClient's DelegatingHandler chain, lightweight extension points with Func, and the cost of speculative generality.

7 Nov 2026 12 min 2
Blog Map