From e15962d86a10ca54ee0ff4781302941e2caba9a5 Mon Sep 17 00:00:00 2001 From: Willem van den Ende Date: Mon, 14 Sep 2026 14:41:16 +0100 Subject: [PATCH 1/4] Add MIT license (Living Software LTD) --- .gitignore | 1 + LICENSE.TXT | 21 +++++++++++++++++++++ after-dto.mmd.svg | 1 + before-after-dto.mmd.svg | 1 + puppeteer.config.json | 15 +++++++++++++++ scripts/mermaid.sh | 31 +++++++++++++++++++++++++++++++ 6 files changed, 70 insertions(+) create mode 100644 LICENSE.TXT create mode 100644 after-dto.mmd.svg create mode 100644 before-after-dto.mmd.svg create mode 100644 puppeteer.config.json create mode 100755 scripts/mermaid.sh diff --git a/.gitignore b/.gitignore index 782430f..bce6fee 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ obj/ *.user # NuGet restore scratch dir (DOTNET_CLI_HOME fallout) .local/ +.idea diff --git a/LICENSE.TXT b/LICENSE.TXT new file mode 100644 index 0000000..fce4ddf --- /dev/null +++ b/LICENSE.TXT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Living Software LTD (UK) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/after-dto.mmd.svg b/after-dto.mmd.svg new file mode 100644 index 0000000..57e72c6 --- /dev/null +++ b/after-dto.mmd.svg @@ -0,0 +1 @@ +

still used by persistence layer

maps each way

maps each way

maps each way

maps each way

has many (domain relation)

has many (DTO relation)

1

1

*

*

DbContext

+SaveChangesAsync()

DbBase

+Guid id

«Web App»

WebApp

Client

+Guid id

+string name

Order

+Guid id

ClientDto

+Guid id

+string name

OrderDto

+Guid id

+ClientDto client

Mappers

+ClientDto ToClientDto(Client c)

+Client FromClientDto(ClientDto dto)

+OrderDto ToOrderDto(Order o)

+Order FromOrderDto(OrderDto dto)

\ No newline at end of file diff --git a/before-after-dto.mmd.svg b/before-after-dto.mmd.svg new file mode 100644 index 0000000..f0bc941 --- /dev/null +++ b/before-after-dto.mmd.svg @@ -0,0 +1 @@ +

uses (EF)

depends on

inherits

inherits

has many

open / close

1

*

*

1

DbContext

+SaveChangesAsync()

DbBase

+Guid id

«Web App»

WebApp

Client

+Guid id

+string name

Order

+Guid id

