<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mig Salazar</title>
    <description>The latest articles on DEV Community by Mig Salazar (@migsalazar_).</description>
    <link>https://dev.to/migsalazar_</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1777%2F58d02f3c-9150-4109-b406-6527214add03.gif</url>
      <title>DEV Community: Mig Salazar</title>
      <link>https://dev.to/migsalazar_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/migsalazar_"/>
    <language>en</language>
    <item>
      <title>Exploring vertical slices in dotnet core</title>
      <dc:creator>Mig Salazar</dc:creator>
      <pubDate>Fri, 05 Mar 2021 21:25:58 +0000</pubDate>
      <link>https://dev.to/htech/exploring-vertical-slices-in-dotnet-core-3mik</link>
      <guid>https://dev.to/htech/exploring-vertical-slices-in-dotnet-core-3mik</guid>
      <description>&lt;p&gt;Talking about software architecture is complex, often due to the technical aspects but largely due to the fact that there's no single answer, rarely conclusions and always depends on the context.&lt;/p&gt;

&lt;p&gt;Why it depends on the context? because it can contains a lot concerns; the strategy and business model, cost and time constraints, team capabilities and skills of each individual team-member, technologies/techniques and &lt;a href="https://en.wikipedia.org/wiki/No_Silver_Bullet" rel="noopener noreferrer"&gt;their accidental complexity&lt;/a&gt;, etc. So, our technical decisions might be biased by all of these things and will change our path toward desired state.&lt;/p&gt;

&lt;p&gt;The fact is, &lt;a href="https://en.wikipedia.org/wiki/Technical_debt" rel="noopener noreferrer"&gt;technical debt&lt;/a&gt; is inherent in software and this gives us enough reasons to look for answers and the best way to build software; even, when the reality &lt;a href="https://hennyportman.wordpress.com/2021/01/06/review-standish-group-chaos-2020-beyond-infinity/" rel="noopener noreferrer"&gt;can be quite painful&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our context
&lt;/h2&gt;

&lt;p&gt;Recently at HTech, we started a project that aims to manage the features of other software products. From a &lt;em&gt;digital product&lt;/em&gt; perspective, it could be categorized as a back-office software. For me, it represents a set of rules that acts as an interface of business rules from other products. Some considerations about our project are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The interface rules -inside of our back-office software- of a specific product, must be built by the team that knows the business rules that the specific product has. This means that one team should be able to add functionality without fear of impacting the functionality of another team.&lt;/li&gt;
&lt;li&gt;The team is variable depending on the their time and anyone could &lt;em&gt;select for development&lt;/em&gt; a jira-issue and work on it.&lt;/li&gt;
&lt;li&gt;From (1) and (2) it's likely that the work will be triggered in a bounded time, and there will be a lot of &lt;em&gt;commits&lt;/em&gt; of multiple teams at the same time. &lt;em&gt;&lt;a href="https://project-management.info/number-of-communication-channels-pmp-formula-calculator/" rel="noopener noreferrer"&gt;Communication channels complexity here?&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;The functionalities are clearly independent from others and also this tasks are generally feature oriented.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Software layers
&lt;/h1&gt;

&lt;p&gt;Generally, in the software architecture space, what we're looking for is an appropriate component segregation. The traditional way is separate the software in &lt;em&gt;layers&lt;/em&gt;, and we understand as "layer", as a segregation oriented to non-functional responsibilities; sometimes it's just in a logical and chaotic way; and at best, physical and orderly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F21ugoaw79brlrzvefm3a.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F21ugoaw79brlrzvefm3a.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The real struggle and non-trivial thing about layered architecture, is &lt;em&gt;how&lt;/em&gt; this layers interact with each other. Some of the most popular software architecture approaches, and accepted in the community, are the concentric-like architectures. For example &lt;a href="https://alistair.cockburn.us/hexagonal-architecture/" rel="noopener noreferrer"&gt;hexagonal architecture&lt;/a&gt;, &lt;a href="https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/" rel="noopener noreferrer"&gt;onion architecture&lt;/a&gt;, &lt;a href="https://www.dddcommunity.org/" rel="noopener noreferrer"&gt;domain driven design&lt;/a&gt;, &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;clean architecture&lt;/a&gt;, etcetera.&lt;/p&gt;

