Great video! We're 2 years into this kind of refactoring, can't wait to get rid of the repo layer. As abstractions go, I prefer a specification pattern because it gives a name to what can be a complex piece of logic. If your where clause has 7 or 8 different components combined, then a combination of specifications is often more readable.
You can accomplish the same thing with extension methods as well as methods on your DbContext. I might add this as an example in a future video. I almost did it in this video.
2 years sounds like a vanity project. It would take decades of additional development time to recuperate that investment. There is no reason to assume vertical slice is inherently better, it requires much better development skills in general to still ensure consistency, and refactor parts out that should be reused, otherwise you just add a lot of possibilities for new errors and more maintenance cost. But I doubt in your company there is that kind of expertise, otherwise your implementation of clean architecture might be inconvenient, but never warrant such an investment in the first place
@@FarmerSchinken thanks for your feedback. Sold my first website in 99 and been building enterprise for 20 years. I know how to migrate architecture alongside business day to day to ensure the business is where it needs to be technically in 3 and 5 years. Yep, cutting up a system from monolith to specific DDD aggregate boundaries is a long trek if taken as a background one but then you need to have vision to do that. You do you. Good luck.
Thanks for covering another important topic that can help teams improve on their delivery velocity. What I love about your videos is that they are concise and bring together the most modern consensus from the industry with approaches that really work. It’s surprising how often I find younger developers stuck in the past holding onto design patterns that hold them back. Keep it up!
That's exactly what we did with BlazorPlate SaaS boilerplate template. we used Vertical Slice architecture alongside Clean Architecture to organize code by a self-containing feature.
Awesome video as always!! Can you make a video on your approach to testing applications? I think that's an extremelly important topic that is sometimes overlooked "Do I write a stub for this? Should I test this class? Should I test this with a database? How to organize my tests?" etc
I find the principle of Vertical Slice Architecture awesome. You have included the views and viewmodels in the ApplicationCore project. If someone now wants to have a CLI program in addition to the WebApp program, then they have also referenced the views and viewmodels. My question is whether it is better to leave the views and viewmodels in the WebApp project.
same question! for me Core should contains only the domain logic, the core logic, no matter who is the consumer, it could be an http request, a rabbitmq-consumer a cli, etc.
awesome video... have a question... imagine i have an app with 10 features and 5 of them requires sending mail. do i duplicate the mail functionality in those 5 places ? doing so is bad right , because fixing a bug in mail sending logic will require fixing it in 5 places right ?
This is my preferred architecture. However, for new projects I like to start out by-layer because sometimes it takes a bit for the boundaries of features to shake out. I don't use clean architecture for this - e.g. I have no repo - because the plan is to move to vertical slices once the project accumulates some more features. I also find this superior for eventually moving to microservices. I always start with a monolith. Feature slices can turn into microservices down the road.
I undersand the advantages of this approach but can you please explain to me how do you avoid violating the DRY principle in this kind of architecture? Or is that even relevant, I mean do you just don't bother with DRY at all?
You can have shared concerns between features. It's not about 100% segregation between features. But focusing and organizing code by features and limiting the dependencies to what each feature set needs. Focus on vertical of a slice rather than horizontal of technical concerns.
The application core is a kind of service layer rigth?A client of domain model? The second-In generall the repository shall be used in write model rathen then in query side when it is advisable to use sql or dapper?Thanks!
3 года назад+2
Thanks for another great video! What are your thoughts about the combination of event sourcing and vertical slices? I haven't been able to find many examples of this. Do you still query the related events directly from the db? Or would a repository make sense in this situation? Do you colocate the read model in the slice as well? Including the logic to build it up from events / storing snapshots? (sorry a lot of questions here)
You can create read models that live in another service that are composing from various services. ES can be used in various situations, regardless of clean or vertical slices. It's more about boundaries of the the capabilities of the service.
@CodeOpinion I can't agree on removing repositories. If Data access changes I have repository interfaces remain unchanged and instead of changing data access in all features/use-cases I only change repository methods Implementation. If I am relying on specs to formulate query those are gonna be 4 or 5 methods per repository, Or am I missing something ?
Heya, trying this out in a side project. Out of interest, how does feature -> feature communication/dependency usually work? If a feature is explicitly dependent on another feature (e.g. feature X is a bulk orchestration of feature Y) would you have it rely on the feature explicitly? And if calling other features is more so a side effect would it be best to trigger/ orchestrate this via an event to avoid coupling? (For example, on an application level feature A should trigger feature B, but they should not be aware of one another). Just trying to wrap my head around this segment of vertical slice and don't see much info regarding it online; hope my question makes sense lol. Cheers
@@CodeOpinion In hindsight orchestration was an overloaded word - it's pretty simple and doesn't require that kind of finesse IMO. I guess if I was to reword my question it would be the following: Is it okay to have one feature depend upon another if it's a tightly coupled action? For example if I had a DeleteInvoice feature that took in an invoice ID and a DeleteInvoices (bulk) feature that took in a collection of invoice IDs, would it be recommended for DeleteInvoices to depend upon DeleteInvoice?
@@alucinorbeats, great question, tested the structure a little and also bumped into feature-to-feature coupling/dependencies. Did you stick with vertical-slice/ by-feature design?
Hi, Thanks for useful video. Could we use vertical slice in a simple crud based application? Or, just like the cqrs approach, we should only use them in task-based application!
You could for both CRUD and task based. Reality for me is that applications will have a mixture of both CRUD for things that are on the edge and more referential and tasks for more core parts of your domain.
Thanks for binging this up. I totally wanted to cover the "cons" in this video and I totally forgot while I was recording it. But the cons IMO are: 1) It's easy to forget that you can have shared concerns between features (eg domain model, validation, etc) 2) Directly related to #1 is ending up with a lot of handlers that are transaction scripts on the command side. Meaning you're changing data directly in handlers and adding more and more logic. As time goes on and complexity adds up. You need to be aware to refactor and move to a proper domain model and invoke it from your handlers. 3) It's a mindset shift for a lot of people. The majority of tooling scaffolds by technical concern. Almost everyone is thought about separating by technical concerns. You're still doing that, but narrowing the focus. It's a mindset change for sure.
@@CodeOpinion Thank you for detailed reply. I am actually in the middle of a migration from a traditional onion architecture to a vertical slice architecture and I was wondering what exactly are the tradeoffs. So far, the only concerns I was able to find is the fact that you absolutely need to define conventions and the fact that we are using dapper to communicate with several data stores so getting rid of the repository layer feels a bit... dirty. With entity framework i totally agree that it doesn't make much sense to add yet another abstraction layer.
@@paulomartins7969, as complexity of the system increase, I actually think (and based on the cons that Derik me sounded above) the vertical slice architecture works tend to be refactored towards onion architecture and not the other way around. Curious to know what you think.
Great content as always Derek! Seeing your implementation and the direct use of the DBContext, I now understand your point on removing the repository abstraction (when it's not necessary). I was looking the other day at how to cleanly combine the use of the Dapper and EFCore, but with vertical slices, it's no longer a concern as every feature can use the ORM that fits its needs directly. I do hope you'll make a video on where you actually find it beneficial (the repository pattern that is).
Just a regular keyboard, nothing special. I know it got picked up by my mic a bit in some spots more than others. Need to pay attention to that more next time.
How do you plan to run tests now that your query handler operates directly on the database? Isn’t the purpose of the injected repository that it can be replaced (e.g., in tests with an in-memory repository)?
I love the feature approach. This should always be the way, but still loads of projects have that vertical jump F12 key press for their lifes. Regards to the abstractions, instead of having a Infrastructure project maybe make sense to call Infrastructure folder inside the ApplicationCore. Data Accesses, Logging, Proxies they should be exposed by their API using interfaces. If the handlers need some IO from the outside we need to inject them in a specific handler for example, and specially for testing we should work with abstractions so at that level we don't think too much about the technicals and also is easier to test it and mock it. What do you think about that subject? Regarding people creating IWhateverDbContext and etc to abstract the actual context to make possible to test each specific handler? so that way we should keep the Infrastructure project and keep the implementations there... but thats crap now that things are far away again. mixed feelings.
I generally don't concern myself with abstracting Entity Framework within a logical boundary. This is because coupling is limited to the vertical slice which is very narrow to begin with. This means that coupling is limited. Another way to put it, is I don't create large DbContext's but rather small ones that own a particular schema (tables). Abstracting the DbContext ends up having little value and just another layer of indirection. Check out a couple videos that might help get a better idea: Cost of Indirection: ruclips.net/video/DNjDZ0E6GUs/видео.html Should you use a Repository: ruclips.net/video/01lygxvbao4/видео.html
Hi Derek, what a great video. Congrats🎯 I have some questions and I'm sure you can give your opinion. How can coexist DDD practices and Vertical Slice architecture? Let me explain my use case: I have my clear architecture application, and I have a controller for my orders, an application service to manage my application logic (e.g save in database, publish events), my domain service that is responsible for domain validations and business rules (e.g you can't place an order if the product is only available for some kind of customer segment) and finally my domain model. Restructuring this to a vertical slice, I can imagine 2 projects, OrdersAPI (which have my features) and OrdersDomain (which have my domain models and services). This could be a good decision? I'm asking because I can see this domain service living in the Feature folder, but should I move it? Or leave it together with my domain models? Or I'm thinking a lot about clean architecture and what makes sense is to put all things together? Can you please share your opinion? Thank you, cheers 🍺
There are different ways you can approach and think about this. You can apply clean to a "set" of features if you want to have that technical separation between infrastructure, application and domain, just as you do now. You can share concerns (eg, data access, data models, domain models) between feature slices. The biggest thing with thinking about vertical slices is putting the concept of a feature at the forefront and not technical concerns. This other video might help a bit where I talk about various concerns and how transaction scripts may be simple in some places, while others need more control over complexity. ruclips.net/video/PrJIMTZsbDw/видео.html
Hey Derek! In a front-end application which is just calling endpoints and doing it's things and does not have actual business logic(because it is implemented on the back-end side). So, My question is what will be the entities in this case?
Not entirely sure what you mean. Your client would be just calling your HTTP API and using the results. Check out this video, let me know if it helps: ruclips.net/video/6XO6vSiioWE/видео.html
@@CodeOpinion It did help. Let me make my question clear. So, let's say I have a Mobile app and I want to architect it using clean architecture. So, in that case what will be my entities, if I'm just calling endpoints from the app and doing things based off that result?
Say two or more features need as a part of their handlers to check if a user exists, among other things. Would you isolate this operation into a reusable function in something like a repository class or you would repeat the same code in all the features? And last but not least, thanks for all your videos, amazing content.
Yes, for sure you can share some reusable functions between handlers. The point isn't to make them 100% independent but rather think vertically and organize that way rather that horizontally. Once you do so, even if you do share some reusable function, it likely would be limited to a few handlers, which limits coupling.
I am quite curious by this, but I have a question with Vertical Slice architecture and EventSourcing. Say you 2 have separate features (Delete Line Item) (Complete Order) that add a new event on the Aggregate/Stream. For both cases you need to load the stream from your event store and replay the events to build the aggregate. Where does the loading from event store and replaying the events code live? That seems to be it has to be shared across all features that need to manipulate a given Stream
Yes, a shared class that both use. Some type of BasketRepository. Vertical slices aren't about NO sharing, but grouping the functionality together, deciding individually per feature and set which dependencies you take.
Generally I'm creating a pipeline for a request. Each individual filter can be tested independently. Check out this video on creating a pipeline ruclips.net/video/msXtN15qXOE/видео.html
Is it ok if I use "GetMyOrders" as method? because I think a class should be treated as a noun not a verb, I like arquitecture and I like these things lol
When I saw the repo in for the query feature I was screaming then you refactored it and I had a smile upon my face 😁 Quick question: for the orders query feature what is the value of using MediatR? Why not get rid of it like the repo?
Good question. The video on Pipes & Filters (ruclips.net/video/msXtN15qXOE/видео.html) is really a primary driver for using a dispatcher like MediatR because it supports creating a pipeline (behaviors). If you're not using a pipeline, the value diminishes a bit IMO. Arguably you could still have your code separate from the controller and just inject the class (or interface) of your "handler" rather than dispatching with MediatR. If you want to use a pipeline, then MediatR (or similar) makes a lot of sense.
Hi Derek. Thanks for all your content. Very inspiring. I am not sure I understand this entirely. In your looslyCoupledMonolith you had a project for abstractions for communication between bounded contexts. How would that work in a scenario like this? What if some other feature needs to get a list of my orders?
If you're in a monolith, and you want to use in-process communication between boundaries then just expose an interface/delegate in the contract/abstractions project for fetching/returning that data. Just realize you're more tightly coupled doing so.
Cool video. I noticed that you mainly use GUIDs instead of Sequential Ids for your entities. Did you ever have problems with Fragmentation when using GUIDs for your projects?
@@CodeOpinion Yes I mean at database level. I just read a bit about this topic and see the advantages of Guids, but some posts about fragmentation really made me wonder if I should use them.
With regards to the repository layer, are you suggesting that omitting the repository is good for the read model/querying model (I agree with this especially after your explanation). However the repository layer is still essential for the write model as this is an anti corruption layer (ACL) and will protect our domain layer (e.g. we don't want to load aggregate root and not its children directly via db context)?
I understand the motivation to return focused view models for list operations in the context of a web application that selectively uses a subset of the resource’s properties, but in the case of API-first, REST-based applications, that are designed to return the full representation of the entity in the list queries, would you still choose to remove the repository and specifications? Or is that perhaps the wrong question? Put another way, would you ever design a REST API to return the same model for the elements of a list as the query for a single element of the same resource? An example off the top of my head is Stripe’s API.
A resource can be whatever you want. Don't constrain yourself to the notion of a resource is an entity and CRUD built around it. It does not need to be an Entity. I created a video on this, if you haven't watched already. ruclips.net/video/2gOOstEI4vU/видео.html
How do you deal with identity in this case? Do you have some sort of IdentityService which abstracts away the UserManager and RoleManager? Or do you just use those Identity classes directly in your handlers, just like you use EF Core directly? Also, if you have an entity that can "belong" to a user (e.g. a booking), would you use the `IdentityUser` derived `ApplicationUser` in the `Booking` class as a User property? Or just have a string property for their ID? Cheers
It really depends how you want to handle authorization. I generally attach some form of identity to messages (commands/queries/events). To get the general gist, even if you aren't using NServiceBus, check out this post: docs.particular.net/samples/username-header/
@@CodeOpinion That makes sense. What about handling changes to Identity? Like a user updates their display name, or an admin updates the roles/permissions of a user? Is there a separate "slice" to deal with users, roles, etc?
Thanks for the interesting video, Derek! What would be the difference between this and transaction scripts? The approach you show works well IMO because you still have a set of well designed abstractions (view models, controllers, a domain layer for the rules of changing state, etc.) that you can use as and when you need to. I’ve seen codebases I’d describe as set of vertical procedural Python scripts (cannot be called OO or FP really) with very little abstractions, attached to the web host / event bus. You either need physical layers or lot of discipline to impose order IMO when you remove those walls
I didn't show anything in this video, but if you had a command handler that did everything in the handler directly. Meaning it was interacting with the data model directly. This can work as you start out if you don't understand the model that well or where the transaction boundaries are. Transaction scripts can get out of hand in a hurry and before you know it you're changing data in various handlers and have no central model. This is when you can start introducing aggregates and centralizing logic around a transaction boundary. Check out this video if you haven't about Aggregate Design: ruclips.net/video/64ngP-aUYPc/видео.html
but isn't it data driven instead of behaviour driven if you're grouping by domain model names ? I remember you told behaviour > data in one of your videos. I mean you name the folder Orders, but it doesn't tell anything about the system's purpose, why don't we name our folders based on the feature's name ? (fi.: DriveCar and BuyCar instead of Cars folder)
Man, your videos are gold. I have said this in previous videos but it is very hard to find quality videos on software architecture but yours are good and to the point. On the other hand, I know you won't like this "dumb" question but what do you think works better Onion or Vertical architecture?. By the way, I would like to do a request: What do you think about creating a series of videos where you expose an imaginary client request (For example, creating a backend for an eshop) and building a decoupled monolith following for example vertical architecture? I am not talking about adding the real business logic but things like how to split features from requirements, how to build the folder structure for each feature, etc. I mean, the things about architecture that no one talks about or if they do they are really generalistic :)
I prefer vertical because it allows me to focus on capabilities and organize them by commands, queries, and events. Thinking vertically also allows for more distinct logical service boundaries. As for the the request, I'll think about how I can work that out. The difficulty is using a simple enough example that most can understand without actually understanding the domain. Anything complex has a lot of value explaining but only if you already are familiar with the domain. It's a tough situation when creating examples.
@@CodeOpinion Yes, I agree with that. It is difficult to find a good project to showcase infra structure if the learner doesn't understand the domain. Let's hope you find something that could fit :)
If you need an abstraction, create an abstraction if it serves you value. However not everything needs a mock for testing. ruclips.net/video/2oRofOH2NT4/видео.html
About 12:20 Also, now that the "file" keyword exists in C#, it could be useful when you need to create a new model for a specific feature, like here in with MyOrdersViewModel. Having to find a new name would not be a problem anymore. Maybe more responses with different columns would make sense to only be named "OderResponse" or so
@@CodeOpinion and what kind of tests you do the most? As you get rid of interfaces/abstractions I guess you're forced to have more integration tests than unit tests, right?
Hi Derek, In this video, you said we don't need to abstract EF, changing our persistence mechanism is fine because we just replace it in our feature level, But what about testing? It is hard testing with a direct dependency. Although EF core has in-momroy provider for unit testing, but what about using other providers like MongoDriver? So we have to use an abstraction here!!
@@CodeOpinion How do you unit test it if we don't use entity framework? How could we test without abstraction? Something like this we have to. What is your opinion?
from one extreme to another extreme. Vertical Slice is the best architecture I've seen, but this implementation is not pragmatic at all. You can still have a layered application (clean) and still implement vertical slice within clean architecture. This is the ultimate monolith that we were told to stop and quit doing. Funny how old becomes new again. Granted, this is the faster way to onboard any new developers. This is my favorite architecture but no, I would not go this far. You can still have infranstructure and separate your domain objects in case they change.
Nice video. One technical comment. Include is not needed if you have Select. Include is instruction to load related data when full entity is loaded. With Select you are specifying which properties to load and which shape result should have. IOW, EF just ignores your Include.
I don't see how it's the repositories fault that you're returning more data that you have to. Simply return an IEnumerable of the db model from your repository and do the select on your service method, DbContext will defer the query until you call the ToList.
Unfortunately in my experience, this leads to devs having no idea of the implications that the underlying EF is materializing and having a cost when calling methods on it.
I haven't used EF in years as it dominates the overall design too much. People tend to naturally implement repository pattern on top of EF as the exposed interface is vast. There is no going back when devs start to implement complex features with IQueryable stuff. I chose to go with Dapper/SQL instead where repository pattern makes sense. So far really happy with it. Most of the app is event sourced so there is not much use for complex SQL anyway (looking at you Linq). Vertical slices does not yet appeal to me as I like to organize by layers first and features second. This way dependencies per code does not explode. Also testing is easier as lower layers are simple and faster to test. For VSA it seems that you need the whole stack for integration tests or a lot of mock code.
@@CodeOpinion I have separate pipelines for integration and web API tests. Both use real databases. Integration tests don't reference or need any ASP.NET core stuff so they are a lighter to run. Web API tests use full stack, but only include simple flows. This way development can be mostly done without full stack. As in this example I use Mediatr to pass requests from controller to handlers which is a great pattern. With VSA I would probably add directories for each area like: controllers, handlers, views etc. Shared domain code may become a maintenance issue with multiple teams/devs. It is not that clear when you can or should share code as features are mostly independent. Copy-paste may be the safest way to go if you don't fully understand all the features sharing implementation which may add maintenance burden.
DbSet IS a repository pattern that already abstracts the data access away...don't add something repository-like on top of it. Also you are on the right track not to mindlessly adopt everything someone somewhere blogged about :-) Vertical Slices trade development performance for robustness. It just depends on what you need in your project and there is a reason patterns like clean architecture emerged in the first place - because yolo-code where everyone just does "what suits the feature best" led to very unpredictable code
@FarmerSchinken Clean architecture template by Jason Taylor is a prime example of what is often problematic with using EF's DbContext in a layered architecture. In his templates, the application layer has EF reference, which is definitely only an infrastructure concern. It is funnily against the whole idea. DbContext is exposed as-is, which enables application logic to call any operation on any database table. The proper way would be to expose an interface without EF dependency, which would mean exposing feature interfaces that are adapted by the infrastructure layer. I use EF nowadays in some use cases, but I accept to go all in with it.
@@CodeOpinion We have roles like 'client', 'lawfirm', and 'admin' (internal employee user) to represent a specific user view and specifically which tables and data to interact with for the view
If you're using ASP.NET Core you can still do it the same way (via authorize attribute) or you could add authorization in the pipeline if you're using something like MediatR.
@@CodeOpinion I realize now my question was more about handling context with vertical slice architecture. Our contexts are client, law firm, and internal users (admin) vs in another video of yours (warehouse, sales, ect.) Because our feature take into consideration our contexts.
the better approach in the repository thing u can make a contract(interface) of the particular methods you want, the return type is the view model so if u implemented different Datastore/ORM u can implement that contract and get the exact same data from a one class without involve the data layer in the view layer
i think that was the point, removing that abstraction...... why do it if this feature is only going to use this particular set of data that isn't shared by anything else. what else would use "getMyorders" with those specific columns? in this case, nothing. you could swap that out for dapper or or something faster if you needed.
@@digibluh you will have a hard time finding all the queries and change it imagine you moved away from sql so that will be a pain but most of the time people dont change orms/datastores for the entire application on one big update
*_IF_* you move away from SQL? As I mentioned in the very end of the video, boundaries are key. In most situations you aren't dealing with a large schema, or shouldn't be.
You could. I don't generally think much about it in terms of infrastructure I/O. Since vertical slices of a feature can be pretty narrow, I'm more often thinking of transaction scripts or if I need a more rich domain model. I created a video related to this: ruclips.net/video/PrJIMTZsbDw/видео.html
Hi Dereck, Thank you for showing this. This might work on small projects, but it is just not feasible on large projects. Can you imagine what would happen with your app after 15 years of use with 10 programmers working full time on it? N-Layers will never go away even with the microservices architecture.
I'm working on a almost 7 year old system, that is not small by any sense. A combination of feature slices and event driven architecture make it less likely to cause a big ball of mud because there is a clear distinction between features. We almost never have merge conflicts because nobody is ever touch the same files because they are working on individual features.
Amazing video! I learnt a ton from you. How would you couple this Vertical Slicing strategy with Domain Driven Design pattern (aggregate roots, events, etc...)?
You share concerns like aggregates between features. Events fit naturally IMO with vertical slices because a consumer of an event is just similar any other message handler. It consumes to be reactive to perform some action.
EF is kind of a trivial example as it's easy to use POCO classes at the boundary so it doesn't leak through the rest of your code. However if you had an endpoint that depended on multiple Cloud and 3rd party services, SharePoint etc would you put your business logic in the same project as those dependencies, and write business logic against those external classes? If so how would you keep your business logic cleanly separated from the code that is just for integrating with those services? Then what about for junior devs coming in, without those boundaries how are they going to avoid tangling that all up into what essentially becomes a big procedural script with business logic meshed in with integration code? That's what abstractions and Clean are for, to ensure that separation. Also I keep seeing this straw man argument of "abstractions are because we might want to substitute another implementation and they don't solve that problem therefore we don't need abstractions", and I'm going to keep calling it out - That's not what abstractions are for, they're for separating your business logic and integration code. I'm totally onboard with grouping code by domain but not seeing what vertical slice "architecture" gives me over writing a big method that does everything.
History is best teacher. Every good abstraction is build using bottom-up approach. Ex. machine code -> better abstraction is assembler -> better abstraction for the assembler is C -> better abstraction for C is managed environments or jvm, cli etc. Every bad abstraction is build using top-down approach. Ex. Corba Let's start by solving all problems of distributed computing, failed because it was complex So, you are better without abstractions and then when you see patterns (mostly 3 times of copy-paste operations of the same code ) then you create abstraction for the code you copy-paste.
@@JosifovGjorgi By "abstractions" I was referring to programming to interfaces and not implementations (and all their dependencies). I realize it can also be used to refer to layering but that's not what I meant in this context.
@@CodeOpinion I'll look into this some more but it doesn't seem like a substitute for simple use of interfaces and adapters where appropriate. I wouldn't want my pure business logic taking a dependency on a messaging library for example. I'll take a look through your videos but if you could point me to a good complete example that would be great!
Many of my videos are about messaging and decoupling. If you watch others the bigger picture might be a bit clearer. For one specific video, checkout a recent one on using a message driven architecture for decoupling: ruclips.net/video/bxGkavGaEiM/видео.html
"If you need to change implementation from EF core to something else, you are doing that on a feature level" - what? I have never seen that outside of microservices, but they are inherently vertically sliced... Who t f would do that in a more monolithic application? Vertical slice is only great if you really have no cross cutting concerns at all or the awareness and discipline in the team to identify and refactor components that are to be reused anyways (ever tried adding soft delete for domain objects in a HUGE vertically sliced project)? It is basically just a more elaborate way of saying: Just do it all in a single procedure like in the '80 and be smart enough to then refactor your code where it is required. It starts from a weak foundation and then gives no guidelines other than "be smart". That works great for small teams, internal apps or POC-software but there is a reason why clean code emerged in the first place...
Microservices are making logical boundaries also physical boundaries. Logical boundaries should be defined, even within a monolith. How you couple between them is a different conversation. So to answer the question who would do this in a monolithic app? Someone that is defining logical boundaries and likely applying vertical slices within those boundaries. Usually this lands on task based application-level CQRS (not different data models).
Great video! We're 2 years into this kind of refactoring, can't wait to get rid of the repo layer. As abstractions go, I prefer a specification pattern because it gives a name to what can be a complex piece of logic. If your where clause has 7 or 8 different components combined, then a combination of specifications is often more readable.
You can accomplish the same thing with extension methods as well as methods on your DbContext. I might add this as an example in a future video. I almost did it in this video.
@@CodeOpinion That's a great idea, I'll give it a ponder and see if it fits for our future.
2 years sounds like a vanity project. It would take decades of additional development time to recuperate that investment. There is no reason to assume vertical slice is inherently better, it requires much better development skills in general to still ensure consistency, and refactor parts out that should be reused, otherwise you just add a lot of possibilities for new errors and more maintenance cost. But I doubt in your company there is that kind of expertise, otherwise your implementation of clean architecture might be inconvenient, but never warrant such an investment in the first place
@@FarmerSchinken thanks for your feedback. Sold my first website in 99 and been building enterprise for 20 years. I know how to migrate architecture alongside business day to day to ensure the business is where it needs to be technically in 3 and 5 years. Yep, cutting up a system from monolith to specific DDD aggregate boundaries is a long trek if taken as a background one but then you need to have vision to do that.
You do you. Good luck.
Thanks for covering another important topic that can help teams improve on their delivery velocity.
What I love about your videos is that they are concise and bring together the most modern consensus from the industry with approaches that really work.
It’s surprising how often I find younger developers stuck in the past holding onto design patterns that hold them back. Keep it up!
Thanks 👍
That's exactly what we did with BlazorPlate SaaS boilerplate template. we used Vertical Slice architecture alongside Clean Architecture to organize code by a self-containing feature.
Awesome video as always!! Can you make a video on your approach to testing applications? I think that's an extremelly important topic that is sometimes overlooked
"Do I write a stub for this? Should I test this class? Should I test this with a database? How to organize my tests?" etc
Great suggestion!
I find the principle of Vertical Slice Architecture awesome. You have included the views and viewmodels in the ApplicationCore project. If someone now wants to have a CLI program in addition to the WebApp program, then they have also referenced the views and viewmodels. My question is whether it is better to leave the views and viewmodels in the WebApp project.
same question! for me Core should contains only the domain logic, the core logic, no matter who is the consumer, it could be an http request, a rabbitmq-consumer a cli, etc.
awesome video... have a question... imagine i have an app with 10 features and 5 of them requires sending mail. do i duplicate the mail functionality in those 5 places ? doing so is bad right , because fixing a bug in mail sending logic will require fixing it in 5 places right ?
Awesome video, thanks Derek!
Glad you liked it!
This is my preferred architecture. However, for new projects I like to start out by-layer because sometimes it takes a bit for the boundaries of features to shake out. I don't use clean architecture for this - e.g. I have no repo - because the plan is to move to vertical slices once the project accumulates some more features.
I also find this superior for eventually moving to microservices. I always start with a monolith. Feature slices can turn into microservices down the road.
It is more or less a lack of architecture...have you only worked on projects where features are actually "vertical lines of single dependencies"?
I undersand the advantages of this approach but can you please explain to me how do you avoid violating the DRY principle in this kind of architecture? Or is that even relevant, I mean do you just don't bother with DRY at all?
You can have shared concerns between features. It's not about 100% segregation between features. But focusing and organizing code by features and limiting the dependencies to what each feature set needs. Focus on vertical of a slice rather than horizontal of technical concerns.
The application core is a kind of service layer rigth?A client of domain model?
The second-In generall the repository shall be used in write model rathen then in query side when it is advisable to use sql or dapper?Thanks!
Thanks for another great video! What are your thoughts about the combination of event sourcing and vertical slices? I haven't been able to find many examples of this. Do you still query the related events directly from the db? Or would a repository make sense in this situation? Do you colocate the read model in the slice as well? Including the logic to build it up from events / storing snapshots? (sorry a lot of questions here)
You can create read models that live in another service that are composing from various services. ES can be used in various situations, regardless of clean or vertical slices. It's more about boundaries of the the capabilities of the service.
Since I start watching your video I'm every day here
Thank you very much for the contribution. Would this work well in a WindowsForm Project?
Yes. It's not exclusive to HTTP APIs at all.
Using VSA on our new green api project at work. Huge fan!
Hope it works out well!
Good video. This is my preferred way to do Vertical Slicing.
@CodeOpinion I can't agree on removing repositories. If Data access changes I have repository interfaces remain unchanged and instead of changing data access in all features/use-cases I only change repository methods Implementation. If I am relying on specs to formulate query those are gonna be 4 or 5 methods per repository, Or am I missing something ?
Heya, trying this out in a side project. Out of interest, how does feature -> feature communication/dependency usually work? If a feature is explicitly dependent on another feature (e.g. feature X is a bulk orchestration of feature Y) would you have it rely on the feature explicitly? And if calling other features is more so a side effect would it be best to trigger/ orchestrate this via an event to avoid coupling? (For example, on an application level feature A should trigger feature B, but they should not be aware of one another). Just trying to wrap my head around this segment of vertical slice and don't see much info regarding it online; hope my question makes sense lol. Cheers
Since you mentioned orchestrate, have you watched this video on Event Choreography & Orchestration? ruclips.net/video/rO9BXsl4AMQ/видео.html
@@CodeOpinion In hindsight orchestration was an overloaded word - it's pretty simple and doesn't require that kind of finesse IMO. I guess if I was to reword my question it would be the following: Is it okay to have one feature depend upon another if it's a tightly coupled action?
For example if I had a DeleteInvoice feature that took in an invoice ID and a DeleteInvoices (bulk) feature that took in a collection of invoice IDs, would it be recommended for DeleteInvoices to depend upon DeleteInvoice?
@@alucinorbeats Yes absolutely. You can still share types and shared concerns that both features are leveraging.
@@CodeOpinion awesome, thank you for clearing that up! Really appreciate your videos 😁
@@alucinorbeats, great question, tested the structure a little and also bumped into feature-to-feature coupling/dependencies.
Did you stick with vertical-slice/ by-feature design?
I found this video easier to understand than how Jimmy explains it.
Hi,
Thanks for useful video.
Could we use vertical slice in a simple crud based application? Or, just like the cqrs approach, we should only use them in task-based application!
You could for both CRUD and task based. Reality for me is that applications will have a mixture of both CRUD for things that are on the edge and more referential and tasks for more core parts of your domain.
What do you consider to be the cons of this architecture? Feature explosion seems like it could become a problem as the application grows.
Thanks for binging this up. I totally wanted to cover the "cons" in this video and I totally forgot while I was recording it. But the cons IMO are:
1) It's easy to forget that you can have shared concerns between features (eg domain model, validation, etc)
2) Directly related to #1 is ending up with a lot of handlers that are transaction scripts on the command side. Meaning you're changing data directly in handlers and adding more and more logic. As time goes on and complexity adds up. You need to be aware to refactor and move to a proper domain model and invoke it from your handlers.
3) It's a mindset shift for a lot of people. The majority of tooling scaffolds by technical concern. Almost everyone is thought about separating by technical concerns. You're still doing that, but narrowing the focus. It's a mindset change for sure.
@@CodeOpinion Thank you for detailed reply. I am actually in the middle of a migration from a traditional onion architecture to a vertical slice architecture and I was wondering what exactly are the tradeoffs. So far, the only concerns I was able to find is the fact that you absolutely need to define conventions and the fact that we are using dapper to communicate with several data stores so getting rid of the repository layer feels a bit... dirty. With entity framework i totally agree that it doesn't make much sense to add yet another abstraction layer.
@@paulomartins7969, as complexity of the system increase, I actually think (and based on the cons that Derik me sounded above) the vertical slice architecture works tend to be refactored towards onion architecture and not the other way around.
Curious to know what you think.
If you have a class(es) used in multiple different features, which vertical slice feature folder will you put that class in?
Possibly in a parent folder relevant to the multiple features.
Great content as always Derek!
Seeing your implementation and the direct use of the DBContext, I now understand your point on removing the repository abstraction (when it's not necessary).
I was looking the other day at how to cleanly combine the use of the Dapper and EFCore, but with vertical slices, it's no longer a concern as every feature can use the ORM that fits its needs directly.
I do hope you'll make a video on where you actually find it beneficial (the repository pattern that is).
Generally for getting out an Aggregate (Root). Check out this video: ruclips.net/video/GtWVGJp061A/видео.html
A DbSet IS a repository pattern...If you tack another thing on top of it, you are doing it wrong to begin with....
@CodeOpinion Great video! Btw which keyboard are you using?
Just a regular keyboard, nothing special. I know it got picked up by my mic a bit in some spots more than others. Need to pay attention to that more next time.
@@CodeOpinion give logitech mx keys a try. by far the best i had.
How do you plan to run tests now that your query handler operates directly on the database? Isn’t the purpose of the injected repository that it can be replaced (e.g., in tests with an in-memory repository)?
Use something like Testcontainers for Docker instantiated DBs . Very useful for integration testing as in-memory for EF isnt really recommend anyway.
I love the feature approach. This should always be the way, but still loads of projects have that vertical jump F12 key press for their lifes.
Regards to the abstractions, instead of having a Infrastructure project maybe make sense to call Infrastructure folder inside the ApplicationCore. Data Accesses, Logging, Proxies they should be exposed by their API using interfaces. If the handlers need some IO from the outside we need to inject them in a specific handler for example, and specially for testing we should work with abstractions so at that level we don't think too much about the technicals and also is easier to test it and mock it.
What do you think about that subject? Regarding people creating IWhateverDbContext and etc to abstract the actual context to make possible to test each specific handler? so that way we should keep the Infrastructure project and keep the implementations there... but thats crap now that things are far away again. mixed feelings.
I generally don't concern myself with abstracting Entity Framework within a logical boundary. This is because coupling is limited to the vertical slice which is very narrow to begin with. This means that coupling is limited. Another way to put it, is I don't create large DbContext's but rather small ones that own a particular schema (tables). Abstracting the DbContext ends up having little value and just another layer of indirection. Check out a couple videos that might help get a better idea:
Cost of Indirection: ruclips.net/video/DNjDZ0E6GUs/видео.html
Should you use a Repository: ruclips.net/video/01lygxvbao4/видео.html
Hi Derek, what a great video. Congrats🎯
I have some questions and I'm sure you can give your opinion. How can coexist DDD practices and Vertical Slice architecture?
Let me explain my use case: I have my clear architecture application, and I have a controller for my orders, an application service to manage my application logic (e.g save in database, publish events), my domain service that is responsible for domain validations and business rules (e.g you can't place an order if the product is only available for some kind of customer segment) and finally my domain model. Restructuring this to a vertical slice, I can imagine 2 projects, OrdersAPI (which have my features) and OrdersDomain (which have my domain models and services). This could be a good decision? I'm asking because I can see this domain service living in the Feature folder, but should I move it? Or leave it together with my domain models? Or I'm thinking a lot about clean architecture and what makes sense is to put all things together?
Can you please share your opinion?
Thank you, cheers 🍺
There are different ways you can approach and think about this. You can apply clean to a "set" of features if you want to have that technical separation between infrastructure, application and domain, just as you do now. You can share concerns (eg, data access, data models, domain models) between feature slices. The biggest thing with thinking about vertical slices is putting the concept of a feature at the forefront and not technical concerns. This other video might help a bit where I talk about various concerns and how transaction scripts may be simple in some places, while others need more control over complexity. ruclips.net/video/PrJIMTZsbDw/видео.html
Hey Derek! In a front-end application which is just calling endpoints and doing it's things and does not have actual business logic(because it is implemented on the back-end side). So, My question is what will be the entities in this case?
Not entirely sure what you mean. Your client would be just calling your HTTP API and using the results. Check out this video, let me know if it helps: ruclips.net/video/6XO6vSiioWE/видео.html
@@CodeOpinion It did help. Let me make my question clear. So, let's say I have a Mobile app and I want to architect it using clean architecture. So, in that case what will be my entities, if I'm just calling endpoints from the app and doing things based off that result?
Say two or more features need as a part of their handlers to check if a user exists, among other things. Would you isolate this operation into a reusable function in something like a repository class or you would repeat the same code in all the features? And last but not least, thanks for all your videos, amazing content.
Yes, for sure you can share some reusable functions between handlers. The point isn't to make them 100% independent but rather think vertically and organize that way rather that horizontally. Once you do so, even if you do share some reusable function, it likely would be limited to a few handlers, which limits coupling.
I am quite curious by this, but I have a question with Vertical Slice architecture and EventSourcing.
Say you 2 have separate features (Delete Line Item) (Complete Order) that add a new event on the Aggregate/Stream. For both cases you need to load the stream from your event store and replay the events to build the aggregate.
Where does the loading from event store and replaying the events code live? That seems to be it has to be shared across all features that need to manipulate a given Stream
Yes, a shared class that both use. Some type of BasketRepository. Vertical slices aren't about NO sharing, but grouping the functionality together, deciding individually per feature and set which dependencies you take.
What's the benefit of using mediator here if they're all in the same file?
Why not make the get handler a helper method and call from the controller?
I’m curious how do you write unit tests for features?
Generally I'm creating a pipeline for a request. Each individual filter can be tested independently. Check out this video on creating a pipeline ruclips.net/video/msXtN15qXOE/видео.html
Is it ok if I use "GetMyOrders" as method? because I think a class should be treated as a noun not a verb, I like arquitecture and I like these things lol
When I saw the repo in for the query feature I was screaming then you refactored it and I had a smile upon my face 😁
Quick question: for the orders query feature what is the value of using MediatR? Why not get rid of it like the repo?
Good question. The video on Pipes & Filters (ruclips.net/video/msXtN15qXOE/видео.html) is really a primary driver for using a dispatcher like MediatR because it supports creating a pipeline (behaviors). If you're not using a pipeline, the value diminishes a bit IMO. Arguably you could still have your code separate from the controller and just inject the class (or interface) of your "handler" rather than dispatching with MediatR. If you want to use a pipeline, then MediatR (or similar) makes a lot of sense.
Hi Derek.
Thanks for all your content. Very inspiring. I am not sure I understand this entirely. In your looslyCoupledMonolith you had a project for abstractions for communication between bounded contexts. How would that work in a scenario like this? What if some other feature needs to get a list of my orders?
If you're in a monolith, and you want to use in-process communication between boundaries then just expose an interface/delegate in the contract/abstractions project for fetching/returning that data. Just realize you're more tightly coupled doing so.
Cool video. I noticed that you mainly use GUIDs instead of Sequential Ids for your entities. Did you ever have problems with Fragmentation when using GUIDs for your projects?
Fragmentation at the database level you mean? Using GUIDs is helpful when in asynchronous messaging, which is where you'll see me often use it.
@@CodeOpinion Yes I mean at database level. I just read a bit about this topic and see the advantages of Guids, but some posts about fragmentation really made me wonder if I should use them.
Depends on the DB and the type of index.
With regards to the repository layer, are you suggesting that omitting the repository is good for the read model/querying model (I agree with this especially after your explanation). However the repository layer is still essential for the write model as this is an anti corruption layer (ACL) and will protect our domain layer (e.g. we don't want to load aggregate root and not its children directly via db context)?
This video directly covers the question: ruclips.net/video/01lygxvbao4/видео.html
@@CodeOpinion Oh Perfect!
I understand the motivation to return focused view models for list operations in the context of a web application that selectively uses a subset of the resource’s properties, but in the case of API-first, REST-based applications, that are designed to return the full representation of the entity in the list queries, would you still choose to remove the repository and specifications?
Or is that perhaps the wrong question? Put another way, would you ever design a REST API to return the same model for the elements of a list as the query for a single element of the same resource? An example off the top of my head is Stripe’s API.
A resource can be whatever you want. Don't constrain yourself to the notion of a resource is an entity and CRUD built around it. It does not need to be an Entity. I created a video on this, if you haven't watched already. ruclips.net/video/2gOOstEI4vU/видео.html
How do you deal with identity in this case? Do you have some sort of IdentityService which abstracts away the UserManager and RoleManager? Or do you just use those Identity classes directly in your handlers, just like you use EF Core directly? Also, if you have an entity that can "belong" to a user (e.g. a booking), would you use the `IdentityUser` derived `ApplicationUser` in the `Booking` class as a User property? Or just have a string property for their ID?
Cheers
It really depends how you want to handle authorization. I generally attach some form of identity to messages (commands/queries/events). To get the general gist, even if you aren't using NServiceBus, check out this post: docs.particular.net/samples/username-header/
@@CodeOpinion That makes sense. What about handling changes to Identity? Like a user updates their display name, or an admin updates the roles/permissions of a user? Is there a separate "slice" to deal with users, roles, etc?
Thanks for the interesting video, Derek! What would be the difference between this and transaction scripts? The approach you show works well IMO because you still have a set of well designed abstractions (view models, controllers, a domain layer for the rules of changing state, etc.) that you can use as and when you need to. I’ve seen codebases I’d describe as set of vertical procedural Python scripts (cannot be called OO or FP really) with very little abstractions, attached to the web host / event bus. You either need physical layers or lot of discipline to impose order IMO when you remove those walls
I didn't show anything in this video, but if you had a command handler that did everything in the handler directly. Meaning it was interacting with the data model directly. This can work as you start out if you don't understand the model that well or where the transaction boundaries are. Transaction scripts can get out of hand in a hurry and before you know it you're changing data in various handlers and have no central model. This is when you can start introducing aggregates and centralizing logic around a transaction boundary. Check out this video if you haven't about Aggregate Design: ruclips.net/video/64ngP-aUYPc/видео.html
but isn't it data driven instead of behaviour driven if you're grouping by domain model names ? I remember you told behaviour > data in one of your videos. I mean you name the folder Orders, but it doesn't tell anything about the system's purpose, why don't we name our folders based on the feature's name ? (fi.: DriveCar and BuyCar instead of Cars folder)
Man, your videos are gold. I have said this in previous videos but it is very hard to find quality videos on software architecture but yours are good and to the point. On the other hand, I know you won't like this "dumb" question but what do you think works better Onion or Vertical architecture?. By the way, I would like to do a request: What do you think about creating a series of videos where you expose an imaginary client request (For example, creating a backend for an eshop) and building a decoupled monolith following for example vertical architecture? I am not talking about adding the real business logic but things like how to split features from requirements, how to build the folder structure for each feature, etc. I mean, the things about architecture that no one talks about or if they do they are really generalistic :)
I prefer vertical because it allows me to focus on capabilities and organize them by commands, queries, and events. Thinking vertically also allows for more distinct logical service boundaries. As for the the request, I'll think about how I can work that out. The difficulty is using a simple enough example that most can understand without actually understanding the domain. Anything complex has a lot of value explaining but only if you already are familiar with the domain. It's a tough situation when creating examples.
@@CodeOpinion Yes, I agree with that. It is difficult to find a good project to showcase infra structure if the learner doesn't understand the domain. Let's hope you find something that could fit :)
if tis not hidden behind an abstraction how do you test it? can you mock the dbContext in the test phase?
If you need an abstraction, create an abstraction if it serves you value. However not everything needs a mock for testing. ruclips.net/video/2oRofOH2NT4/видео.html
About 12:20
Also, now that the "file" keyword exists in C#, it could be useful when you need to create a new model for a specific feature, like here in with MyOrdersViewModel. Having to find a new name would not be a problem anymore. Maybe more responses with different columns would make sense to only be named "OderResponse" or so
What's your approach with testing when doing vertical slicing?
Writing tests for the handlers or individual parts of a request pipeline.
@@CodeOpinion and what kind of tests you do the most? As you get rid of interfaces/abstractions I guess you're forced to have more integration tests than unit tests, right?
Do you have a sample project for API project?
Hi Derek,
In this video, you said we don't need to abstract EF, changing our persistence mechanism is fine because we just replace it in our feature level, But what about testing? It is hard testing with a direct dependency. Although EF core has in-momroy provider for unit testing, but what about using other providers like MongoDriver? So we have to use an abstraction here!!
I view EF as an abstraction already. If you want to create an abstraction (so you own it) over the data persistence you're using, by all means!
@@CodeOpinion How do you unit test it if we don't use entity framework? How could we test without abstraction? Something like this we have to. What is your opinion?
Awesome video!
Glad you enjoyed it
This is genius
I want to click 1000 times on thumbs up button!
from one extreme to another extreme. Vertical Slice is the best architecture I've seen, but this implementation is not pragmatic at all. You can still have a layered application (clean) and still implement vertical slice within clean architecture. This is the ultimate monolith that we were told to stop and quit doing. Funny how old becomes new again. Granted, this is the faster way to onboard any new developers. This is my favorite architecture but no, I would not go this far. You can still have infranstructure and separate your domain objects in case they change.
Where do you keep the domain models? in the Entities folder?
Anywhere that can be shared by the features that require it.
Nice video. One technical comment. Include is not needed if you have Select. Include is instruction to load related data when full entity is loaded. With Select you are specifying which properties to load and which shape result should have. IOW, EF just ignores your Include.
He meant select * as in SQL not LINQ Select().
I don't see how it's the repositories fault that you're returning more data that you have to. Simply return an IEnumerable of the db model from your repository and do the select on your service method, DbContext will defer the query until you call the ToList.
Unfortunately in my experience, this leads to devs having no idea of the implications that the underlying EF is materializing and having a cost when calling methods on it.
I haven't used EF in years as it dominates the overall design too much. People tend to naturally implement repository pattern on top of EF as the exposed interface is vast. There is no going back when devs start to implement complex features with IQueryable stuff. I chose to go with Dapper/SQL instead where repository pattern makes sense. So far really happy with it. Most of the app is event sourced so there is not much use for complex SQL anyway (looking at you Linq).
Vertical slices does not yet appeal to me as I like to organize by layers first and features second. This way dependencies per code does not explode. Also testing is easier as lower layers are simple and faster to test. For VSA it seems that you need the whole stack for integration tests or a lot of mock code.
If you have a pipeline for a request, you can test each step independently or the entire pipeline.
@@CodeOpinion I have separate pipelines for integration and web API tests. Both use real databases. Integration tests don't reference or need any ASP.NET core stuff so they are a lighter to run. Web API tests use full stack, but only include simple flows. This way development can be mostly done without full stack. As in this example I use Mediatr to pass requests from controller to handlers which is a great pattern.
With VSA I would probably add directories for each area like: controllers, handlers, views etc. Shared domain code may become a maintenance issue with multiple teams/devs. It is not that clear when you can or should share code as features are mostly independent. Copy-paste may be the safest way to go if you don't fully understand all the features sharing implementation which may add maintenance burden.
DbSet IS a repository pattern that already abstracts the data access away...don't add something repository-like on top of it. Also you are on the right track not to mindlessly adopt everything someone somewhere blogged about :-) Vertical Slices trade development performance for robustness. It just depends on what you need in your project and there is a reason patterns like clean architecture emerged in the first place - because yolo-code where everyone just does "what suits the feature best" led to very unpredictable code
@FarmerSchinken Clean architecture template by Jason Taylor is a prime example of what is often problematic with using EF's DbContext in a layered architecture. In his templates, the application layer has EF reference, which is definitely only an infrastructure concern. It is funnily against the whole idea. DbContext is exposed as-is, which enables application logic to call any operation on any database table.
The proper way would be to expose an interface without EF dependency, which would mean exposing feature interfaces that are adapted by the infrastructure layer. I use EF nowadays in some use cases, but I accept to go all in with it.
Would love to get to Vertical Slice Architecture, how could web roles be handled with VSA?
What exactly do you mean by "web roles"?
@@CodeOpinion We have roles like 'client', 'lawfirm', and 'admin' (internal employee user) to represent a specific user view and specifically which tables and data to interact with for the view
If you're using ASP.NET Core you can still do it the same way (via authorize attribute) or you could add authorization in the pipeline if you're using something like MediatR.
@@CodeOpinion so don't separate the role view out in the feature correct?
@@CodeOpinion I realize now my question was more about handling context with vertical slice architecture. Our contexts are client, law firm, and internal users (admin) vs in another video of yours (warehouse, sales, ect.) Because our feature take into consideration our contexts.
Can you please give an example github repo?
the better approach in the repository thing u can make a contract(interface) of the particular methods you want, the return type is the view model so if u implemented different Datastore/ORM u can implement that contract and get the exact same data from a one class without involve the data layer in the view layer
i think that was the point, removing that abstraction...... why do it if this feature is only going to use this particular set of data that isn't shared by anything else. what else would use "getMyorders" with those specific columns? in this case, nothing. you could swap that out for dapper or or something faster if you needed.
@@digibluh you will have a hard time finding all the queries and change it imagine you moved away from sql so that will be a pain but most of the time people dont change orms/datastores for the entire application on one big update
*_IF_* you move away from SQL? As I mentioned in the very end of the video, boundaries are key. In most situations you aren't dealing with a large schema, or shouldn't be.
As I'm getting into GraphQL I wonder how that can fit into CQRS and vertical slice architecture...
I need to talk about this is a video soon!
The query side seems to be really flexible in this approach. Maybe we can go further and use GraphQL there?
You could, nothing stopping you from using it on the query side.
Dude...is that twitter-driven-design? You don't have to incorporate every single hype...
@@FarmerSchinken gql is 10 year old tech and adding it to the mix can solve a lot of problems with over/under fetching which is important on mobile :)
Can vertical slice be clean?
You could. I don't generally think much about it in terms of infrastructure I/O. Since vertical slices of a feature can be pretty narrow, I'm more often thinking of transaction scripts or if I need a more rich domain model. I created a video related to this: ruclips.net/video/PrJIMTZsbDw/видео.html
Hi Dereck,
Thank you for showing this.
This might work on small projects, but it is just not feasible on large projects.
Can you imagine what would happen with your app after 15 years of use with 10 programmers working full time on it?
N-Layers will never go away even with the microservices architecture.
I'm working on a almost 7 year old system, that is not small by any sense. A combination of feature slices and event driven architecture make it less likely to cause a big ball of mud because there is a clear distinction between features. We almost never have merge conflicts because nobody is ever touch the same files because they are working on individual features.
Hi I tried this and my reference to the view throw a cannot find path to my file.cshtml.
Are you using my members git repo or recreated it yourself? If you've re-created it, make sure the ApplicationCore.csproj is using the Razor SDK:
@@CodeOpinion It did fix the issue thanks. This type of project is it like a Razor Class Library?
Amazing video! I learnt a ton from you. How would you couple this Vertical Slicing strategy with Domain Driven Design pattern (aggregate roots, events, etc...)?
You share concerns like aggregates between features. Events fit naturally IMO with vertical slices because a consumer of an event is just similar any other message handler. It consumes to be reactive to perform some action.
EF is kind of a trivial example as it's easy to use POCO classes at the boundary so it doesn't leak through the rest of your code. However if you had an endpoint that depended on multiple Cloud and 3rd party services, SharePoint etc would you put your business logic in the same project as those dependencies, and write business logic against those external classes? If so how would you keep your business logic cleanly separated from the code that is just for integrating with those services? Then what about for junior devs coming in, without those boundaries how are they going to avoid tangling that all up into what essentially becomes a big procedural script with business logic meshed in with integration code? That's what abstractions and Clean are for, to ensure that separation.
Also I keep seeing this straw man argument of "abstractions are because we might want to substitute another implementation and they don't solve that problem therefore we don't need abstractions", and I'm going to keep calling it out - That's not what abstractions are for, they're for separating your business logic and integration code.
I'm totally onboard with grouping code by domain but not seeing what vertical slice "architecture" gives me over writing a big method that does everything.
I use message and event driven architecture for a lot of integration.
History is best teacher.
Every good abstraction is build using bottom-up approach.
Ex. machine code -> better abstraction is assembler -> better abstraction for the assembler is C -> better abstraction for C is managed environments or jvm, cli etc.
Every bad abstraction is build using top-down approach.
Ex. Corba
Let's start by solving all problems of distributed computing, failed because it was complex
So, you are better without abstractions and then when you see patterns (mostly 3 times of copy-paste operations of the same code ) then you create abstraction for the code you copy-paste.
@@JosifovGjorgi By "abstractions" I was referring to programming to interfaces and not implementations (and all their dependencies). I realize it can also be used to refer to layering but that's not what I meant in this context.
@@CodeOpinion I'll look into this some more but it doesn't seem like a substitute for simple use of interfaces and adapters where appropriate. I wouldn't want my pure business logic taking a dependency on a messaging library for example. I'll take a look through your videos but if you could point me to a good complete example that would be great!
Many of my videos are about messaging and decoupling. If you watch others the bigger picture might be a bit clearer. For one specific video, checkout a recent one on using a message driven architecture for decoupling: ruclips.net/video/bxGkavGaEiM/видео.html
Such a pity the code sample is not publicly available :(
Nvm, just became a member lol. That's an effective sales tactic overthere.
😊 I really do appreciate the support! Thank you!
Feature 🍕
Should I put that emoji in the title? 😆
"If you need to change implementation from EF core to something else, you are doing that on a feature level" - what? I have never seen that outside of microservices, but they are inherently vertically sliced... Who t f would do that in a more monolithic application? Vertical slice is only great if you really have no cross cutting concerns at all or the awareness and discipline in the team to identify and refactor components that are to be reused anyways (ever tried adding soft delete for domain objects in a HUGE vertically sliced project)?
It is basically just a more elaborate way of saying: Just do it all in a single procedure like in the '80 and be smart enough to then refactor your code where it is required. It starts from a weak foundation and then gives no guidelines other than "be smart". That works great for small teams, internal apps or POC-software but there is a reason why clean code emerged in the first place...
Microservices are making logical boundaries also physical boundaries. Logical boundaries should be defined, even within a monolith. How you couple between them is a different conversation. So to answer the question who would do this in a monolithic app? Someone that is defining logical boundaries and likely applying vertical slices within those boundaries. Usually this lands on task based application-level CQRS (not different data models).