\ No newline at end of file diff --git a/puppeteer.config.json b/puppeteer.config.json new file mode 100644 index 0000000..1333d16 --- /dev/null +++ b/puppeteer.config.json @@ -0,0 +1,15 @@ +{ + "executablePath": "/home/willem/.cache/puppeteer/chrome/linux-152.0.7977.75/chrome-linux64/chrome", + "headless": true, + "args": [ + "--no-sandbox", + "--disable-setuid-sandbox", + "--disable-gpu", + "--disable-gpu-compositing", + "--disable-software-rasterizer", + "--disable-dev-shm-usage", + "--disable-features=VizDisplayCompositor", + "--use-gl=swiftshader", + "--disable-gpu-driver-bug-workaround" + ] +} \ No newline at end of file diff --git a/scripts/mermaid.sh b/scripts/mermaid.sh new file mode 100755 index 0000000..c537e77 --- /dev/null +++ b/scripts/mermaid.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# Render a mermaid diagram to SVG using mmdc with sandbox/GPU workarounds +# for Ubuntu 24.04+ (AppArmor restrictions). +# +# Usage: scripts/mermaid.sh input.mmd [output.svg] +# scripts/mermaid.sh input.mmd - # output to stdout + +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +CONFIG="$REPO_ROOT/puppeteer.config.json" + +if [[ $# -lt 1 ]]; then + echo "Usage: $0 [output.svg|-]" >&2 + exit 1 +fi + +INPUT="$1" +shift + +ARGS=("-i" "$INPUT" "-p" "$CONFIG") + +if [[ $# -gt 0 ]]; then + OUTPUT="$1" + shift + ARGS+=("-o" "$OUTPUT") +fi + +ARGS+=("$@") + +exec mmdc "${ARGS[@]}" \ No newline at end of file From 1188ce4e573471b99e9373ebd6d8c50234470390 Mon Sep 17 00:00:00 2001 From: Willem van den Ende Date: Mon, 14 Sep 2026 14:42:17 +0100 Subject: [PATCH 2/4] Add screenshots.md with Flameshot and Knip notes --- screenshots.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 screenshots.md diff --git a/screenshots.md b/screenshots.md new file mode 100644 index 0000000..5532507 --- /dev/null +++ b/screenshots.md @@ -0,0 +1,31 @@ +# Screenshots + +## Flameshot + +Flameshot v12.1.0 is installed at `/usr/bin/flameshot`. + +| Command | Description | +|---|---| +| `flameshot launcher` | Open the capture launcher (recommended) | +| `flameshot gui` | Start a manual (rectangular) capture | +| `flameshot screen` | Capture a single screen | +| `flameshot full` | Capture the entire desktop | +| `flameshot config` | Open the configuration dialog | + +Launches a tray icon by default for quick access. + +## Knip + +Knip is **not installed** on this machine. Install it per-project: + +```sh +npx knip # dry-run report +npx knip --fix # auto-remove unused exports +npx knip --config knip.config.ts # custom config +``` + +Fix npm cache ownership first if you hit `EACCES`: + +```sh +sudo chown -R 1000:1000 /home/willem/.npm +``` \ No newline at end of file From 804695f12dec6fce28d15fc0cea554a6c08a6e83 Mon Sep 17 00:00:00 2001 From: Willem van den Ende Date: Mon, 14 Sep 2026 14:48:11 +0100 Subject: [PATCH 3/4] Add exercise descriptions to README.md --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..acf0027 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# db-subclass-to-dto + +This is a workspace for creating two exercises. + +One exercise is about exploring a repository using prompts for a coding agent to create Mermaid and PlantUML diagrams. We're focusing on class diagrams and sequence diagrams to get an idea of what is going on. We use the starting point of the second exercise for this. + +The second exercise is factoring out domain objects, domain entities, from a structure that is previously subclass-based. So say you use a structure like active records or Entity Framework where you have an active record class and your domain class subclasses from the active record class which gives you maybe some nice things like find by an attribute. And then you can quite quickly — so these are straight-offs — you can quite quickly structure an application while it's also persisted. So you can say, "I want to have a customer, I want to have an order. And oh yes, I'm doing this for a webshop." So you have objects, relations, attributes, and you can all easily save them in your database. And this is fine when your application is small and you're just starting out. It allows you to very quickly scaffold an application. But it can become painful when your data doesn't have the right shape for it. So performance is slow. So at some point as your application grows, you probably want to be more deliberate in how you start. + +The second exercise is factoring out domain classes from a database inheritance structure. So we start with a couple of domain classes and some relations. Then we pre-deliver some classes that we already created and we demo it. As we have some domain classes, we create a mapping for writing and reading a domain class. And we make sure that running the existing tests against the fake database that we have for the exercise is really slow. The sequence diagrams that we make in the first exercise will come in handy. Because in order to do this, you do start wondering how does this web application find a client? How can we see clients? How can we create an order? And what happens once the flow through the application as we do this? You sort of need to understand this to choose the kind of mapping that you use. So we are going to reuse the analysis we did in the first exercise in the second exercise. From 5270eabcf3517e618840c3a46a85040754cb0ab0 Mon Sep 17 00:00:00 2001 From: Willem van den Ende Date: Mon, 14 Sep 2026 14:52:03 +0100 Subject: [PATCH 4/4] Add third exercise description (Roslyn extract method spike) to README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index acf0027..ce98258 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ # db-subclass-to-dto -This is a workspace for creating two exercises. +This is a workspace for creating three exercises. One exercise is about exploring a repository using prompts for a coding agent to create Mermaid and PlantUML diagrams. We're focusing on class diagrams and sequence diagrams to get an idea of what is going on. We use the starting point of the second exercise for this. The second exercise is factoring out domain objects, domain entities, from a structure that is previously subclass-based. So say you use a structure like active records or Entity Framework where you have an active record class and your domain class subclasses from the active record class which gives you maybe some nice things like find by an attribute. And then you can quite quickly — so these are straight-offs — you can quite quickly structure an application while it's also persisted. So you can say, "I want to have a customer, I want to have an order. And oh yes, I'm doing this for a webshop." So you have objects, relations, attributes, and you can all easily save them in your database. And this is fine when your application is small and you're just starting out. It allows you to very quickly scaffold an application. But it can become painful when your data doesn't have the right shape for it. So performance is slow. So at some point as your application grows, you probably want to be more deliberate in how you start. The second exercise is factoring out domain classes from a database inheritance structure. So we start with a couple of domain classes and some relations. Then we pre-deliver some classes that we already created and we demo it. As we have some domain classes, we create a mapping for writing and reading a domain class. And we make sure that running the existing tests against the fake database that we have for the exercise is really slow. The sequence diagrams that we make in the first exercise will come in handy. Because in order to do this, you do start wondering how does this web application find a client? How can we see clients? How can we create an order? And what happens once the flow through the application as we do this? You sort of need to understand this to choose the kind of mapping that you use. So we are going to reuse the analysis we did in the first exercise in the second exercise. + +The third part is a spike in creating an extract method refactoring using Roslyn, the C# static analysis tooling that comes as part of C# more or less. It's an additional NuGet download but yeah it is quite good. So this is a simple command line that allows you to specify the name of a file, the starting line and the end line and it will give you an analysis of dependencies inside the method that you need to decide which things could lend itself to extracting to a method, what the parameters could be and what the return value could be. This is work in progress so this is not something to share with participants but it is part of a flow where you first you iterate and you prompt, you create codes then maybe you extract things into a skill or you prompt for a diagram of some kind. You go, ah I often seem to make sequence diagrams. Okay, can we make something deterministic to create these sequence diagrams so it's faster and more reliable? Or in my case I don't like, well I like the extract method stuff in JetBrains IDEs but I need to do some steps before to find the parameters, extract variables, extract the methods with these variables as parameters then inline the variables again and I was wondering if I could do that more smoothly in the flow with a coding agent. That also means that going further I could do things like forbid extracted methods from having Async in all parts, but see if we can extract parts without side effects first.