&lt;p&gt;Something that these approaches have in common is that all of these are trying to keep the core/business layer (a.k.a domain) independent of frameworks and isolated from the rest of the layers. My &lt;em&gt;mental representation&lt;/em&gt; of this looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm2y8m8b4yo9uiox3qqdg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm2y8m8b4yo9uiox3qqdg.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our backend, generally, we follow these approaches. Although I agree with this, it's true that for many contexts these approaches might not be suitable -or at least not from the beginning-. These architectures are usually complex by nature, they have rigid rules of &lt;a href="https://martinfowler.com/articles/injection.html" rel="noopener noreferrer"&gt;inversion of control&lt;/a&gt;, a lot of abstractions and in many cases they are unnecessary.&lt;/p&gt;

&lt;p&gt;My aim here isn't to break with the &lt;a href="https://en.wikipedia.org/wiki/Separation_of_concerns" rel="noopener noreferrer"&gt;&lt;em&gt;separation of concerns&lt;/em&gt;&lt;/a&gt; -and other benefits that these approaches bring us- but given the conditions of our context, such as the fact that the team could be constantly rotating in a bounded time, I am looking for a way to reduce the learning curve that the concentric architectures has. But, at the same time, without losing the notion of the fact that the domain must be pushed toward the center and keeping &lt;a href="https://martinfowler.com/bliki/UbiquitousLanguage.html" rel="noopener noreferrer"&gt;the ubiquitous language&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Vertical slices
&lt;/h1&gt;

&lt;p&gt;The first time I heard the "vertical-slices" term was &lt;a href="https://en.wikipedia.org/wiki/Vertical_slice" rel="noopener noreferrer"&gt;in the agile world&lt;/a&gt;; and recently, I had the opportunity to listen &lt;a href="https://www.youtube.com/watch?v=5kOzZz2vj2o" rel="noopener noreferrer"&gt;an online talk&lt;/a&gt; by Jimmy Bogard, who promotes an architecture oriented to vertical slices. Basically, his approach is in the following way:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3tet9a0m7dmic2d3xr4m.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3tet9a0m7dmic2d3xr4m.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The way he describes this is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When adding or changing a feature in an application, I'm typically touching many different "layers" in an application. I'm changing the user interface, adding fields to models, modifying validation, and so on. &lt;strong&gt;Instead of coupling across a layer, we couple vertically along a slice. Minimize coupling between slices, and maximize coupling in a slice.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, We can assume that the separation by features can be done simply by organizing the code with the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;|-- src
|   |-- OurProject.csproj
|   |-- Program.cs
|   |-- appsettings.json
|   |-- Feature1
|   |   |-- Controllers
|   |   |-- Services
|   |   |-- Models
|   |-- Feature2
|   |   |-- Controllers
|   |   |-- Services
|   |   |-- Models
|   |-- SharedLogic
|   |   |-- Services
|   |   |-- Models
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, the problem with this -and I have always seen with backend APIs- is that we tend to build a lot of &lt;a href="https://martinfowler.com/eaaCatalog/serviceLayer.html" rel="noopener noreferrer"&gt;application/domain services&lt;/a&gt;, something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6kr0u8kfurpid63n4cg3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6kr0u8kfurpid63n4cg3.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This leads us to build a kind of &lt;em&gt;main service&lt;/em&gt; that acts as an orchestrator in a typical procedural way; at other hand, this makes us lose notion of which service we need to use when adding new functionality and, even, where to physically locate that service. After a while it becomes chaotic, and indirectly causes, just to mention an example, that our domain entities become into &lt;a href="https://www.martinfowler.com/bliki/AnemicDomainModel.html" rel="noopener noreferrer"&gt;anemic domain models&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Given that, the need to have an intermediary that works as an orchestrator and avoid the use of domain and/or application services for this purpose. One way to solve this is through &lt;a href="https://refactoring.guru/design-patterns/mediator" rel="noopener noreferrer"&gt;the mediator pattern&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frefactoring.guru%2Fimages%2Fpatterns%2Fcontent%2Fmediator%2Fmediator.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frefactoring.guru%2Fimages%2Fpatterns%2Fcontent%2Fmediator%2Fmediator.png" alt="Image from refactoring.guru"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, we find &lt;a href="https://github.com/jbogard/MediatR" rel="noopener noreferrer"&gt;Mediatr&lt;/a&gt;, which is a library that implements the mediator pattern by decoupling the in-process sending of messages from handling messages. The approach, considering the organization by features, is given by the following way:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn42zockmz9bcmhnrik4e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn42zockmz9bcmhnrik4e.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Walkthrough
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Register handlers
&lt;/h3&gt;

