Restructuring to a Vertical Slice Architecture

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Tried out VSA earlier this year after using Onion and I never want to go back πŸš€

πŸ‘οΈŽ︎ 18 πŸ‘€οΈŽ︎ u/In8-code πŸ“…οΈŽ︎ Jul 28 2021 πŸ—«︎ replies

Love it. Having all aspects of a feature in one place, rather than scattered across multiple assemblies. Which then have their own tests at different levels scattered across multiple test assemblies. Would make it so much simpler to work on. Like you say, there is little point in grouping things by layer when it's features you work on rather than layers.

One thing that made be pause though is removing the abstraction of the repository level. Say you added some flag to your Order entity. Like a soft delete or something. You then want (almost) all queries to only return all orders that are not soft deleted. With a repository you would change the repository method and have all calls to it display the newly desired behaviour. You can also find all references to that method and easily see where it is used. What would you do with VSA? Manually comb through the code for every instance of fetching Orders and update each one? Or is there something more elegant that I'm missing?

πŸ‘οΈŽ︎ 7 πŸ‘€οΈŽ︎ u/Clearandblue πŸ“…οΈŽ︎ Jul 28 2021 πŸ—«︎ replies

This coin has 2 sides, as always.

From one side - yes, instead of creating all those interfaces and implementations for all a dependences for every action, distributed across several projects (or even nugets) this approach is much more readable and easily supported.

From other side, when logic in handlers becomes more complicated than CRUD ... he haven't shown the way he is doing the tests. And here can be the real problem with this approach.

πŸ‘οΈŽ︎ 6 πŸ‘€οΈŽ︎ u/euglzihrzivxfxoz πŸ“…οΈŽ︎ Jul 28 2021 πŸ—«︎ replies

The problem with videos/articles like these is that they assume one size fits all. There's rarely only one right way to do things, architecture is highly dependent on project requirements.

πŸ‘οΈŽ︎ 10 πŸ‘€οΈŽ︎ u/letsjustbefriendz πŸ“…οΈŽ︎ Jul 28 2021 πŸ—«︎ replies

Looks nice for small things when we can separate use cases.

But when it comes to larger systems and complicated business logic I am afraid that it may quickly become a nightmare.

πŸ‘οΈŽ︎ 4 πŸ‘€οΈŽ︎ u/Quanramiro πŸ“…οΈŽ︎ Jul 29 2021 πŸ—«︎ replies

It's pedantic, but also accurate, you should have used "Restructuring" instead of "Refactoring" for your title.

Other than that, interesting stuff!

πŸ‘οΈŽ︎ 4 πŸ‘€οΈŽ︎ u/Finickyflame πŸ“…οΈŽ︎ Jul 28 2021 πŸ—«︎ replies

Back in the day we would have a GetMyOrders.aspx for the UI and a GetMyOrders.aspx.cs for the code behind it. I guess we have come full circle.

πŸ‘οΈŽ︎ 2 πŸ‘€οΈŽ︎ u/mbhoek πŸ“…οΈŽ︎ Jul 29 2021 πŸ—«︎ replies

By the way, the thing not related to the approach itself, but it makes it not so clean. In many cases writing queries directly to the database is not good at all. It's better to abstract the calls with some repositories with business-related calls and hide db connect from feature developer.

Why? Because if all the db queries will be in one repository (even better in separate nuget) it can be controlled/reviewed by the team, which will ensure, that all the queries are covered by right indexes. Also this team can do the speed tests of this repo and refactor/limit code, make some caching, db separations ... etc. And all this not touching other team components. For high-load projects it can be really critical. If all db calls are spread between 1000 features in code files - it will be fully impossible.

πŸ‘οΈŽ︎ 2 πŸ‘€οΈŽ︎ u/euglzihrzivxfxoz πŸ“…οΈŽ︎ Jul 29 2021 πŸ—«︎ replies

What I can’t get to work properly is to have the razor files on a library when using MVC. That’s my main issue with VSA currently.

