Mert Özen Further With Every Line

Blog

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

Series
47 posts found
Clean Code in Practice: Cleaning Up a Legacy OrderService Step by Step
Software Design PART 14

Clean Code in Practice: Cleaning Up a Legacy OrderService Step by Step

The safe way to clean up legacy code is to first pin the current behavior with a small seam and characterization tests, then make every step a separate commit and keep behavior changes in their own fix commits. The post cleans up the 609-line OrderService in 16 commits with green tests at every commit; the highest Cognitive Complexity drops from 92 to 10, and the smells left on purpose are listed with their reasons.

7 Nov 2026 14 min 1
The Clean Code Debate: Ousterhout, Muratori and the Limits of the Rules
Software Design PART 13

The Clean Code Debate: Ousterhout, Muratori and the Limits of the Rules

Ousterhout and Martin agree on the goal, reducing the reader's load; they part on how far to split methods, the value of comments and TDD. The post summarizes the 2024–25 debate, Muratori's performance critique (repeated in C# with BenchmarkDotNet) and qntm's critique of the book from each side's own sources.

7 Nov 2026 13 min 2
A Code Smell Catalog: Recognizing Smells in C# Code
Software Design PART 12

A Code Smell Catalog: Recognizing Smells in C# Code

A code smell is a surface indication that usually points to a deeper design problem; it's not a diagnosis but a sign of where to look. The post maps Fowler's 24 second-edition smells onto Mäntylä's five groups, looks for each one in the legacy OrderService.cs and shows with real output which ones SonarAnalyzer catches and which it misses.

7 Nov 2026 12 min 2
The Four Rules of Simple Design: Passes Tests, Reveals Intent, No Duplication, Fewest Elements
Software Design PART 11

The Four Rules of Simple Design: Passes Tests, Reveals Intent, No Duplication, Fewest Elements

Kent Beck's simple design rules, in priority order, are: passes the tests, reveals intention, no duplication, fewest elements. The post grows a coupon discount calculation step by step with these four questions, separates coincidental similarity from real duplication and shows the cost of an over-generalized version that passes the same tests.

7 Nov 2026 13 min 1
Clean Test Code: F.I.R.S.T., Readable Asserts and Test Data Builders
Software Design PART 10

Clean Test Code: F.I.R.S.T., Readable Asserts and Test Data Builders

A clean test is fast, independent, repeatable, self-validating and timely (F.I.R.S.T.); the legacy OrderService tests break on Saturdays because of DateTime.Now and depending on run order because of the static Db. With TimeProvider and FakeTimeProvider, a test data builder, test names that read like sentences and asserts that state the reason when they fail, we turn the same rules into clean tests.

7 Nov 2026 11 min 2
Classes in Clean Code: Small Classes, Cohesion and Organizing for Change
Software Design PART 09

Classes in Clean Code: Small Classes, Cohesion and Organizing for Change

A class's size is measured by the number of actors who ask it to change, not by lines; methods that share no fields and CA1822 "make it static" warnings signal low cohesion. In the legacy OrderService two price calculations in the same class had drifted apart, quoting 731.50 TRY and charging 690.52 TRY; we gather pricing into a single OrderPricing class and build modern C# classes with primary constructors, sealed and required.

7 Nov 2026 13 min 2
Boundaries: Wrapping Third-Party Code and Learning Tests
Software Design PART 08

Boundaries: Wrapping Third-Party Code and Learning Tests

Put code you don't control, such as a payment SDK, an email library and a cache, behind an interface shaped by your own need and a single adapter; don't let its types and exceptions leak in. Pin the library's behavior down with learning tests: MimeKit's TryParse even accepts "ada", and on the upgrade from 4.17.0 to 4.18.2 all 13 tests passed unchanged while a transitive security warning disappeared.

7 Nov 2026 11 min 2
Error Handling in Clean Code: Exceptions, the Try Pattern and the Result Pattern
Software Design PART 07

Error Handling in Clean Code: Exceptions, the Try Pattern and the Result Pattern

Use the Try pattern or Result<T> for expected business outcomes (out of stock, invalid coupon, payment declined), argument exceptions for bugs and exceptions with added context for infrastructure failures, and catch them only at the application's boundary. We clean up the return codes, the static LastError and the empty catch blocks of the legacy OrderService with these three tools; in our measurement a thrown exception is about 1,165 times slower than TryParse.

7 Nov 2026 14 min 0
Objects or Data Structures? Records, DTOs and Primitive Obsession
Software Design PART 06

Objects or Data Structures? Records, DTOs and Primitive Obsession

An object hides its data and exposes behavior, a data structure exposes data and carries no behavior, and the hybrid in between is the most expensive of all. Use records for DTOs, encapsulation for the domain and value objects such as Money and Email for concepts carried in strings and decimals; we also give a short introduction to the Law of Demeter.

7 Nov 2026 16 min 0
Formatting and File Layout: Making Code Read Like a Newspaper
Software Design PART 05

Formatting and File Layout: Making Code Read Like a Newspaper

Formatting is communication, not aesthetics, and a tool rather than a person should enforce it: wrong indentation in a brace-less if makes the log say an e-mail was sent when it wasn't, and SonarAnalyzer and dotnet format catch it, not the compiler. The post covers the newspaper metaphor, vertical layout, member order, one type per file, converting to file-scoped namespaces and splitting a 259-character LINQ chain into lines, with real output.

7 Nov 2026 11 min 0
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 0
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 0
Blog Map