&lt;p&gt;First of all, assuming we are using ASP.NET Core and its built-in injection dependency pattern, we need to &lt;a href="https://github.com/jbogard/MediatR/wiki#aspnet-core" rel="noopener noreferrer"&gt;configure the Mediatr dependencies&lt;/a&gt; to register our handlers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddMediatR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Startup&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Handlers
&lt;/h3&gt;

&lt;p&gt;We can think that the Handlers acts -in some way- &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;as the Use Cases of clean architecture&lt;/a&gt;. This is the entry point of our feature, from a business logic perspectie. A brief example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GetBy&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Query&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRequest&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Result&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Handler&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRequestHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// our logic here&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you notice, there are two nested classes: &lt;code&gt;Query&lt;/code&gt; and &lt;code&gt;Result&lt;/code&gt;. This two types are scoped under &lt;code&gt;GetBy&lt;/code&gt; static class in order to -logically- structure the &lt;em&gt;use case&lt;/em&gt; of our feature. That means, this isn't a generic input/output, this is only used in a specific case &lt;code&gt;GetBy&lt;/code&gt;. With this, the inputs and outputs of our API are easily to identify and gives us more evident the use of &lt;a href="https://martinfowler.com/bliki/CQRS.html" rel="noopener noreferrer"&gt;CQRS&lt;/a&gt; pattern -which by the way is &lt;a href="http://codebetter.com/gregyoung/2010/02/16/cqrs-task-based-uis-event-sourcing-agh/" rel="noopener noreferrer"&gt;more like conceptual pattern rather than archiectural pattern&lt;/a&gt;-. &lt;/p&gt;

&lt;p&gt;But, What's CQRS?. From Greg Young's &lt;a href="http://codebetter.com/gregyoung/2010/02/16/cqrs-task-based-uis-event-sourcing-agh/" rel="noopener noreferrer"&gt;post&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;CQRS is simply the creation of two objects where there was previously only one&lt;/em&gt;. The separation occurs based upon whether the methods are a command or a query (the same definition that is used by Meyer in Command and Query Separation, a command is any method that mutates state and a query is any method that returns a value).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are &lt;a href="https://github.com/BrighterCommand/Brighter" rel="noopener noreferrer"&gt;some other libraries&lt;/a&gt; to implement this, even &lt;a href="https://blogs.cuttingedge.it/steven/posts/2011/meanwhile-on-the-query-side-of-my-architecture/" rel="noopener noreferrer"&gt;from scratch&lt;/a&gt;, but at this time I'm using the same Mediatr library, implementing &lt;code&gt;IRquest&lt;/code&gt; and &lt;code&gt;IRequestHandler&lt;/code&gt; interfaces.&lt;/p&gt;

