Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
From Class Diagram to Code and Back: Domain Model, Design Model and puml-gen
A domain model shows business concepts without types or operations, while a design class diagram shows the C#-level design decisions for the same case; the first is drawn by hand, slices of the second become code, and diagrams generated from code with tools like puml-gen are for observation and drift checks only. The post takes the HR Portal leave module from diagram to EF Core configuration and DDL, then back to PlantUML with puml-gen.
Class Diagrams 2: Association, Aggregation, Composition, Generalization and Dependency — with C# Equivalents
An association is a lasting link and becomes a navigation property in C#; in a composition the part has one owner and is deleted with it, which in EF Core means an owned or complex type or cascade delete; aggregation has no precise meaning in UML 2.5.1. The notation and C# counterpart of six relationships, EF Core's cascade default on required relationships, qualified associations, and why Approval is promoted from an association class to a class of its own.
Class Diagrams 1: Classes, Attributes, Operations, Visibility, Multiplicity and Stereotypes
Every marker in a class diagram is a decision in code: [0..1] is a nullable type, [0..*] a collection, a slash a computed property, an underlined line a static member, and {readOnly} a field that never changes. The three compartments of a class box, attribute and operation syntax, the corners where visibility does not match C#, interfaces, enumerations, data types and stereotypes, and the same diagram in Mermaid.
Use Case Diagrams and Specifications: Actors, include, extend and the Cockburn Template
A use case diagram shows the system from outside: actors are roles, use cases are goals; the include arrow goes from the base to a mandatory step, the extend arrow from a conditional addition to the base. The HR Portal leave module's use case diagram, the Request Leave specification in Cockburn's fully dressed template, mapping use cases to user stories and API endpoints, and the same diagram in Mermaid.
From Requirements to Diagrams: Which Question Does Each Diagram Answer?
Every diagram answers one question: use cases answer who does what, class diagrams which concepts exist, sequence diagrams who calls whom, and state machines which states an object goes through. The requirements of the HR Portal Leave Request module, extracting candidate classes, use cases and guards from nouns, verbs and conditions, choosing the level of detail by audience, and the map of the series.
What Is UML? A Short History, the 14 Diagrams of UML 2.5.1 and Which Ones You Will Actually Use
UML is the OMG's standard modeling language for putting the model scattered through your code into a notation everyone reads the same way; its current version is UML 2.5.1 from 2017, which defines 14 diagrams, 7 structure and 7 behavior. A short history from the method wars, the diagrams people actually use, the difference between model and diagram, and Fowler's sketch, blueprint and programming language modes.
Anti-Patterns: God Object, Service Locator, Singleton Abuse, Anemic Domain Model and Patternitis
An anti-pattern is a solution that looks reasonable at first but produces the same trouble again and again, and recognizing one means knowing the refactoring that moves it to a better structure. The dependency Service Locator hides from ValidateOnBuild, a God Object measured with CA1506, singleton tests that break depending on order, an anemic model whose rule gets bypassed, Golden Hammer, Lava Flow, Poltergeist and patternitis.
Visitor Pattern: Double Dispatch, ExpressionVisitor and a Comparison with Pattern Matching
Visitor doubles C#'s one-dimensional virtual dispatch through Accept and Visit calls, letting you add new operations to a stable type hierarchy without touching the elements; the price is that a new type breaks every visitor. The static-type trap of overload resolution, the expression problem, ExpressionVisitor and Roslyn's CSharpSyntaxWalker, and a comparison with switch expressions that have no exhaustiveness check.
Template Method Pattern: Algorithm Skeletons, Hooks and the Delegate-Based Alternative
Template Method fixes an algorithm's skeleton in a non-overridable base class method and leaves the varying steps to abstract methods or empty hooks. The hook silently skipped by a forgotten override (CS0114), Stream.CopyTo and BackgroundService.ExecuteAsync whose behavior changed in .NET 10, the virtual-call-in-constructor trap (CA2214), and building the same flow with delegates through composition.
Strategy Pattern in Depth: Keyed Services, IEnumerable<IStrategy> and Func for Runtime Selection
Writing a strategy is easy; choosing the right one at runtime is the hard part: keyed services select by a single key, IEnumerable<IStrategy> with CanHandle looks at several properties of the object, and Dictionary<string, Func<>> selects with the least ceremony when formulas have no dependencies. How registration order silently changes prices, why keyed registrations don't show up in GetServices, and IComparer and StringComparer as strategies in the BCL.
Observer Pattern in Depth: event, IObservable<T>, IChangeToken and Domain Events
Observer means that the objects depending on an object are notified when its state changes; in C# you meet it as event, in the BCL as IObservable<T>/IObserver<T>, and in ASP.NET Core as IChangeToken and IOptionsMonitor. Starting from a phantom confirmation email sent by an event raised before the save, we study the OnNext/OnError/OnCompleted contract, Rx.NET operators, single-use change tokens and domain events dispatched in isolation after the save, all with real output.
Memento Pattern: Taking Snapshots, Restoring and Keeping Encapsulation
Memento lets you take an object's internal state out without breaking encapsulation and restore it later; in C# the cleanest way is a private nested record plus a narrow interface shown to the caretaker. With real output we look at the shallow-copy trap of the with expression, a capacity-limited undo in the checkout wizard, Utf8JsonReader's JsonReaderState, undo with Command, versioning snapshots written to JSON, and the memory difference immutable state makes.