πŸ‘οΈŽ︎ 1 πŸ‘€οΈŽ︎ u/MisterFor πŸ“…οΈŽ︎ Jul 29 2021 πŸ—«︎ replies
Captions
hey everybody it's derek homer from codepinion.com what does a vertical slice architecture look like in code and how does it compare to a clean architecture i'm going to refactor a sample application to use a vertical slice architecture and provide some insights along the way if you're new to my channel i post videos on software architecture and design so if you're in those topics make sure to subscribe if you find this video helpful at any point make sure to give it a thumbs up and leave a comment so the key point about clean architecture or layered architecture or anything similar to it is the direction of dependencies so you can see here has the dependencies are pointing inwards that means at the very core what is called entities here or you may think this of your actual core domain where your business logic lives it does not have any dependencies on the outside of that you have use cases this is where you may have some application logic and it's pointing to your core to your entities and so forth as you go out it doesn't necessarily need to be these exact um layers if you will but this is the general concept of your dependencies pointing inward so if we were to take these similar concepts and display it a little bit differently is we have the web ui an infrastructure an application a domain when we're talking about vertical slices really what we're talking about is instead of having those layers really what we're thinking about is take the individual pieces from each one of those layers and segregate them to a direct to a feature so we're thinking vertically not horizontally meaning we're not thinking about all these different layers in the direction of dependencies we're thinking about what are all the things that belong to a particular feature and get really narrow on what that feature is and contain all those things within that within that feature within that vertical slice so a different way of looking at that vertical slice is we're going to have a top layer that ultimately really isn't anything that we own it's going to be something like our web host so in the example that i'm using this is going to be asp.net core it's not going to contain any controllers or entry points into our actual application but it's going to be simply asp.net core it's middleware but things like mvc eraser pages etc that's not going to live in that particular project we're just using the web host for being a web host the features is what contains everything that we care about that's going to be our application logic and then if we actually have something relevant to our domain that we want to share across features we can do that now again this is very narrow you'll see that there's no infrastructure there's no separate projects related to any of that because our features are very narrow and we're going to limit them in scope of what relates to each other and what's using a particular domain we're not so concerned about abstractions we're not so concerned about abstracting things like our database because it we're going to use our implementation say in this case we're using entity framework in my example we don't need to abstract entity framework we're just going to use it the reason being is because if we have something that we're going to depend on like entity framework that is testable to create another abstraction on top of that is just more work for very little benefit the reason being is because if you need to change implementation from entity framework to something else you're just doing at a feature level you're not doing it at a later level so one last thing before i jump into code and if you ever watch my videos on loosely coupled monolith this will make a lot of sense but i'll jump back to this at the end of the video which is you can see at the top here i have a web host which i showed earlier but i also have something separate with a message processor i'm not showing this in my videos but it's just to illustrate that these are different ways to invoke features so maybe our message processor is just using a messaging library that's talking to a message broker or a queue and it's invoking features and we have certain features that maybe are sharing a particular domain model maybe we have a separate free feature here that's not even using the domain model at all it's just using particular data model but this is again take keeping this in mind as i'm going through explaining uh the rest of my kind of refactoring here all the code i'm showing is available to my developer level members if you're interested in joining my channel go to my channel click the join button for more info so the very first thing i'm going to do is i'm going to merge infrastructure and application core the reason being again is that infrastructure contains implementation for things like our database contacts services and logging and because i want to keep these things all things together i'm not so concerned about having them as separate layers for direction and dependencies i'm actually going to merge them together so let's kind of move stuff over here so i'm going to move the data folder over i'm going to move identity over logging and then services since there's already a folder for that we'll move our email sender just to that particular folder and then we're just going to completely remove the infrastructure project all right so now we're basically down just to application core and our web so i'm in the web project now and we can see we have controllers and we also interestingly have this features folder which has my orders and this is actually using mediator so we're going to move some of this around here i don't want the web project to be have any necessarily any logic in it i actually want to move all of it to the application core including the controllers so let's do that all right so what i'm going to do is in the application core i'm going to create another directory called features inside of this i'm going to create a subfolder called orders and the thing i'm going to refactor here is actually getting the list of your orders so i'm going to create a new class called get my orders because that's what the actual query was called beneath it so what i want to do here is i actually just want this particular route so i'm actually going to copy the entire class let's move it over to get my orders i'm going to paste this in here and then get rid of the detail route because we don't really particularly care about that we'll just leave this and we'll add all our using statements and now we can see that we are missing some types here get my errors so let's move that order uh that type over that class because it also exists in the web project so get my orders that's where this type existed let's completely cut this out go back over here and we're going to paste it here we're going to call this the get my orders query and look at that we're actually let's rename get my orders controller rename that as well and then this one was you don't want to use the template here so we'll use order my orders i believe is the name all right so now we have this view model that we need to move over all right so let's do that so order view model that belongs order view model so i'm going to move that all the way up to our features folder and this one's actually this view model is used actually in a couple different places so i'm actually going to move the order items to because it's used let's keep going up we'll add it here so add our using statements now the thing here is that generally i don't actually recommend for the most part ever returning a list um from a particular view model especially if you're going to use this result as a result of a web api where you're just going to be serializing it in this case it's actually being used in a razer view but i actually don't recommend returning a list the reason being is because if you do want to add something to that you're kind of botched you can't really do it you're going to have to return the type so i usually like creating a root type that'll have the list in so let's add that so let's create one so get my orders view model and then what i'm going to do is i'm just going to put this and we're going to change this all around so that the request is actually the get orders view model and then we will pass the orders into here so again i'm doing this simply because if you want to add something you can do it to this root level but if you're just returning a 90 numeral level of order so you can't really have anything to the root all right so now i'm going to move the actual handler so this is empty we can delete this and then let's move the handler over so i'm literally going to cut and paste this entire thing and go back to my orders i'm going to add our handler get my handler and then we can see now that it's our query and our query now returns not the innumerable rather it returns the view model so we'll replace that signature here uh let's place the signature here and then we'll add our references all right so now only thing we gotta change is now we got to return our new get my viewmodel and then i can just specify the orders in this list oops typos all right so that's fixed so now all we really have to do is move over our view alright so let's go get that view my orders paste it into our folder and actually i'm going to rename this just so it aligns i'll call it get my orders and then i'm going to change this to reference that path you could do this with conventions but for simplicity's sake new features orders get my orders.html and now we have moved basically everything order we have our controller we have our viewmodel we have the query and we now have the handler to process that particular order so everything will work just as it is before except now everything's together in the same location you can do this as separate files if you don't prefer if you prefer having like kind of a class per file for your query and your handler i prefer everything having in the same file because i'm just in here if i know i'm doing something with my get my orders i know i'm going into one file and maybe i guess including the razer view so the last thing i want to touch on on at least moving this and consolidating this into one central place is dealing with this actual handler and it's doing a couple things that i just have no interest in one is it's using a repository to get out the list of orders the thing with this is that this repository although it's using a specification with a specification pattern to limit base by user to get the right orders it's returning the entire order set when the reality of it is if you actually look at what's actually being used in this view it's not using the entire order view model it's using really just like a summary so if i look at the actual view here when we're iterating over everything we're not showing any of the items we're showing kind of a the order number the date a total a status that's it however if you actually look at the code the thing we have to build up includes the items the pictures the shipping address none of this is relevant for the actual view so this is often the problem i see with using a repository especially for queries in the query side is i would much rather use the database directly instead of using repository and get the data i need to project that to a view model that is relevant for the view whether this be a razor page whether you're serializing this with a web api it's still the same thing way back when if you ever wrote sql directly most people always said don't write a select star this is writing a select star this is it's never about it's not even about pre-optimization is that you're using something to get a whole bunch of data back that you don't actually need get to the simplest path so just i'm going to change this so we're going to create a view model specifically that's a summary for the orders rather than using this shared order view model so what that looks like is i'll just save you again some hassles we're going to get rid of the order repository we're going to add in our catalog db context we're going to reference it directly getting rid of our repository add our using statement so now i'm using the database directly getting orders including our items so we can count our sum of total we're doing our where which is again what a specification is and we're doing a select which is basically a projection on that order summary and returning it so again the simplest path to get to the data you need the reason why i don't particularly need the repository here and i generally don't use repositories for again for queries is to get the after the data that you need the thing even with the specification is that it's an abstraction over everything within any framework so you can have a centralized place to say this is how i want to filter out this particular data the thing is is that specification was a nuget package a part of this project and i can understand having an abstraction so that you own the abstraction but the problem is you don't own the abstraction it's an abstraction on top of an extraction of link in entity framework so get rid of the abstraction entirely why do i prefer concrete implementations rather than abstractions because this is so narrow if you again i have large projects that do exactly this if you need to change for example that you're no longer going to use entity framework then change this particular handler you can do that a handler at a time you do not need some abstraction over top of another abstraction that's going to be used in multiple places and have some high degree of coupling that if you change that thing it changes everywhere again i would rather have things centralized in or i should say consolidated to individual places so that you can define what the dependencies are per given feature so to visually summarize in code now i have one file called get my orders which is in the application core under feature orders it contains my controller my view model any sub view models are part of that the actual mediator query and its relevant handler it's and then the razer view is living directly aside of it if i need to go into one place i'm not jumping through projects jumping through folders like i was before i don't have this feature folder and this view models folder with a view in a separate place then it going to the application core and the infrastructure i'm not dealing with those abstractions i have a centralized place of defining its dependencies i'm using complicated implementations where appropriate like any framework like i feel here it's just a central place where this feature is organized everything is here so the last thing i want to touch on is i was showing this slide at the very beginning saying i was going to loot to a little bit more and you start thinking of okay well if i have feature explosion where does it end and it really does come about boundaries so in my loosely coupled monolith video drop a link in the description is that you're really breaking things up by feature and what they actually commonly share that could be in this particular case say there's two features that's not realistic for this diagram but let's say you have a dozen features that particularly relate to a particular domain model that you have and it has its own actual database then you have some other feature set that maybe doesn't have maybe it's very crud in nature you don't really want to have a domain model you're just having more transaction scripts and you just have a data model and it has its own database that it interacts with so again this is the concept i have of the elusive couple monolith where we have particular boundaries that don't communicate directly with other boundaries they're using messaging to do so and then you have these top level entry points like a web host which is asp.net core or whatever the case may be and you have a message processor that's communicating with your message broker to then push those messages to the relevant features if i were continuing refactoring i'd be doing the exact same thing there's a details page i can order details page i'd be doing the same thing i'd be moving the controller the query the view models the handler and realizing what is appropriate for that particular handler what it actually needs to do does it need a repository does it not need a repository would i rather simplify it and then just use the actual database directly like entity framework in this particular case and get the data out directly that i need maybe it was a particular command where i actually need the repository needs a relative word here to actually get out a particular data model maybe i actually have a domain model that a few different features are sharing that's fine it's not that a feature can't share other concerns with other things it's just being aware of what you're coupling to so you're coupling in within an individual feature and defining what those dependencies are so again thinking more narrow in future in organizing code that way rather than organizing and thinking about layers if you found this video helpful give it a thumbs up if you have any thoughts or questions make sure to leave a comment and please subscribe for more videos on software architecture and design thanks you
Info
Channel: CodeOpinion
Views: 8,558
Rating: undefined out of 5
Keywords: vertical slice architecture, software architecture, software design, cqrs, event sourcing, design patterns, software architect, .net, .net core, asp.net, asp.net core, soa, microservices, event driven architecture, service bus, mass transit, nservicebus, messaging patterns, service oriented architecture, microservice architecture, domain-driven design, enterprise service bus, clean architecture, feature slices, vertical feature slice, Vertical slice archetecture
Id: cVVMbuKmNes
Channel Id: undefined
Length: 17min 50sec (1070 seconds)
Published: Wed Jul 28 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.