&lt;p&gt;These concerns (Querys/Commands, Handler and DTO's) can be written in the same file. However, I prefer &lt;em&gt;-but not for all cases-&lt;/em&gt; to separate each of these into single files, namespaced by &lt;code&gt;static partial class&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Refactoring our controllers
&lt;/h3&gt;

&lt;p&gt;Then, our controller methods will take the following form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// obvious code here omitted for brevity&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;OurController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IMediator&lt;/span&gt; &lt;span class="n"&gt;mediator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_mediatr&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mediator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{id}"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_mediatr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;HttpPost&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_mediatr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Take note that the goal here, is to turn the controller into a logic-agnostic component that just represent a set of input/outputs points for our api.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With this approach, each vertical slice can decide how to manage their request/response:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft6rc07osyas03akfgl9e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft6rc07osyas03akfgl9e.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pushing the domain
&lt;/h3&gt;

&lt;p&gt;Under this organization, the important thing is to take care the growth of our Handlers. Is extremely important consider the capabilities of our team, to timely detect code-smells and push logic down into domain layer and out of Handlers. There are some code-smells that I consider are very likely to occur with this approach and we must bear in mind.&lt;/p&gt;

&lt;p&gt;For example, this bad smells in logic and/or behavioral code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Large Class&lt;/li&gt;
&lt;li&gt;Long Method&lt;/li&gt;
&lt;li&gt;Duplicated Code&lt;/li&gt;
&lt;li&gt;Combinatorial Explosion&lt;/li&gt;
&lt;li&gt;Repeated Switches&lt;/li&gt;
&lt;li&gt;Feature Envy&lt;/li&gt;
&lt;li&gt;Conditional Complexity&lt;/li&gt;
&lt;li&gt;Inappropriate Intimacy&lt;/li&gt;
&lt;li&gt;Middle Man&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can use refactoring techniques that are &lt;a href="https://refactoring.com/" rel="noopener noreferrer"&gt;very well documented by Martin Fowler&lt;/a&gt;, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extract Class&lt;/li&gt;
&lt;li&gt;Extract Subclass&lt;/li&gt;
&lt;li&gt;Extract Interface&lt;/li&gt;
&lt;li&gt;Extract Method&lt;/li&gt;
&lt;li&gt;Replace Method with Method Object&lt;/li&gt;
&lt;li&gt;Move Function&lt;/li&gt;
&lt;li&gt;Compose Method&lt;/li&gt;
&lt;li&gt;Inline function&lt;/li&gt;
&lt;li&gt;Replace parameter with Query&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eventually, if we're on the right way, the approach will take on a domain-centric style.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu90xo2sfgfbqtamyvkni.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu90xo2sfgfbqtamyvkni.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, we can organize our input and output rules through pipelines around the core. This &lt;a href="https://github.com/jbogard/MediatR/wiki/Behaviors" rel="noopener noreferrer"&gt;pipelines can be implemented&lt;/a&gt; with the same Mediatr library:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzl6n0avedjime10lizdf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzl6n0avedjime10lizdf.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  So...
&lt;/h3&gt;

&lt;p&gt;This approach will helps us, in addition to orchestrating certain logic, to be able to recognize what we must push to the domain or to external layers, without worrying at the beginning of our project. And, mainly, it can guide to the team to work on independent features without conflicts and minimize problems to identify how the architecture works.&lt;/p&gt;

&lt;p&gt;My aim with this is to experiment another approach to organize our code and try to measure in order to find if this really brings productivity to the team; but, without losing sight of SOLID principles, keeping technical debt out and promoting refactoring as a daily practice.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;[WIP] The complete demo of this post &lt;a href="https://github.com/migsalazar/vertialslice-demo" rel="noopener noreferrer"&gt;can be found here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>architecture</category>
      <category>verticalslices</category>
      <category>designpatterns</category>
    </item>
  </channel>
</rss>
