diff --git a/README.md b/README.md index a74af63..e4a16ef 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ When adding or changing a feature in an application in n-tire architecture, we a With this approach, each of our vertical slices can decide for itself how to best fulfill the request. New features only add code, we're not changing shared code and worrying about side effects. -![](./assets/Vertical-Slice-Architecture.jpg) +![](./assets/vertical-slice-architecture.png) Instead of grouping related action methods in one controller, as found in traditional ASP.net controllers, I used the [REPR pattern](https://deviq.com/design-patterns/repr-design-pattern). Each action gets its own small endpoint, consisting of a route, the action, and an `IMediator` instance (see [MediatR](https://github.com/jbogard/MediatR)). The request is passed to the `IMediator` instance, routed through a [`Mediatr pipeline`](https://lostechies.com/jimmybogard/2014/09/09/tackling-cross-cutting-concerns-with-a-mediator-pipeline/) where custom [middleware](https://github.com/jbogard/MediatR/wiki/Behaviors) can log, validate and intercept requests. The request is then handled by a request specific `IRequestHandler` which performs business logic before returning the result. diff --git a/assets/Vertical-Slice-Architecture.jpg b/assets/Vertical-Slice-Architecture.jpg deleted file mode 100644 index fff1aec..0000000 Binary files a/assets/Vertical-Slice-Architecture.jpg and /dev/null differ diff --git a/assets/vertical-slice-architecture.excalidraw b/assets/vertical-slice-architecture.excalidraw new file mode 100644 index 0000000..f395eb0 --- /dev/null +++ b/assets/vertical-slice-architecture.excalidraw @@ -0,0 +1,431 @@ +{ + "type": "excalidraw", + "version": 2, + "source": "https://excalidraw.com", + "elements": [ + { + "id": "80OGzNPG6Gk8NAvbV3XaF", + "type": "rectangle", + "x": 648, + "y": 187, + "width": 538, + "height": 62, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "#5dade2", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 70, + "groupIds": [], + "roundness": { + "type": 3 + }, + "seed": 246982778, + "version": 236, + "versionNonce": 69633510, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "46GLDhDwmnc8RGy3v8OK8" + } + ], + "updated": 1677440080893, + "link": null, + "locked": false + }, + { + "id": "46GLDhDwmnc8RGy3v8OK8", + "type": "text", + "x": 897.848014831543, + "y": 201.2, + "width": 38.30397033691406, + "height": 33.6, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 70, + "groupIds": [], + "roundness": null, + "seed": 2080176422, + "version": 133, + "versionNonce": 467252090, + "isDeleted": false, + "boundElements": null, + "updated": 1677440080893, + "link": null, + "locked": false, + "text": "Api", + "fontSize": 28, + "fontFamily": 1, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "80OGzNPG6Gk8NAvbV3XaF", + "originalText": "Api" + }, + { + "type": "rectangle", + "version": 339, + "versionNonce": 2033133178, + "isDeleted": false, + "id": "nZuYK7wbLObwRvpRRLHay", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 70, + "angle": 0, + "x": 648, + "y": 263, + "strokeColor": "#000000", + "backgroundColor": "#ced4da", + "width": 538, + "height": 62, + "seed": 287502970, + "groupIds": [], + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "OALII-DXtatRPgn_EkHfp" + } + ], + "updated": 1677440080893, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 242, + "versionNonce": 1368921638, + "isDeleted": false, + "id": "OALII-DXtatRPgn_EkHfp", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 70, + "angle": 0, + "x": 845.628044128418, + "y": 277.2, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 142.74391174316406, + "height": 33.6, + "seed": 1016531494, + "groupIds": [], + "roundness": null, + "boundElements": null, + "updated": 1677440080893, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "Application", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "nZuYK7wbLObwRvpRRLHay", + "originalText": "Application" + }, + { + "type": "rectangle", + "version": 271, + "versionNonce": 1144538938, + "isDeleted": false, + "id": "za_4vz64MSfPF5TWmD7wj", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 70, + "angle": 0, + "x": 650, + "y": 338, + "strokeColor": "#000000", + "backgroundColor": "#fa5252", + "width": 538, + "height": 62, + "seed": 676018342, + "groupIds": [], + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "6CqYCSOKHqhqJ8nf4b-Sv" + } + ], + "updated": 1677440080893, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 185, + "versionNonce": 1874747750, + "isDeleted": false, + "id": "6CqYCSOKHqhqJ8nf4b-Sv", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 70, + "angle": 0, + "x": 816.618049621582, + "y": 352.2, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 204.76390075683594, + "height": 33.6, + "seed": 1067355322, + "groupIds": [], + "roundness": null, + "boundElements": null, + "updated": 1677440080893, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "Infrastructure", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "za_4vz64MSfPF5TWmD7wj", + "originalText": "Infrastructure" + }, + { + "type": "rectangle", + "version": 323, + "versionNonce": 987713530, + "isDeleted": false, + "id": "t2sZwLLvmq3y2ndIbEomB", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 70, + "angle": 0, + "x": 648, + "y": 413, + "strokeColor": "#000000", + "backgroundColor": "#58ccae", + "width": 538, + "height": 62, + "seed": 1173221990, + "groupIds": [], + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "b3wdaWjaVmgHpzMD26uKD" + } + ], + "updated": 1677440080893, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 223, + "versionNonce": 1635337382, + "isDeleted": false, + "id": "b3wdaWjaVmgHpzMD26uKD", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 70, + "angle": 0, + "x": 886.5500106811523, + "y": 427.2, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 60.89997863769531, + "height": 33.6, + "seed": 1307397882, + "groupIds": [], + "roundness": null, + "boundElements": null, + "updated": 1677440080893, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "Core", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "t2sZwLLvmq3y2ndIbEomB", + "originalText": "Core" + }, + { + "id": "FQZImjU2-VUOATU9Yeyly", + "type": "rectangle", + "x": 678, + "y": 154, + "width": 48, + "height": 361, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "#f9e79f", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "groupIds": [], + "roundness": { + "type": 3 + }, + "seed": 1254939642, + "version": 185, + "versionNonce": 19349690, + "isDeleted": false, + "boundElements": [], + "updated": 1677440080893, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 224, + "versionNonce": 1119033722, + "isDeleted": false, + "id": "_Vw9EnXAyzxRDEzXCTfeL", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 743, + "y": 153.5, + "strokeColor": "#000000", + "backgroundColor": "#f9e79f", + "width": 48, + "height": 361, + "seed": 523058342, + "groupIds": [], + "roundness": { + "type": 3 + }, + "boundElements": null, + "updated": 1677440080893, + "link": null, + "locked": false + }, + { + "id": "hyJiOwPt7LFndn5R0xgfL", + "type": "text", + "x": 637.1248451774691, + "y": 317.9455509364301, + "width": 130.73194885253906, + "height": 33.6, + "angle": 4.707547804955119, + "strokeColor": "#000000", + "backgroundColor": "#f9e79f", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 70, + "groupIds": [], + "roundness": null, + "seed": 678740006, + "version": 245, + "versionNonce": 1220596518, + "isDeleted": false, + "boundElements": null, + "updated": 1677440080893, + "link": null, + "locked": false, + "text": "Feature 1", + "fontSize": 28, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Feature 1" + }, + { + "type": "text", + "version": 179, + "versionNonce": 1053153850, + "isDeleted": false, + "id": "7KOHd5JA_wVMmwXPVT1N3", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 70, + "angle": 4.7123889803846915, + "x": 695.6880416870117, + "y": 313.20000000000005, + "strokeColor": "#000000", + "backgroundColor": "#f9e79f", + "width": 143.07994079589844, + "height": 33.6, + "seed": 1387191482, + "groupIds": [], + "roundness": null, + "boundElements": null, + "updated": 1677440080893, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "Feature 2", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Feature 2" + }, + { + "id": "SuFNrbzZGowiIybusnadN", + "type": "text", + "x": 748, + "y": 96, + "width": 360.47186279296875, + "height": 33.6, + "angle": 0, + "strokeColor": "#000000", + "backgroundColor": "#f9e79f", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 70, + "groupIds": [], + "roundness": null, + "seed": 2006173690, + "version": 162, + "versionNonce": 1556577894, + "isDeleted": false, + "boundElements": null, + "updated": 1677440080893, + "link": null, + "locked": false, + "text": "Vertical Slice Architecture", + "fontSize": 28, + "fontFamily": 1, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Vertical Slice Architecture" + } + ], + "appState": { + "gridSize": null, + "viewBackgroundColor": "#ffffff" + }, + "files": {} +} \ No newline at end of file diff --git a/assets/vertical-slice-architecture.png b/assets/vertical-slice-architecture.png new file mode 100644 index 0000000..b5b30d1 Binary files /dev/null and b/assets/vertical-slice-architecture.png differ