Mert Özen Further With Every Line

Blog

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

Series
23 posts found
What Is a Design Pattern? The GoF Catalog, Pattern Anatomy and Patterns That Vanish in Modern Languages
Software Design PART 01

What Is a Design Pattern? The GoF Catalog, Pattern Anatomy and Patterns That Vanish in Modern Languages

A design pattern is a named solution to a design problem that recurs in a given context, with defined roles and a known price (its consequences); it is not a diagram to memorise. The idea from Alexander to the GoF, the GoF's 13-section template, the purpose × scope map, and Norvig's observation on patterns that turn invisible in C# as yield, event and lambdas.

7 Nov 2026 14 min 5
Singleton Pattern: Thread-Safe Lazy<T>, Static Fields and Why the DI Singleton Lifetime Is Better
Software Design PART 02

Singleton Pattern: Thread-Safe Lazy<T>, Static Fields and Why the DI Singleton Lifetime Is Better

If you need a single instance, the cleanest route is not the classic Singleton but registering with AddSingleton in the DI container: the single-instance guarantee stays, while global access and hidden dependencies go away. The race in a naive Singleton, the history of double-checked locking, static readonly and beforefieldinit, Lazy<T>'s exception caching, captive dependencies and shared state inside a singleton, with real output.

7 Nov 2026 14 min 4
Factory Method and Static Factories: Delegating Creation to Subclasses or a Single Method
Software Design PART 03

Factory Method and Static Factories: Delegating Creation to Subclasses or a Single Method

The GoF Factory Method leaves the choice of product to a subclass; a static factory method is a single named method that replaces a constructor, can cache and can return a hidden subtype. The factory-method-in-constructor bug and CA2214, DbConnection.CreateDbCommand, ILoggerFactory and IHttpClientFactory, Func<T>, ActivatorUtilities and keyed services in DI, and ownership of IDisposable products, with real output.

7 Nov 2026 16 min 3
Abstract Factory: Creating Families of Compatible Objects Together
Software Design PART 04

Abstract Factory: Creating Families of Compatible Objects Together

Abstract Factory makes invalid combinations impossible by creating products that must fit together (such as blob storage, queue and secret store) from a single factory; the price is that adding a new product changes every factory. Choosing the family through configuration, ADO.NET's DbProviderFactory and CanCreateBatch, and a factory per tenant with keyed services, with real output.

7 Nov 2026 15 min 3
Builder Pattern: Fluent Builders, WebApplicationBuilder and Where Object Initializers and required Fall Short
Software Design PART 05

Builder Pattern: Fluent Builders, WebApplicationBuilder and Where Object Initializers and required Fall Short

required, init and object initializers make a many-parameter constructor readable, but they do not solve cross-field rules, step order or an immutable result that accumulates piece by piece; Builder enforces those rules at a single Build() moment. How with skips a record's rule, the GoF Builder with a director versus the fluent builder, UriBuilder, connection string builders, the ImmutableArray builder, HostApplicationBuilder and the step builder, with real output.

7 Nov 2026 16 min 4
Prototype Pattern: record and with, Shallow vs Deep Copy and Why ICloneable Is Discouraged
Software Design PART 06

Prototype Pattern: record and with, Shallow vs Deep Copy and Why ICloneable Is Discouraged

Prototype creates a new object by copying a configured sample instead of building it from scratch; in C#, the with expression on records does this while preserving the runtime type, but the copy is shallow. A prototype registry, controlled deep copies with a copy constructor, ICloneable's vague contract, the measured cost of copying through JSON and the with traps that skip validation.

7 Nov 2026 16 min 4
Adapter Pattern: Fitting a Third-Party SDK to Your Own Interface
Software Design PART 07

Adapter Pattern: Fitting a Third-Party SDK to Your Own Interface

Adapter fits a class you can't change to the interface the client expects; in C# that is almost always an object adapter, built with composition. Connecting two imaginary payment SDKs to a single IPaymentGateway, turning a callback into a Task with TaskCompletionSource, mapping error codes to domain exceptions and verifying both adapters with the same contract test.

7 Nov 2026 14 min 3
Bridge Pattern: Letting Abstraction and Implementation Grow Independently
Software Design PART 08

Bridge Pattern: Letting Abstraction and Implementation Grow Independently

Bridge splits two independent axes of change (like message type and channel) into two hierarchies connected by a reference, instead of squeezing them into one inheritance hierarchy, so the class count becomes a sum rather than a product. Moving Bookstore's notifications from a 3 × 3 class explosion to 3 + 3, the HttpClient/HttpMessageHandler and ILogger/ILoggerProvider bridges and how it differs from Adapter.

7 Nov 2026 13 min 3
Composite Pattern: Treating Tree Structures Through One Interface
Software Design PART 09

Composite Pattern: Treating Tree Structures Through One Interface

Composite puts leaves and the composites containing them behind the same interface, so the client can use a single item and a nested tree without telling them apart; the recursion stays in the only place that knows the tree, inside the composite. Pricing nested book bundles in Bookstore, the transparency versus safety choice, IConfiguration and CompositeChangeToken, and the stack overflow of a cyclic tree.

7 Nov 2026 12 min 4
Decorator Pattern: Adding Caching, Logging and Retry Without Touching the Code
Software Design PART 10

Decorator Pattern: Adding Caching, Logging and Retry Without Touching the Code

Decorator adds behavior to an object at runtime by implementing the same interface and delegating to the object inside; the order of decorators is a design decision that determines what they measure and what they protect. Adding cache, logging and retries to Bookstore's catalog, the Stream family and ownership with leaveOpen, manual DI registration and Scrutor's Decorate, DelegatingHandler and how default interface methods silently bypass a decorator.

7 Nov 2026 13 min 5
Facade Pattern: Presenting a Complex Subsystem Through a Single Door
Software Design PART 11

Facade Pattern: Presenting a Complex Subsystem Through a Single Door

A facade gathers the knowledge of using several subsystems in the right order, with the right compensation steps, into one class; it gives clients an easy entry point without closing off the subsystem. A CheckoutFacade in Bookstore that coordinates stock, payment, invoicing and notification, the real code behind File.ReadAllTextAsync and GetFromJsonAsync, how Facade differs from Service Layer, Adapter and Mediator, and the god facade trap.

7 Nov 2026 13 min 4
Flyweight Pattern: Saving Memory with Shared State — string.Intern and ArrayPool
Software Design PART 12

Flyweight Pattern: Saving Memory with Shared State — string.Intern and ArrayPool

Flyweight stores the repeating, immutable part of many objects (intrinsic state) once through a factory and shares it, keeping the line-specific part (extrinsic state) outside. A BookInfoFactory that cuts a million-line report from 377 MB to 30 MB, the side effects of string.Intern, the Task and array instances .NET already shares, why ArrayPool is an object pool rather than a flyweight, and BenchmarkDotNet measurements.

7 Nov 2026 14 min 3
Blog Map