SOLID Architecture: Slices not Layers
CC Attribution - NonCommercial - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Bogard, Jimmy
For too long we've lived under the tyranny of n-tier architectures. Building systems with complicated abstractions, needless indirection and more mocks in our tests than a comedy special. But there is a better way - thinking in terms of architectures of vertical slices instead horizontal layers. Once we embrace slices over layers, we open ourselves to a new, simpler architecture, changing how we build, organize and deploy systems.
 All right, good morning everyone. Or, no, yes, it's still morning. Okay. My name is Jimmy. I wanted to talk a little bit today about crappy architecture and good architecture, especially in the face of all these microservices talks. I wanted to embrace the monolith and show an architecture that it could actually scale with complexity. I have a feeling that a lot of the people that are doing microservices are doing this because they're already building on top of kind of crappy platforms to begin with, like Ruby on Rails and Node. So with architectures that do actually scale, we can actually get a pretty long way to building at a nice system. So you can find me on Twitter at atjbogards. My GitHub is also the same github.com. Everything that we see today in all my open source projects are going to be on there. So there's a presentations repository. You can find everything here, as well as my other presentations. I blog on those techies, jimmybogard.listtechies.com. And that's about it. So let's start the first thing. I want to talk about this. Crap. So most of what I do in real development is I work with existing legacy systems and try to build better systems from those ashes of those horrible, horrible systems. And a lot of what I see of systems today are these big balls of mud. And they came out not because any developer had an intention of creating this big pile of crap, but it just kind of happened over time. And a lot of what I see even on smaller systems is an assumption that some kind of layered architecture will somehow provide a better system in the end. But what I found is that those layers don't actually produce anything better in the end. They just produce kind of a layered pile of crap and not actually anything good. So a few weeks ago, I had the privilege of reviewing some code from a customer of mine. This is a customer that their primary domain was manufacturing, and they weren't really coders. They knew how to build things. They didn't know how to really write code and say they would hire other people to come and write code for them. What this meant, though, is they didn't really have any expertise in understanding, looking at code whether it was good or bad. All they knew is that their deadlines were missed. There were a lot of bugs in the system, and they wanted to know why. So they asked me to come and take a look and say, it's not a very complex system. Can you tell us why they're missing deadlines? Why there are so many bugs? So looking at this application, it's clear to me that the inmates were definitely running the asylum. This is an app with a very small footprint. There were four screens, just four screens. And the purpose of the system was the company was moving off of a set of bespoke systems into one centralized system for some of their manufacturing data. And the point of this system was really just to take the data out of the old systems and cleanse it, so to speak, and put it into their new system. And that was literally it, just like screens to modify data and then some basic workflow to say, I have approved this data and now I can go on to the central system. And that was it, just like few screens, the home screen, and that was it. But somehow, with the system, there's just a few tables and workflow, the developers managed to create a code base with 20,000 lines of code. And on the one hand, I want to applaud them and say, well, that's actually pretty hard to do to create such an insanely complex system for something so simple, so kudos to you for that. And as well as, let's see, I had two solutions and 12 projects to do this very, very simple thing. It was one of the most insane things I've ever seen. So I wanted to walk through real quick what their architecture currently was. So it first started out, this is a system built in the last six months, first started out with web forms, which red flag number one, if you're building a new system today and you're using web forms, you should probably just quit. Just stop doing anything development-wise. You shouldn't be using web forms at all. So from the ASPX page, there was the code behind. Now what I found was that with all those 20,000 lines of code, most of it actually resided in these two parts, the ASPX page and the code behind. And the ASPX page would have, in the middle of there's like one, the other three pages were just like a login screen and a home screen, which you click the link to go to this screen. There's about 3,000 lines of code in the ASPX page, and then about another 3,000 or 4,000 lines of code in the code behind. So with all this layers they had put in here, these 12 projects, they didn't actually solve their complexity problem, they just shoved it into exactly two files. So from there, the request hit a service proxy, which was another Visual Studio project to wrap WCF, because what WCF needs is more abstraction. From there, it hit the actual WCF service proxy. And this is where we switched solutions. So now I was in the UI project, now I have to go to the service, the UI solution, now I have to go to the service solution. I did ask the business, so why are you guys creating web services for this project? They have to expose their capabilities to someone else? No, they didn't even know what a web service was. So again, just complete over-engineering. So from here, we hit the actual WCF service. And from the WCF service, we hit the actual business application layer. I don't really know what the a actually stood for. In the name states, it said BAL, so I can just assume it's business application layer. I don't know, has anyone had any guesses for what the a stood for besides that? Abstraction, sure, why not? Because we need more of that. OK, so the business abstraction layer, architecture layer, application layer, whatever a stood for, it's lost to the ages because we deleted this repository soon after we met these folks. From there, the business, the bow, whatever that means, hit the dow, which could only mean data access layer or data application layer or data abstraction layer. I don't know what. One of those three things. And looking at the code from each of these new layers, the service proxy, the BAL and the DAL, the entirety of those code bases just consisted of interfaces, then classes. And then inside those classes, each of the methods would be to do something like approve material data or something like that. And inside the method, there was one line of code that was actually real stuff, and that line of code would just call into the next layer down. And then surrounding that was a try catch block, which caught whatever exception it might be, wrap it in a new exception based on that layer, and then throw that exception and maybe do some logging as well. Looking across the dozens of these service classes to see what, if there's any business logic in them, there was none. It was literally try catch, wrap, throw again. By the way, this whole talk is a complete straw man. I know you're probably not creating these architectures, right? OK. OK, so from the data access layer, which didn't do actually data access, it was still using ADO.NET, raw just like bare bones ADO.NET. And from there, it actually called a stored procedure where the actual data access logic lied. Funny enough, the stored procedure and everything going down were regular kind of DTOs, but on the way up, they decided to use data sets for everything, which I found just absolutely hilarious. So I actually built a tool called AutoMapper, which enables some of these architectures. And so what I'm trying to do with this talk is to repent for some of the sins of people using my tool for very evil and nefarious purposes. When I first started out in.NET, this was when I first graduated university around the early 2000s. I was desperate to see how people actually built systems. I went to school not for computer science or anything like that. I went to school for computer engineering. So I didn't really get any instruction from the university about how to build actual applications. I knew about how to build things that made robots go, but nothing about actual systems. So I looked at the documentation and the guidance at the time to see how do people really build systems these days. And naturally, my first result that came up was MSDN documentation for Microsoft about how to build systems with good architecture. Now, the picture they drew was something like this. I have a UI layer, a business logic layer, data access layer, and then finally the database. Now, this should be warning number one. Don't take advice from people about architectures that don't actually build real systems. They just write about them. If they haven't actually built systems, then they're probably giving lousy advice. And this is what the advice that I was given early on was, to build everything in layers. Now, that worked OK for small systems that I worked with. But my first real job and real product I had to work with, I saw that this architecture wouldn't scale. So at the time, the domain-driven design book just came out, and people were really latching onto this as a way to manage complex systems. So this was replaced by a much better architecture, the domain-driven-desire style interior architecture, which is obviously much better. Instead of my business logic layer, I have domain objects. And instead of a data access layer, I have repository. So it was actually pretty easy to move from an interior style architecture to domain-driven design. You really just have to rename some files. And now you're doing domain-driven design. And when I built these systems, I would organize everything in my system by its layer. So if I had something that was person, and by the way, this is another huge warning. If you have something in your system called person, you've probably done something wrong in your modeling, as well as something called user. No one has a title of user or title of person in your company, so you should probably have a thing called person. And I would build things around this by its layer. So I'd have a person class that had a person data in it, a person controller for MVC stuff, then a person service, which is really where all the business logic lied, because I couldn't figure out how to put things in the actual domain layer, and then finally a person repository, which again was really just a gateway on top of the database. And so at the time, when it came time to actually building out my repository, I wound up looking something like this. Now this is actual code that I wrote, so I have no one to blame but myself on this when I can blame developers somewhere else. I built something like this for my repository. And it's actually cut off at the bottom, because there's actually too many methods for you to fit in the screen. And so this repository had methods for basically every single kind of data access thing I would actually have in the system. And I might have something simple like get some person by its person ID. But if I need to do extra data access or extra ORM fetching or something like that, well, I couldn't just use that. I had to actually build new methods for every style of thing or every kind of thing I need to fetch out. So I'd start to have more methods for all the different ways that actually query and on and on and on and on. So how can I dig myself out of this? The first thing I would need to do is to characterize what I'm actually doing in my application. And this is where I find that the architecture of the web lends itself well to actually good back in architecture. The web itself is very, very simple. I have basically two kinds of requests in my system. I'm going to ignore the hipster ones, the put, patch, delete those ones, and just focus on the ones that people actually use, get and post. And these two things are very, very simple. I use gets for reads, and I use posts for writes. Gits are nice because they're safe and then they don't have side effects. And their item potent means I can call them over and over again, and the result is the same as if I called it once. The effect of emangling the definition, that's good enough. Post is for everything else. So if I'm mutating data, doing something, or modifying something in the server, I use posts. And in that case, it's not guaranteed to be safe and not guaranteed to be item-poded. Now it could be, but there's just no guarantees around that. So looking at these two things, I can see that my gets are queries and my posts are commands. So queries to do something or to ask for some data, and then a command to then make some modification to the data and go on with my day. Looking at my systems that I built, if I look in my application, the way I've organized and the way I built it out, I've got all these layers for every kind of thing in my system. And I only have four layers here, but typically I see much more than that. I might have models, view models, services, all these different folders for all these different layers. When it comes time to actually building something in the system, I don't build something across a layer. I'll build things down layers. So if I'm going to add a new screen to my system, I'm going to make a change to the user interface, create a new view file, create a new controller. I may have to make changes to some data objects. I don't have repositories anymore, but we'll get to that. And so what I'm doing here is making changes not across a layer, but down a layer. So every new feature I have in my system, something like view and approve invoices. I'm making changes to every single layer. Approving an invoice, again, every single layer, or rejecting an invoice. I'm having to touch all these different places down the line. And typically in my solutions, I'm jumping all around to go ahead and make these changes. I often find that with these layered architectures, this is where a lot of the source of merge conflicts comes into play, because I'm modifying these objects that have changes across all these different layers. For example, the repository here. For each of those three vertical yellow boxes, I'm making some change in that repository to add some functionality for whatever that is. So if more than one person is having to change these files across these layers, that's going to be running into conflicts. So about five years ago, I can't take credit for it, but maybe I will anyway. There's a great pattern introduced that built on top of the idea of command query separation and said, OK, how about instead of us just talking about methods where I have commands and queries, how about when we talk about objects, where I have two different models for commands and queries as opposed to just one? And really this is coming around and looking at things like repositories and saying, well, we thought that repositories, not kind of pattern, was there to help be a good example of something in solid, that it was a single responsibility because it did data access. The really big one, though, that I missed was the I in solid, I being interface segregation principle. The idea that if I need to make a, I have no idea what ISP means, I just know that repository violates it somehow. So the idea is that in my repository, if I look back at the one that had all those different methods on it, for any given one of these vertical slices, I'm only using one of those methods in each different use case. You'd have just shoved them all in one file as if they have something to do with each other. But in reality, they don't. Recently, about a year ago, I guess now, I was part of a project where we were moving ORMs. I know that's something people never, ever do as a code base change ORMs, but it's something that we had to do. And for us, if I was using the abstraction of the repository, we would have never been able to make that switch because the repository was coupled to whatever ORM I was using underneath the covers. But with a more vertical slice architecture, we were actually able to change our ORMs we were using. Originally, you were using NPoco, which is a micro-ORM, went to Inhybernate, which is a complete other side of the spectrum, and finally, we went to Entity Framework, which was kind of in the middle between those two choices. And we made these changes in the course of about two or three days that we would never have been able to do with this style of architecture of layers. So it all came back for us to CQRS, where we built two models where once there was one. Now, if anyone who was in Udi's talk yesterday on CQRS, this is the style of CQRS I'm talking about. Not the asynchronous, invented, like, two databases ridiculously architecture version, but where I'm just taking one object and splitting it into two, and that's it. So if I go back and look at my repository, in this repository, I have all these methods that are only used in one specific use case. So there's really no reason for them to live together. If they don't change together, then they shouldn't live together. When I look at this, I also see a pattern emerging in that I have a set of methods that describe some kind of distinct query for a specific use case, and then I may have things in there for specific commands, like remove updated flag from all people, which is probably a bad idea to do anyway, but there it is. OK, so with this crazy layered architecture, I want to get to someplace better. The first thing I have to do is rewind all those abstractions. Unfortunately, when you have a very poorly architected system, it's difficult to refactor incrementally to something better. Sometimes you have to just take away all the crap and put everything in one spot, and then you can go out and then put something else on top of it. So my first step was just to collapse all the layers and remove any kind of insanity-errant system. So I looked at my system. This is MVC. And I know that GETs are basically queries and posts or commands. So if I start to look at those different controller actions and see what they're actually doing, I can start to see if there's any sort of concept that emerges from these two styles of usage, queries and commands. So moving all those repositories, doing the heinous thing of just doing data access directly in my controller, I know it's horrible, using it directly, I start to look at, OK, what are these things doing? This is a more complex query in which I actually took this from Microsoft's new example on how to build systems, Contoso University, which is also another great example of how not to build systems. And I'm trying to take this and move it to some kind of better architecture. So inside the controller action, I have a mix of concerns going on. I have some data access going on in which I'm going and querying entity framework for stuff. Then I'm putting stuff into View Bag, which is just a data dictionary for storing stuff for views. And then finally, I'm telling MVC to go ahead and show a view by passing it a view model. This is also another red flag I saw mixing the data dictionary style of MVC and the strongly-type view side of MVC. If you're doing both of those things, it's really confusing. So this was a simple version. So this is a more complex query. I might have a more simple version that looks something like this, where it's literally one line of code. There is one thing that is a little bit interesting here. And that I have, in this case, I'm showing a list of departments, but I have this include method at the end. This include method says, I want you to go ahead and fetch that additional data. And there's one thing that developers do really well. It's managing ORM fetching. Oh, no, I'm sorry. What we do horribly is manage ORM fetching. This is one of those things that I see as the shining example of why people don't like ORMs. It's because they have to do crap like this, fetching some additional data because they have to use it sometime later. Now, in ORMs, it's actually relatively easy for us to go ahead and navigate associations on our data access objects or in any models, whatever you want to call them, and then have the ORM go ahead and silently behind the scenes fetch stuff, which is actually a very horrible thing to do, to go and let the ORM just magically do queries behind the scenes. So instead of doing that, we have to kind of remember that, oh, by the way, we're using this other object over here, so go ahead and fetch that. If we use anything else on those objects, we'll have to go back and change this to make sure we also include and fetch that additional data. Again, if there's something I have to remember to do, I'm going to forget. So I'd rather build on top of an architecture that forces me to be explicit about what I need. Some of my queries could be a little bit more complex in the actual logic they're doing in the controller action. In this one, for example, whenever I'm modifying information, there's still a git that has to be made that shows the form, and then there's a post on the other side to actually modify the data. So in the git case, there's only a very small piece that's doing the actual data access. The rest of it is just other junk I'm using to take care of other kind of edge cases. So in this case, if they don't supply an ID, I need to return a bad request. Results, if the actual object is in file, so they give me an ID, but the thing isn't in the database, then I return yet another thing. And then this is the kind of code that I see copy and pasted all over the application. So this is another thing I'd like to address is to figure out when I have these things that I see copied and pasted over and over again, what could I put in my system to address those cross-cutting concerns? And the answer is not another layer, by the way, but we'll get to what it is in the future. But my commands look something like this. I accept a form post, and the bound object is going to be my real entity in the database. And by the way, this is an absolute horrible thing to do in NBC. You never want to do this, where I have to whitelist a set of properties in my system. A few years ago, the reason why I have to whitelist is because every single request variable is going to be attempted to be bound to my real data access or entity up model to be persisted in the database. A few years ago, there was a security bug in Rails found in which Rails would take request variables and then bind them, state your active record objects, and then persist them to the database. And any request variable that was found that happened to match something, whether I actually showed it on a form or not, would be bound up. So someone saw this bug and opened up a GitHub issue with the Ruby on Rails repository and said, hey, you have a security hole. You're just binding every single request variable. Someone could use this to maliciously add extra request parameters to do whatever they wanted. Well, I guess the Ruby on Rails team wasn't quite as quick to fix this issue as the developer liked. And so the person that found the issue also knew that GitHub was built on Ruby on Rails. So they decided what they would do was exploit this hole to make themselves an administrator of the project, open up a pull request to fix the issue, and then actually merge in the issue and close it. Now, the Rails team was not too happy about this, but it addressed the issue. So their solution for this was to use a form of white listing or black listing to say, I only want these form fields to be bound up to my active record object, or in this case, my entity model and entity framework. Now, one thing I love about programming is strings, especially when I have strings that refer to properties that are really good for refactoring. Because one thing that refactoring tools really do well is go through strings and figure out you're actually referring to a property. Now, that's not true. That's one thing to do horribly. Again, this is one of those things that if I have to remember to have the exact right fields, then I'm going to forget. This is one of the things that could easily become divergent from what the actual truth is behind my form. So if I make some change in my system where I'm now allowing them to edit some other piece of data on here, if I forget to include this here, that's going to be a very subtle bug that I only find when I actually run the application. No controller unit test is going to be able to find out that request variables aren't being bound correctly. If I just launch this controller up in a unit test and said, make sure that I can pass on a course, and I'll get saved correctly, well, that's not actually exercising the real framework behind the scenes that will go through request variables and model binding and filtering here to make sure everything gets bound correctly. So I wouldn't actually know if something worked correctly until I ran the system. A very bad thing to be. So what I'd like to do is build up concepts around both my queries and my commands in the system. So let's look first at how we might create queries. When I'm looking at my requests, just all the requests on my system that take in where all my gets in my system, I notice one pattern emerging. That's almost a very functional style that my user interface layer has, which I have some kind of input in the form of query string parameters or form variables. And then something handles those and then produces some output. So it's always this input going in and input going back out. What I'd like to do is represent those concepts, the inputs, the handling of the request, and the output as distinct things in my system. So I model this as some kind of query object that had the query input, something to handle the query, and then the query output. And I wanted to make those things completely divorced from anything in the user interface and just talked about data coming in and data coming out. So we built something to help do this. I copied and pasted several times and got to the point where this idea of request coming in and an object going out was simple enough that it created an open source project around it. So I built this open source tool called Mediator. Of course, this was during the time when it was fashionable to not have vowels all the time and capitalize letters. So that's why it's called Mediator. Because it just seems like that's the thing people do now. So in this open source library, we're able to model commands and queries as requests and request handlers. So going back to my controller action, what I first need to do to figure is figure out what my inputs are. So the inputs to whatever my handler is going to be, in this case, are going to be all of my query string parameters. All those pieces together, I can pull together and make it to a single request object that becomes my query input. So all those query parameters become properties on a query object. And the outputs are going to be everything that's now fed to the view. So this includes not only the view model thing that was created, but also anything that was built into my view bag. So taking everything that is an output to be able to be displayed or used somehow, I'm going to stick into a single object. So that means in my view, I need to go look to see what's actually being used there. I go to my view and see that I'm using these three properties to be able to be showing data on the screen. So I'm going to build a response object that models all of that data that I'm going to be displaying on the screen whatever form or fashion it might be used. So this result object is made distinct to that individual request. And what this is doing is ensuring that I'm not sharing any kind of logic or behavior across my individual requests So whatever happens, however crazy this page gets, its behavior and logic is confined to just these individual objects. This one, for example, shows a list of things. So I'm going to have a list of my student objects. In this case, I'm showing students on the screen. Now the naming of these objects, what I try to do is name them after the request of my system. So in this case, this is the student controller and the index action. So just as a convention, I'm naming it student index model. And then every single request will have some sort of model associated with it. Now the final part after I have my input and my output defined is actually handling that query request. And so this object is solely responsible for taking the input and building the output. And that's it. Now if I was in a more functional language, I would have to create a type around this. But because you're in C-sharp, I had to create a class to hold this concept. So this request handler takes the inputs of the query and returns the result. And whatever it has to do to build that up is inside the logic of that handler method. At this point, there's also no real reason for me to use any abstraction on my data access. I can go ahead and just use any framework directly because this class is just responsible for taking input and building the output. Any kind of abstraction on top of this is just waste. One of the things I like to do with abstractions in my system is to wait as long as possible until I put them in there and make the code itself prove that it needs the abstraction before I put something in. So even in A, I don't put in things like repositories or services or anything like that until the code tells me that it actually is net needed and not before. And so in this case, I didn't put a repository in because it didn't think I needed it and built the rest of the system without ever needing it. And until I need it, I'll put it in. But before then, I won't. The final piece here is building out the query result. And this is where for me, AutoMapper actually enters into the fold. I have a complex data entity model, whatever you want to call it, that has all these relationships and all these methods and all these ways to get around to all these different pieces. And what I'd like to do is have the same conceptual feel of a database view where I have a description of the projection of what I want to have, but not to have to go through the work for every single request creating an individual view. So what AutoMapper does for me here is it sees the input data model, the entity model. It sees the output model and will automatically build for me a select projection and link to build out the result that I want. So this project to page list replaces what I may have before as a link select projection that would get passed to the database as a select projection and SQL. So what happens here behind the scenes is the link select projection is created. It gets passed into my ORM and any framework. And any framework takes that select projection. It builds up a special SQL query just for that individual page. Now what's interesting about this is it has only the data that I need for that individual page. And on top of that, I don't have to do any sort of fetching or joining or anything like that. Because my select projection is navigating those relationships directly, the link provider knows how to take that select projection that navigates complex relationships and turn it to one SQL query that does all the joining for me. So let's look at a more complex example, because that one has paging and stuff, but most of my pages don't have that sort of stuff. The mind instead looks something like this. So this is the output of viewing details of an individual student at a university. It has regular data fields for the students. And then on top of that, it's going to tell me what courses that student is enrolled with. So if I was doing a regular link query just in any framework, and I was showing the real live students to be shown on the view, I would have to do things like fetching. And that includes syntax to say, make sure you grab those enrollments, because if you don't, as I loop through the enrollments, it's going to query and go back to the database for every single one. What I'd like to do is go in one shot, get all the data back and project it into this model, and now have to go back to the database for every single thing, nor do I want to have to instruct my ORM every single time I'm getting additional data to say, oh, and don't forget to get that other thing. So in this one, for example, the enrollments not only has the grade information on here, but it links to a course. And that course has the title information, and so I'd have to have a very wonky syntax to get all these includes in place. But what I do instead is I have one line here that says project to single or default async. That's not the interesting part. But project that student into my student model, and just with one single SQL query, get all that data all at once. So this is the query result that comes back. I cut off the other junk that's the kind of crazy entity framework SQL stuff. It does some really weird things. But the query plans are good, so who cares? And it pulls back just the fields that I have for that individual screen and nothing else. Now, each of those different objects, the enrollment and the course object, have a lot more data as part of it. But what I'm doing here is just pulling back only the pieces I actually need. This is why, for me, CQRS doesn't require a database view for every single thing, because I'm using these projections to have the same exact result. All right. So that's queries. We'll take the commands. Now, commands are interesting. Queries are pretty easy. They were very kind of simple. Everything's just input-output. Commands are where really I see a lot of business logic in place. So for these cases, I want to say, let's look at all the inputs for whatever I need to manipulate. And the outputs may or may not exist. Sometimes there is a result that comes out of executing command. Sometimes there is not. Most often there's not. So what are my inputs? Well, luckily, because I had to whitelist everything here, it's very easy to see what is only the data I need for this individual request. So in this case, it's that bind statement. Well, I still want to go back to the view to make sure I'm not missing anything. But this may be a good start. So I take those three properties that I'm building out and say, let's create an object that represents that request to do some thing in my system. So in this case, the command is to create a student. So I'll have a class that represents this request called student create command. I guess I kind of named it that was a little bit more fluent in nature. But I wanted to keep with the same naming convention of controller, action, and then whatever. In my systems, I create more task oriented user interfaces. The example I'm running from here, the Contessa University, is very crud in nature. So there's not a lot of commands that represent real business activities. But the systems I work with, it's more like invoice approve command, invoice reject command. And I'll have individual forms and individual links on my screens to do those individual actions. Handling command is also now pretty straightforward. I take the input. And in this case, because the object was really simple, I can now use Automapper to go the other way and just manipulate my data entity model with whatever information is coming in. Now, if it gets more complex than this, if I'm doing some other kind of data access or some kind of entity model, I could be using, I don't know, I could be using event sourcing, I could be using complex aggregate roots. I don't care what I'm using here at this point. Any kind of logic that is around this request is going to be limited to this one file. So if I need to refactor this, I need to break out on something else, it's all in this one individual file. And again, no repositories because it's just not needed. Now, there's some pieces missing here that I just skipped. In my controller earlier, we saw that there was basically one line of real business logic which was creating a student and then saving it. But there's a lot of other junk going on with validation and things not found and what to do in those cases. So I still have the issue of what I need to worry about of the cross-cutting concerns in my system. These cross-cutting concerns are the kinds of code I see copied and pasted in method after method. But there's no real easy way for us to abstract those things out into some kind of service layer. Because again, once I abstract this out into just a lower level abstraction, I still am not solving the actual problem of addressing these cross-cutting concerns. So I see this in my controllers a lot. If model state is valid, then do something. If model state is valid, then do something. Model state is valid. And this application, I saw this model state is valid. I looked just looked at how many references are the words who is valid. And there's something like 40 references to that property across my entire system. Which means that if I ever need to extend the functionality around validation, I have to go to 40 different places. This is a relatively small system. And one recent application that we had this style of architecture, we had something on the order of 120 controllers and about 500 actions. And there's no way I could change the cross-cutting concern of validation or any other thing like that if I have to go to 100 of the places to try to modify that. So what I want to do is shift how I think about validation. And currently, this application is not validating individual requests, but it's validating the entity as a whole. So make some changes on the data entity and then validate that the entity is in a good state. But when I'm dealing with my business, I don't ever validate entities. I validate requests. So the other nice thing about having a model built around queries and commands is that instead of my validation centering around entities after the fact, after they've been mutated into bad state, I can instead say, let's wait and let's not make any changes to my model until I've actually validated the request. And so my validation now centers around requests, not entities. In this case, I'm using a library called fluentvalidation who builds validation around objects. And so in this case, I build validators around every request in my system that needs some sort of validation. So I've got whatever validation is needed for creating a student is right here. Now another nice thing about this is if validation is different for different kinds of requests, it's limited to these individual validation classes. So if creating a student has different validation than editing something, that's OK. I see this in systems a lot with legacy data that say, we're now requiring a field. But I can't put that validation on the entity itself because there's consuming existing data that doesn't have that information in there. And I can't go backfill data. But in this case, because I have validation around individual requests, I can say, well, going forward, students that need it are created now have this validation. But for existing students, I could have different validation for whatever those cases may be. I also moved away from attribute-based validation. Sometimes my validation becomes a little more complex, like make sure students have unique names or unique identification numbers. Because I'm centering my validation around classes, this type can actually take an entity framework DB context and then do something with it. So if I needed to query the database to do something, I could have it all in here as well. So I've addressed the problem of validating entities, but I still have that isModelStateValid littered across my application. So I haven't actually solved that problem quite yet. To solve this one, we need to take a little bit outside the box about how our validation flow typically works. So in our normal validation flow, we have some sort of post that makes a request to the server. The server says, is this valid or not? And then if it's not valid, it returns a 400 bad request HTTP status code, as well as the HTML page itself that says, here's all new HTML, both all my validations errors inside of it. If it is valid, then I'll do work, persist my changes to the database, and then I'll do an issue of redirect to say, go ahead and redirect to this new page. Now this is assuming that I've also made the same choice of not building on top of single page application frameworks, and just done plain old post redirect get architecture. Now the downside to this approach is that if something goes wrong on the server, there's some sort of validation error, I have to have an entirely new HTML page to show the user that has to retain the state of whatever they put in there before, including things like drop down lists, and check boxes, and radio buttons, and all sorts of other things, that are actually quite a difficult to recreate if the only thing I'm working with is that very simple post data that came up. So what I'd like to do is modify my validation flow to optimize the success path, and if something goes wrong, then do something a little bit different. So in my modified validation flow, I'm going to actually hijack whatever post that happened in the server. So the user will click a button, their request gets hijacked with Ajax, I issue the post to the server, and then the server does the validation based on just adjacent data. If something goes wrong, and the reform is invalid, what I'll do instead of returning an entirely new set of HTML, I'll instead only return an object that represents the validation errors. So here's the things that are invalid, and here's the property names for those things that can be bound up. So on my Ajax post, when I get the result back, I'll take that result and bind it directly to the screen, because I haven't actually refreshed the page and gotten any new HTML back. So I don't have to go wipe the entire screen, forget everything you've done, and then re-bind everything with the validation errors. I simply take those validation errors and now just show them on the screen. The success case looks exactly the same. I'll just do work, make some change to this database, and then do my normal redirect. So I'll do this now with a cross-cutting abstraction that actually exists in my MVC framework. So in this case, I'm using an action filter, which gets executed in every single request. And if I find that my model state is not valid, then what I'll do is I'll take, actually in this case, I'll just take the raw model state from the MVC framework, I'll serialize it to JSON, and return that as the content to the Ajax post on the browser side. The browser side will receive that, see that it's a 400 bad request, and then just bind that model straight directly to the form variables without having to refresh any of the other HTML on the screen. If things are successful, then it just goes on with the rest of the request. So my controllers no longer have if model state is valid anywhere. I've taken care of validation, that is, the validation flow exactly once, and a cross-cutting layer, and not have to worry about it really ever again. So the final piece of the puzzle is I've now built everything into vertical slices with requests modeled as queries and commands, but I've still got everything scattered across my entire solution, organized by layer, not by feature. So what I want to do is flip this on his head and not organize by layer, but organize by feature. If I look at when I need to make a change to my system, I've got all these different folders for all these different cross-cutting concerns, and when I need to do something like make a new page in my system, I'm going to this folder, I'm going to this folder, I'm going to this folder, I'm going to this folder, probably three or four others to make this change in my system. And it becomes really difficult to follow what's going on when I'm having to go across my whole solution to make any sort of change. So what I want to do is collapse all these different things together, all these different pieces that I need to create for an individual request on my system and gather them in one place. And then what I'm going to do this is I'm going to collapse everything down into folders and namespaces based on those activities. So in this case, I'm creating a features namespace and then another namespace based on whatever area feature that that request belongs to. In this case, I still just defaulted to the controller name, whatever that controller name is going to be, whatever my folder is for my features. And then inside of that, I'm going to create a class that represents whatever thing you're trying to do there. In this case, it's creating a student. And then nested inside that class are all the different things that relate to that request. So in this case, I have the command object that represents whatever thing I'm trying to do. I have whatever validation that is whatever validation deals with that request. And then handling that request is now a handler inside of this create class. Now I could have done this with a namespace, but I find that it's a little bit easier just to have everything in one file, that whenever I'm making a change to the system, everything I need to do is right here. And I don't have to go jump around anywhere. So now I can have entire features be collapsed into one file. So in this case, I have a query that shows the initial get request for editing something. I have validation around my query. I have the command that represents the post. And then I have validation around the post. And then I have the handlers for both my query and my command. So I, as a developer, when I'm creating a new feature in my system, everything's in one spot. I'm going to go even one step further and have everything related to that feature, not just code, but also any kind of scripts or templates also be organized alongside them as well. So inside of this, I've got my edit C sharp code. I've got my edit view. And if there's any JavaScript associated with this, I have that alongside as well. So I want to go see everything there is to do about a certain feature. I've got everything right together as close as possible. And you're starting to see this more and more on client site frameworks as well. For example, React is embracing this concept as well. And instead of having things spread across services and factories and factory service providers and blah, blah, blah, we have everything together that has to deal with one single component. And this is just another implementation of that sort of concept. So to achieve this, it's really just renaming the views folder to features. And then making a little modification in my view engine to be able to redirect those requests to go to the views folder, the features folder. So that's how I can then locate the views. And the final piece then is in my JavaScript side, I want to have individual modules for every single page. I don't want to reuse my JavaScript across different screens. If there's something that needs to be reused, I'll extract that and put it to something that's not specific to any of my features. And so every single JavaScript file is now an individual required JS module per slice. And so this part right here is taking the, I want to have on every single page that loads up one single block that says, go ahead and fetch my required module for this individual page. And instead of me copying that pasting into multiple views, I have one spot that pulls out whatever control I'm looking at, whatever action I'm on, and then goes into the features folder and loads up that individual JavaScript file for that individual page, and then builds and names a required JS module around that. So if I want to go see all the JavaScript that is related to this one page, it's again in one single file, along side, directly alongside everything else that has to do with that one request. So when I get to the end and look back at what my controller became, we're moving all these layers, it becomes now pretty simple. It's really just taking in requests and via mediator sending them out to the actual handlers that is that domain specific handling. But otherwise, this is just going to be UI logic. And you could look at this and say, well, why do I need a controller in the first place? Well, I still need something to satisfy, in this case, routes in MVC. And I've also found that there are cases where I do have to deviate from this model. For example, if I'm doing something like file uploads, that's really crazy MVC logic that does require me to get to the bare metal of MVC itself and the actual HTTP request. So in that case, I didn't go to this normal mediator request, so I still need a controller to represent that's handoff between the UI and my actual domain objects, or my actual domain layer. My end architecture now looks like this. I've got a large number of features that are heavily isolated from each other, that I don't have any sort of shared responsibility between those. I have some things that are cross-cutting concerns, validation, authentication, authorization, logging, any sort of things like that. Those go across all the different features, but are not built on top of different layers. These are just built as cross-cutting concerns. And the final piece is then some sort of persistence that I typically have to share across my whole application anyway. But again, this is not domain specific or not business specific. It's just another tool I'm using across all the layers in my system. So one thing I found about this is these top pieces are all domain agnostic. These are pieces that I can take from project to project, and also very good cases for me to either build common shared libraries, open source projects, or components that I share across the different solutions I have in my company. These are the pieces that are actually unique to my system, and I don't try to share across different pieces. So earlier when I said we were able to switch from Petapoco to Enhybernate to Entity Framework, this is really easier for us to do, because I could take one individual feature size at a time, migrate it, test it, make sure it works, and then move on to the next feature without having a really long-lived branch to the side that doesn't do this really big bang refactoring. I don't actually care the technology used in each of these feature sizes either. They could be using store procedures. I mean, if you're crazy. They could be using micro-RMS. They could be using anything. I don't even care, because all the logic and behavior associated with each individual request is contained in that one set of request files, then those concerns don't leak across the different features in my system. I don't even worry about domain or design patterns anymore. I don't worry about factories and strategies. I mean, these feature folders, these feature sizes, can be as procedural as you could possibly be, because who cares at this point? Just shovel the stuff in a file and just have it in one spot. If it does get crazy, I can always refactor in the future, but I'd actually prefer to have everything in one spot as opposed to trying to break it out into multiple abstractions. So let's do a solid roundup to see how our architecture now deals and addresses solid. So looking at single responsibility principle, now that I have one class per feature concept, requests, results, commands, validators, I have now each class responsible for one exact thing and only one thing. On open-close principle, I extend my application through cross-cutting concerns. In this case, it would be things like the action filters, extra results, but I don't do those things in the actual meat of my application. I do that in horizontal slices that go across all the different features in my system. The L just kind of goes away. I don't have inheritance anymore, so I don't have to worry about things getting substituted for other things. I don't have really wonky repository hierarchies or really crazy service hierarchies or base controller classes. All that kind of goes away if I just don't do inheritance. And instead, focus on individual classes for individual responsibilities. And then this never comes up for me really ever again. And the interface segregation principle, because every single class is responsible for one individual thing and queries are separated from commands, I don't have to worry about having multiple people changing one individual type to do multiple different things. Every single request has an individual class, and so it only has one reason to change. And finally, on the dependency inversion principle, or whatever it is, the thing that requires IOC containers, I save this for actual real external dependencies. So real dependencies like I have to interact with some third-party web service or some third-party components. This is something for things I don't write in my system. So the only thing we saw so far in our system that I needed a true dependency for was that entity framework DB context. I want to have something else manage the creation of that and management of that and not have that inside my type. So what I see is that the number of dependencies in my system are greatly reduced because they don't have things like services and repositories to do with anymore. It's just the actual meat of what's going on in my system and nothing else. I do have occasions where I have some things that are injected that I actually build, but these are things that are wrapping those things I can't control. For example, I need to know who the current user is, and instead of me doing something like going to the thread, current user, whatever, then I'll have something like an eye user context that can be filled in and supplied by something else as well. So thank you, everyone, for attending my solid architecture of Slices Not Layers, and I hope you join me in the anti-crap movement going forward. Thank you very much. We do have five minutes for questions. If anyone has anything, yes? Yeah, so the question is, I showed a CRUD application, which I admitted I was doing a strawman at the beginning, so this is being fully up front there. So what happens when things actually get complex? So I find in those cases I let those handlers themselves tell me which direction to go. This becomes like true sort of TDD style, where as things get more complex in that handler, I can take that behavior and push it down into my domain objects. So my domain objects no longer become just sort of dumb entity models that are just getting stuff in and out of the database, but I push that down. So if, for example, I was doing something like event sourcing, I would see that handler just now hand off that request straight to my aggregate route and have that do all the behavior, and then my handler itself is now just doing basically the handoff between data access and stuff in the actual domain. What is the domain object today? So those domain objects don't live in the future folders because those are one of those cross-cutting things I have in my system. Any other questions? So this full example is of my GitHub, github.com.jbogaard, and there's a Contoso University where we can find an actual running example of everything you saw here. So thanks, everyone, again.
 All right, good morning everyone.  Or, no, yes, it's still morning.  Okay.  My name is Jimmy.  I wanted to talk a little bit today about crappy architecture  and good architecture, especially in the face of all  these microservices talks.  I wanted to embrace the monolith and show an architecture  that it could actually scale with complexity.  I have a feeling that a lot of the people that are doing  microservices are doing this because they're already  building on top of kind of crappy platforms to begin with,  like Ruby on Rails and Node.  So with architectures that do actually scale, we can actually  get a pretty long way to building at a nice system.  So you can find me on Twitter at atjbogards.  My GitHub is also the same github.com.  Everything that we see today in all my open source projects  are going to be on there.  So there's a presentations repository.  You can find everything here, as well as my other  presentations.  I blog on those techies, jimmybogard.listtechies.com.  And that's about it.  So let's start the first thing.  I want to talk about this.  Crap.  So most of what I do in real development is I work with  existing legacy systems and try to build better systems from  those ashes of those horrible, horrible systems.  And a lot of what I see of systems today are these big  balls of mud.  And they came out not because any developer had an  intention of creating this big pile of crap, but it just  kind of happened over time.  And a lot of what I see even on smaller systems is an  assumption that some kind of layered architecture will  somehow provide a better system in the end.  But what I found is that those layers don't actually  produce anything better in the end.  They just produce kind of a layered pile of crap and not  actually anything good.  So a few weeks ago, I had the privilege of reviewing some  code from a customer of mine.  This is a customer that their primary domain was  manufacturing, and they weren't really coders.  They knew how to build things.  They didn't know how to really write code and say they would  hire other people to come and write code for them.  What this meant, though, is they didn't really have any  expertise in understanding, looking at code whether it was  good or bad.  All they knew is that their deadlines were missed.  There were a lot of bugs in the system, and they wanted to  know why.  So they asked me to come and take a look and say, it's not a  very complex system.  Can you tell us why they're missing deadlines?  Why there are so many bugs?  So looking at this application, it's clear to me that the  inmates were definitely running the asylum.  This is an app with a very small footprint.  There were four screens, just four screens.  And the purpose of the system was the company was moving off  of a set of bespoke systems into one centralized system for  some of their manufacturing data.  And the point of this system was really just to take the data  out of the old systems and cleanse it, so to speak, and  put it into their new system.  And that was literally it, just like screens to modify data  and then some basic workflow to say, I have approved this  data and now I can go on to the central system.  And that was it, just like few screens, the home screen, and  that was it.  But somehow, with the system, there's just a few tables and  workflow, the developers managed to create a code base  with 20,000 lines of code.  And on the one hand, I want to applaud them and say, well,  that's actually pretty hard to do to create such an  insanely complex system for something so  simple, so kudos to you for that.  And as well as, let's see, I had two solutions and 12  projects to do this very, very simple thing.  It was one of the most insane things I've ever seen.  So I wanted to walk through real quick what their  architecture currently was.  So it first started out, this is a system built in the last  six months, first started out with web forms, which red  flag number one, if you're building a new system today  and you're using web forms, you should probably just quit.  Just stop doing anything development-wise.  You shouldn't be using web forms at all.  So from the ASPX page, there was the code behind.  Now what I found was that with all those 20,000 lines of  code, most of it actually resided in these two parts, the  ASPX page and the code behind.  And the ASPX page would have, in the middle of there's like  one, the other three pages were just like a login screen and  a home screen, which you click the link to go to this screen.  There's about 3,000 lines of code in the ASPX page, and  then about another 3,000 or 4,000 lines of code in the code  behind.  So with all this layers they had put in here, these 12  projects, they didn't actually solve their complexity  problem, they just shoved it into exactly two files.  So from there, the request hit a service proxy, which was  another Visual Studio project to wrap WCF, because what WCF  needs is more abstraction.  From there, it hit the actual WCF service proxy.  And this is where we switched solutions.  So now I was in the UI project, now I have to go to the  service, the UI solution, now I have to go to the service  solution.  I did ask the business, so why are you guys creating web  services for this project?  They have to expose their capabilities to someone else?  No, they didn't even know what a web service was.  So again, just complete over-engineering.  So from here, we hit the actual WCF service.  And from the WCF service, we hit the actual business  application layer.  I don't really know what the a actually stood for.  In the name states, it said BAL, so I can just assume it's  business application layer.  I don't know, has anyone had any guesses for what the a stood  for besides that?  Abstraction, sure, why not?  Because we need more of that.  OK, so the business abstraction layer, architecture layer,  application layer, whatever a stood for, it's lost to the  ages because we deleted this repository soon after we met  these folks.  From there, the business, the bow, whatever that means, hit  the dow, which could only mean data access layer or data  application layer or data abstraction layer.  I don't know what.  One of those three things.  And looking at the code from each of these new layers, the  service proxy, the BAL and the DAL, the entirety of those  code bases just consisted of interfaces, then classes.  And then inside those classes, each of the methods would be  to do something like approve material data or  something like that.  And inside the method, there was one line of code that was  actually real stuff, and that line of code would just call  into the next layer down.  And then surrounding that was a try catch block, which caught  whatever exception it might be, wrap it in a new exception  based on that layer, and then throw that exception and maybe  do some logging as well.  Looking across the dozens of these service classes to see  what, if there's any business logic in them, there was none.  It was literally try catch, wrap, throw again.  By the way, this whole talk is a complete straw man.  I know you're probably not creating these  architectures, right?  OK.  OK, so from the data access layer, which didn't do  actually data access, it was still using ADO.NET, raw just  like bare bones ADO.NET.  And from there, it actually called a stored procedure  where the actual data access logic lied.  Funny enough, the stored procedure and everything going down  were regular kind of DTOs, but on the way up, they decided to  use data sets for everything, which I found just  absolutely hilarious.  So I actually built a tool called AutoMapper, which  enables some of these architectures.  And so what I'm trying to do with this talk is to repent for  some of the sins of people using my tool for very evil and  nefarious purposes.  When I first started out in.NET, this was when I first  graduated university around the early 2000s.  I was desperate to see how people actually built systems.  I went to school not for computer science or anything  like that.  I went to school for computer engineering.  So I didn't really get any instruction from the university  about how to build actual applications.  I knew about how to build things that made robots go, but  nothing about actual systems.  So I looked at the documentation and the guidance at the  time to see how do people really build systems these  days.  And naturally, my first result that came up was MSDN  documentation for Microsoft about how to build systems  with good architecture.  Now, the picture they drew was something like this.  I have a UI layer, a business logic layer, data access  layer, and then finally the database.  Now, this should be warning number one.  Don't take advice from people about architectures that  don't actually build real systems.  They just write about them.  If they haven't actually built systems, then they're  probably giving lousy advice.  And this is what the advice that I was given early on was,  to build everything in layers.  Now, that worked OK for small systems that I worked with.  But my first real job and real product I had to work with, I  saw that this architecture wouldn't scale.  So at the time, the domain-driven design book just  came out, and people were really latching onto this as a way  to manage complex systems.  So this was replaced by a much better architecture, the  domain-driven-desire style interior architecture, which  is obviously much better.  Instead of my business logic layer, I have domain objects.  And instead of a data access layer, I have repository.  So it was actually pretty easy to move from an interior style  architecture to domain-driven design.  You really just have to rename some files.  And now you're doing domain-driven design.  And when I built these systems, I would organize  everything in my system by its layer.  So if I had something that was person, and by the way, this  is another huge warning.  If you have something in your system called person, you've  probably done something wrong in your modeling, as well as  something called user.  No one has a title of user or title of person in your  company, so you should probably have a thing called  person.  And I would build things around this by its layer.  So I'd have a person class that had a person data in it, a  person controller for MVC stuff, then a person service,  which is really where all the business logic lied, because  I couldn't figure out how to put things in the actual domain  layer, and then finally a person repository, which again was  really just a gateway on top of the database.  And so at the time, when it came time to actually building  out my repository, I wound up looking something like this.  Now this is actual code that I wrote, so I have no one to  blame but myself on this when I can blame developers  somewhere else.  I built something like this for my repository.  And it's actually cut off at the bottom, because there's  actually too many methods for you to fit in the screen.  And so this repository had methods for basically every  single kind of data access thing I would actually have in  the system.  And I might have something simple like get some person  by its person ID.  But if I need to do extra data access or extra ORM fetching  or something like that, well, I couldn't just use that.  I had to actually build new methods for every style of  thing or every kind of thing I need to fetch out.  So I'd start to have more methods for all the different  ways that actually query and on and on and on and on.  So how can I dig myself out of this?  The first thing I would need to do is to characterize what  I'm actually doing in my application.  And this is where I find that the architecture of the web  lends itself well to actually good back in architecture.  The web itself is very, very simple.  I have basically two kinds of requests in my system.  I'm going to ignore the hipster ones, the put, patch,  delete those ones, and just focus on the ones that people  actually use, get and post.  And these two things are very, very simple.  I use gets for reads, and I use posts for writes.  Gits are nice because they're safe and then they don't have  side effects.  And their item potent means I can call them over and over  again, and the result is the same as if I called it once.  The effect of emangling the definition, that's good enough.  Post is for everything else.  So if I'm mutating data, doing something, or modifying  something in the server, I use posts.  And in that case, it's not guaranteed to be safe and not  guaranteed to be item-poded.  Now it could be, but there's just no guarantees around that.  So looking at these two things, I can see that my  gets are queries and my posts are commands.  So queries to do something or to ask for some data, and then  a command to then make some modification to the data and  go on with my day.  Looking at my systems that I built, if I look in my  application, the way I've organized and the way I built  it out, I've got all these layers for every kind of  thing in my system.  And I only have four layers here, but typically I see much  more than that.  I might have models, view models, services, all these  different folders for all these different layers.  When it comes time to actually building something in the  system, I don't build something across a layer.  I'll build things down layers.  So if I'm going to add a new screen to my system, I'm going  to make a change to the user interface, create a new view  file, create a new controller.  I may have to make changes to some data objects.  I don't have repositories anymore, but we'll get to that.  And so what I'm doing here is making changes not across a  layer, but down a layer.  So every new feature I have in my system, something like  view and approve invoices.  I'm making changes to every single layer.  Approving an invoice, again, every single layer, or  rejecting an invoice.  I'm having to touch all these different places down the  line.  And typically in my solutions, I'm jumping all around to go  ahead and make these changes.  I often find that with these layered architectures, this is  where a lot of the source of merge conflicts comes into  play, because I'm modifying these objects that have  changes across all these different layers.  For example, the repository here.  For each of those three vertical yellow boxes, I'm  making some change in that repository to add some  functionality for whatever that is.  So if more than one person is having to change these files  across these layers, that's going to be running into  conflicts.  So about five years ago, I can't take credit for it, but  maybe I will anyway.  There's a great pattern introduced that built on top  of the idea of command query separation and said, OK, how  about instead of us just talking about methods where I  have commands and queries, how about when we talk about  objects, where I have two different models for commands  and queries as opposed to just one?  And really this is coming around and looking at things  like repositories and saying, well, we thought that  repositories, not kind of pattern, was there to help be a  good example of something in solid, that it was a single  responsibility because it did data access.  The really big one, though, that I missed was the I in  solid, I being interface segregation principle.  The idea that if I need to make a, I have no idea what ISP  means, I just know that repository violates it  somehow.  So the idea is that in my repository, if I look back at  the one that had all those different methods on it, for  any given one of these vertical slices, I'm only using one  of those methods in each different use case.  You'd have just shoved them all in one file as if they have  something to do with each other.  But in reality, they don't.  Recently, about a year ago, I guess now, I was part of a  project where we were moving ORMs.  I know that's something people never, ever do as a code base  change ORMs, but it's something that we had to do.  And for us, if I was using the abstraction of the  repository, we would have never been able to make that  switch because the repository was coupled to whatever ORM I  was using underneath the covers.  But with a more vertical slice architecture, we were actually  able to change our ORMs we were using.  Originally, you were using NPoco, which is a micro-ORM,  went to Inhybernate, which is a complete other side of the  spectrum, and finally, we went to Entity Framework, which was  kind of in the middle between those two choices.  And we made these changes in the course of about two or  three days that we would never have been able to do with  this style of architecture of layers.  So it all came back for us to CQRS, where we built two  models where once there was one.  Now, if anyone who was in Udi's talk yesterday on CQRS,  this is the style of CQRS I'm talking about.  Not the asynchronous, invented, like, two databases  ridiculously architecture version, but where I'm just  taking one object and splitting it into two, and that's it.  So if I go back and look at my repository, in this  repository, I have all these methods that are only used in  one specific use case.  So there's really no reason for them to live together.  If they don't change together, then they  shouldn't live together.  When I look at this, I also see a pattern emerging in that  I have a set of methods that describe some kind of distinct  query for a specific use case, and then I may have things in  there for specific commands, like remove updated flag from  all people, which is probably a bad idea to do anyway, but  there it is.  OK, so with this crazy layered architecture, I want to get  to someplace better.  The first thing I have to do is rewind all those  abstractions.  Unfortunately, when you have a very poorly  architected system, it's difficult to refactor  incrementally to something better.  Sometimes you have to just take away all the crap and put  everything in one spot, and then you can go out and then  put something else on top of it.  So my first step was just to collapse all the layers and  remove any kind of insanity-errant system.  So I looked at my system.  This is MVC.  And I know that GETs are basically queries and posts  or commands.  So if I start to look at those different controller actions  and see what they're actually doing, I can start to see if  there's any sort of concept that emerges from these two  styles of usage, queries and commands.  So moving all those repositories, doing the heinous  thing of just doing data access directly in my  controller, I know it's horrible, using it directly, I  start to look at, OK, what are these things doing?  This is a more complex query in which I actually took this  from Microsoft's new example on how to build systems,  Contoso University, which is also another great example  of how not to build systems.  And I'm trying to take this and move it to some kind of  better architecture.  So inside the controller action, I have a mix of  concerns going on.  I have some data access going on in which I'm going and  querying entity framework for stuff.  Then I'm putting stuff into View Bag, which is just a data  dictionary for storing stuff for views.  And then finally, I'm telling MVC to go ahead and show a  view by passing it a view model.  This is also another red flag I saw mixing the data  dictionary style of MVC and the strongly-type view  side of MVC.  If you're doing both of those things, it's really confusing.  So this was a simple version.  So this is a more complex query.  I might have a more simple version that looks something  like this, where it's literally one line of code.  There is one thing that is a little bit interesting here.  And that I have, in this case, I'm showing a list of  departments, but I have this include method at the end.  This include method says, I want you to go ahead and fetch  that additional data.  And there's one thing that developers do really well.  It's managing ORM fetching.  Oh, no, I'm sorry.  What we do horribly is manage ORM fetching.  This is one of those things that I see as the shining  example of why people don't like ORMs.  It's because they have to do crap like this, fetching some  additional data because they have to use it sometime later.  Now, in ORMs, it's actually relatively easy for us to go  ahead and navigate associations on our data access  objects or in any models, whatever you want to call them,  and then have the ORM go ahead and silently behind the  scenes fetch stuff, which is actually a very horrible thing  to do, to go and let the ORM just magically do queries  behind the scenes.  So instead of doing that, we have to kind of remember that,  oh, by the way, we're using this other object over here, so  go ahead and fetch that.  If we use anything else on those objects, we'll have to go  back and change this to make sure we also include and  fetch that additional data.  Again, if there's something I have to remember to do, I'm  going to forget.  So I'd rather build on top of an architecture that forces me  to be explicit about what I need.  Some of my queries could be a little bit more complex in the  actual logic they're doing in the controller action.  In this one, for example, whenever I'm modifying  information, there's still a git that has to be made that  shows the form, and then there's a post on the other side  to actually modify the data.  So in the git case, there's only a very small piece that's  doing the actual data access.  The rest of it is just other junk I'm using to take care of  other kind of edge cases.  So in this case, if they don't supply an ID, I need to  return a bad request.  Results, if the actual object is in file, so they give me an  ID, but the thing isn't in the database, then I return yet  another thing.  And then this is the kind of code that I see copy and  pasted all over the application.  So this is another thing I'd like to address is to figure  out when I have these things that I see copied and pasted  over and over again, what could I put in my system to  address those cross-cutting concerns?  And the answer is not another layer, by the way, but we'll  get to what it is in the future.  But my commands look something like this.  I accept a form post, and the bound object is going to be  my real entity in the database.  And by the way, this is an absolute horrible thing to  do in NBC.  You never want to do this, where I have to whitelist a set  of properties in my system.  A few years ago, the reason why I have to whitelist is  because every single request variable is going to be  attempted to be bound to my real data access or entity  up model to be persisted in the database.  A few years ago, there was a security bug in Rails found  in which Rails would take request variables and then  bind them, state your active record objects, and then  persist them to the database.  And any request variable that was found that happened to  match something, whether I actually showed it on a form  or not, would be bound up.  So someone saw this bug and opened up a GitHub issue with  the Ruby on Rails repository and said, hey, you have a  security hole.  You're just binding every single request variable.  Someone could use this to maliciously add extra request  parameters to do whatever they wanted.  Well, I guess the Ruby on Rails team wasn't quite as quick  to fix this issue as the developer liked.  And so the person that found the issue also knew that  GitHub was built on Ruby on Rails.  So they decided what they would do was exploit this hole to  make themselves an administrator of the project,  open up a pull request to fix the issue, and then actually  merge in the issue and close it.  Now, the Rails team was not too happy about this, but it  addressed the issue.  So their solution for this was to use a form of white  listing or black listing to say, I only want these form  fields to be bound up to my active record object, or in  this case, my entity model and entity framework.  Now, one thing I love about programming is strings,  especially when I have strings that refer to properties  that are really good for refactoring.  Because one thing that refactoring tools really do  well is go through strings and figure out you're actually  referring to a property.  Now, that's not true.  That's one thing to do horribly.  Again, this is one of those things that if I have to  remember to have the exact right fields, then I'm going  to forget.  This is one of the things that could easily become divergent  from what the actual truth is behind my form.  So if I make some change in my system where I'm now allowing  them to edit some other piece of data on here, if I forget  to include this here, that's going to be a very subtle  bug that I only find when I actually run the application.  No controller unit test is going to be able to find out  that request variables aren't being bound correctly.  If I just launch this controller up in a unit test and  said, make sure that I can pass on a course, and I'll get  saved correctly, well, that's not actually exercising the  real framework behind the scenes that will go through  request variables and model binding and filtering here to  make sure everything gets bound correctly.  So I wouldn't actually know if something worked correctly  until I ran the system.  A very bad thing to be.  So what I'd like to do is build up concepts around both my  queries and my commands in the system.  So let's look first at how we might create queries.  When I'm looking at my requests, just all the requests on  my system that take in where all my gets in my system, I  notice one pattern emerging.  That's almost a very functional style that my user  interface layer has, which I have some kind of input in the  form of query string parameters or form variables.  And then something handles those and then produces some  output.  So it's always this input going in and  input going back out.  What I'd like to do is represent those concepts, the  inputs, the handling of the request, and the output as  distinct things in my system.  So I model this as some kind of query object that had the  query input, something to handle the query, and then the  query output.  And I wanted to make those things completely divorced  from anything in the user interface and just talked  about data coming in and data coming out.  So we built something to help do this.  I copied and pasted several times and got to the point  where this idea of request coming in and an object going  out was simple enough that it created an open source  project around it.  So I built this open source tool called Mediator.  Of course, this was during the time when it was fashionable  to not have vowels all the time and capitalize letters.  So that's why it's called Mediator.  Because it just seems like that's the thing people do now.  So in this open source library, we're able to model  commands and queries as requests and request handlers.  So going back to my controller action, what I first need to  do to figure is figure out what my inputs are.  So the inputs to whatever my handler is going to be, in this  case, are going to be all of my query string parameters.  All those pieces together, I can pull together and make it  to a single request object that becomes my query input.  So all those query parameters become properties on a query  object.  And the outputs are going to be everything that's now fed to  the view.  So this includes not only the view model thing that was  created, but also anything that was built into my view bag.  So taking everything that is an output to be able to be  displayed or used somehow, I'm going to stick  into a single object.  So that means in my view, I need to go look to see what's  actually being used there.  I go to my view and see that I'm using these three  properties to be able to be showing data on the screen.  So I'm going to build a response object that models all  of that data that I'm going to be displaying on the screen  whatever form or fashion it might be used.  So this result object is made distinct to that  individual request.  And what this is doing is ensuring that I'm not sharing  any kind of logic or behavior across my individual requests  So whatever happens, however crazy this page gets, its  behavior and logic is confined to just these  individual objects.  This one, for example, shows a list of things.  So I'm going to have a list of my student objects.  In this case, I'm showing students on the screen.  Now the naming of these objects, what I try to do is  name them after the request of my system.  So in this case, this is the student controller and the  index action.  So just as a convention, I'm naming it student index model.  And then every single request will have some sort of model  associated with it.  Now the final part after I have my input and my output  defined is actually handling that query request.  And so this object is solely responsible for taking the  input and building the output.  And that's it.  Now if I was in a more functional language, I would  have to create a type around this.  But because you're in C-sharp, I had to create a class to  hold this concept.  So this request handler takes the inputs of the query and  returns the result.  And whatever it has to do to build that up is inside the  logic of that handler method.  At this point, there's also no real reason for me to use any  abstraction on my data access.  I can go ahead and just use any framework directly because  this class is just responsible for taking input and  building the output.  Any kind of abstraction on top of this is just waste.  One of the things I like to do with abstractions in my system  is to wait as long as possible until I put them in there and  make the code itself prove that it needs the abstraction  before I put something in.  So even in A, I don't put in things like repositories or  services or anything like that until the code tells me that  it actually is net needed and not before.  And so in this case, I didn't put a repository in because it  didn't think I needed it and built the rest of the system  without ever needing it.  And until I need it, I'll put it in.  But before then, I won't.  The final piece here is building out the query result.  And this is where for me, AutoMapper actually  enters into the fold.  I have a complex data entity model, whatever you want to  call it, that has all these relationships and all these  methods and all these ways to get around to all these  different pieces.  And what I'd like to do is have the same conceptual feel of a  database view where I have a description of the projection  of what I want to have, but not to have to go through the  work for every single request creating an individual view.  So what AutoMapper does for me here is it sees the input data  model, the entity model.  It sees the output model and will automatically build for me  a select projection and link to build out the result that I  want.  So this project to page list replaces what I may have  before as a link select projection that would get  passed to the database as a select projection and SQL.  So what happens here behind the scenes is the link select  projection is created.  It gets passed into my ORM and any framework.  And any framework takes that select projection.  It builds up a special SQL query just for that  individual page.  Now what's interesting about this is it has only the data  that I need for that individual page.  And on top of that, I don't have to do any sort of  fetching or joining or anything like that.  Because my select projection is navigating those  relationships directly, the link provider knows how to take  that select projection that navigates complex  relationships and turn it to one SQL query that does all  the joining for me.  So let's look at a more complex example, because that one  has paging and stuff, but most of my pages don't have that  sort of stuff.  The mind instead looks something like this.  So this is the output of viewing details of an  individual student at a university.  It has regular data fields for the students.  And then on top of that, it's going to tell me what courses  that student is enrolled with.  So if I was doing a regular link query just in any  framework, and I was showing the real live students to be  shown on the view, I would have to do things like fetching.  And that includes syntax to say, make sure you grab those  enrollments, because if you don't, as I loop through the  enrollments, it's going to query and go back to the  database for every single one.  What I'd like to do is go in one shot, get all the data back  and project it into this model, and now have to go back to  the database for every single thing, nor do I want to have  to instruct my ORM every single time I'm getting  additional data to say, oh, and don't forget to get that  other thing.  So in this one, for example, the enrollments not only has  the grade information on here, but it links to a course.  And that course has the title information, and so I'd have  to have a very wonky syntax to get all these  includes in place.  But what I do instead is I have one line here that says  project to single or default async.  That's not the interesting part.  But project that student into my student model, and just  with one single SQL query, get all that data all at once.  So this is the query result that comes back.  I cut off the other junk that's the kind of crazy entity  framework SQL stuff.  It does some really weird things.  But the query plans are good, so who cares?  And it pulls back just the fields that I have for that  individual screen and nothing else.  Now, each of those different objects, the enrollment and  the course object, have a lot more data as part of it.  But what I'm doing here is just pulling back only the  pieces I actually need.  This is why, for me, CQRS doesn't require a database  view for every single thing, because I'm using these  projections to have the same exact result.  All right.  So that's queries.  We'll take the commands.  Now, commands are interesting.  Queries are pretty easy.  They were very kind of simple.  Everything's just input-output.  Commands are where really I see a lot of business logic in  place.  So for these cases, I want to say, let's look at all the  inputs for whatever I need to manipulate.  And the outputs may or may not exist.  Sometimes there is a result that comes out of executing  command.  Sometimes there is not.  Most often there's not.  So what are my inputs?  Well, luckily, because I had to whitelist everything here,  it's very easy to see what is only the data I need for this  individual request.  So in this case, it's that bind statement.  Well, I still want to go back to the view to make sure I'm  not missing anything.  But this may be a good start.  So I take those three properties that I'm building out  and say, let's create an object that represents that  request to do some thing in my system.  So in this case, the command is to create a student.  So I'll have a class that represents this request called  student create command.  I guess I kind of named it that was a little bit more  fluent in nature.  But I wanted to keep with the same naming convention of  controller, action, and then whatever.  In my systems, I create more task oriented user interfaces.  The example I'm running from here, the Contessa University,  is very crud in nature.  So there's not a lot of commands that represent real  business activities.  But the systems I work with, it's more like invoice  approve command, invoice reject command.  And I'll have individual forms and individual links on my  screens to do those individual actions.  Handling command is also now pretty straightforward.  I take the input.  And in this case, because the object was really simple, I  can now use Automapper to go the other way and just  manipulate my data entity model with whatever  information is coming in.  Now, if it gets more complex than this, if I'm doing some  other kind of data access or some kind of entity model, I  could be using, I don't know, I could be using event  sourcing, I could be using complex aggregate roots.  I don't care what I'm using here at this point.  Any kind of logic that is around this request is going to  be limited to this one file.  So if I need to refactor this, I need to break out on  something else, it's all in this one individual file.  And again, no repositories because it's just not needed.  Now, there's some pieces missing here that I just skipped.  In my controller earlier, we saw that there was basically one  line of real business logic which was creating a student  and then saving it.  But there's a lot of other junk going on with validation and  things not found and what to do in those cases.  So I still have the issue of what I need to worry about of  the cross-cutting concerns in my system.  These cross-cutting concerns are the kinds of code I see  copied and pasted in method after method.  But there's no real easy way for us to abstract those things  out into some kind of service layer.  Because again, once I abstract this out into just a lower  level abstraction, I still am not solving the actual  problem of addressing these cross-cutting concerns.  So I see this in my controllers a lot.  If model state is valid, then do something.  If model state is valid, then do something.  Model state is valid.  And this application, I saw this model state is valid.  I looked just looked at how many references are the words  who is valid.  And there's something like 40 references to that property  across my entire system.  Which means that if I ever need to extend the functionality  around validation, I have to go to 40 different places.  This is a relatively small system.  And one recent application that we had this style of  architecture, we had something on the order of 120  controllers and about 500 actions.  And there's no way I could change the cross-cutting  concern of validation or any other thing like that if I  have to go to 100 of the places to try to modify that.  So what I want to do is shift how I think about validation.  And currently, this application is not validating  individual requests, but it's validating the entity as a  whole.  So make some changes on the data entity and then validate  that the entity is in a good state.  But when I'm dealing with my business, I don't ever  validate entities.  I validate requests.  So the other nice thing about having a model built around  queries and commands is that instead of my validation  centering around entities after the fact, after they've been  mutated into bad state, I can instead say, let's wait  and let's not make any changes to my model until I've  actually validated the request.  And so my validation now centers around requests, not  entities.  In this case, I'm using a library called fluentvalidation  who builds validation around objects.  And so in this case, I build validators around every  request in my system that needs some sort of validation.  So I've got whatever validation is needed for creating a  student is right here.  Now another nice thing about this is if validation is  different for different kinds of requests, it's limited to  these individual validation classes.  So if creating a student has different validation than  editing something, that's OK.  I see this in systems a lot with legacy data that say, we're  now requiring a field.  But I can't put that validation on the entity itself  because there's consuming existing data that doesn't  have that information in there.  And I can't go backfill data.  But in this case, because I have validation around  individual requests, I can say, well, going forward,  students that need it are created now have this  validation.  But for existing students, I could have different validation  for whatever those cases may be.  I also moved away from attribute-based validation.  Sometimes my validation becomes a little more complex,  like make sure students have unique names or unique  identification numbers.  Because I'm centering my validation around classes,  this type can actually take an entity framework DB context  and then do something with it.  So if I needed to query the database to do something, I  could have it all in here as well.  So I've addressed the problem of validating entities, but I  still have that isModelStateValid littered  across my application.  So I haven't actually solved that problem quite yet.  To solve this one, we need to take a little bit outside the  box about how our validation flow typically works.  So in our normal validation flow, we have some sort of  post that makes a request to the server.  The server says, is this valid or not?  And then if it's not valid, it returns a 400 bad request  HTTP status code, as well as the HTML page itself that says,  here's all new HTML, both all my validations  errors inside of it.  If it is valid, then I'll do work, persist my changes to  the database, and then I'll do an issue of redirect to say,  go ahead and redirect to this new page.  Now this is assuming that I've also made the same choice of  not building on top of single page application frameworks,  and just done plain old post redirect get architecture.  Now the downside to this approach is that if something  goes wrong on the server, there's some sort of  validation error, I have to have an entirely new HTML page  to show the user that has to retain the state of whatever  they put in there before, including things like drop  down lists, and check boxes, and radio buttons, and all  sorts of other things, that are actually quite a difficult  to recreate if the only thing I'm working with is that very  simple post data that came up.  So what I'd like to do is modify my validation flow to  optimize the success path, and if something goes wrong, then  do something a little bit different.  So in my modified validation flow, I'm going to actually  hijack whatever post that happened in the server.  So the user will click a button, their request gets  hijacked with Ajax, I issue the post to the server, and then  the server does the validation based on just  adjacent data.  If something goes wrong, and the reform is invalid, what  I'll do instead of returning an entirely new set of HTML,  I'll instead only return an object that represents the  validation errors.  So here's the things that are invalid, and here's the  property names for those things that can be bound up.  So on my Ajax post, when I get the result back, I'll take  that result and bind it directly to the screen, because  I haven't actually refreshed the page and  gotten any new HTML back.  So I don't have to go wipe the entire screen, forget  everything you've done, and then re-bind everything with  the validation errors.  I simply take those validation errors and now just show them  on the screen.  The success case looks exactly the same.  I'll just do work, make some change to this database, and  then do my normal redirect.  So I'll do this now with a cross-cutting abstraction that  actually exists in my MVC framework.  So in this case, I'm using an action filter, which gets  executed in every single request.  And if I find that my model state is not valid, then what  I'll do is I'll take, actually in this case, I'll just take  the raw model state from the MVC framework, I'll serialize  it to JSON, and return that as the content to the Ajax  post on the browser side.  The browser side will receive that, see that it's a 400  bad request, and then just bind that model straight directly  to the form variables without having to refresh any of the  other HTML on the screen.  If things are successful, then it just goes on with the  rest of the request.  So my controllers no longer have if model state is valid  anywhere.  I've taken care of validation, that is, the validation flow  exactly once, and a cross-cutting layer, and not  have to worry about it really ever again.  So the final piece of the puzzle is I've now built  everything into vertical slices with requests modeled as  queries and commands, but I've still got everything  scattered across my entire solution, organized by  layer, not by feature.  So what I want to do is flip this on his head and not  organize by layer, but organize by feature.  If I look at when I need to make a change to my system, I've  got all these different folders for all these different  cross-cutting concerns, and when I need to do something like  make a new page in my system, I'm going to this folder, I'm  going to this folder, I'm going to this folder, I'm going to  this folder, probably three or four others to make this  change in my system.  And it becomes really difficult to follow what's going on  when I'm having to go across my whole solution to make any  sort of change.  So what I want to do is collapse all these different  things together, all these different pieces that I need  to create for an individual request on my system and  gather them in one place.  And then what I'm going to do this is I'm going to collapse  everything down into folders and namespaces based on those  activities.  So in this case, I'm creating a features namespace and then  another namespace based on whatever area feature that  that request belongs to.  In this case, I still just defaulted to the controller  name, whatever that controller name is going to be,  whatever my folder is for my features.  And then inside of that, I'm going to create a class that  represents whatever thing you're trying to do there.  In this case, it's creating a student.  And then nested inside that class are all the different  things that relate to that request.  So in this case, I have the command object that represents  whatever thing I'm trying to do.  I have whatever validation that is whatever validation  deals with that request.  And then handling that request is now a handler inside of  this create class.  Now I could have done this with a namespace, but I find  that it's a little bit easier just to have everything in one  file, that whenever I'm making a change to the system,  everything I need to do is right here.  And I don't have to go jump around anywhere.  So now I can have entire features be  collapsed into one file.  So in this case, I have a query that shows the initial get  request for editing something.  I have validation around my query.  I have the command that represents the post.  And then I have validation around the post.  And then I have the handlers for both my query and my command.  So I, as a developer, when I'm creating a new feature in my  system, everything's in one spot.  I'm going to go even one step further and have everything  related to that feature, not just code, but also any kind  of scripts or templates also be organized  alongside them as well.  So inside of this, I've got my edit C sharp code.  I've got my edit view.  And if there's any JavaScript associated with this, I have  that alongside as well.  So I want to go see everything there is to do about a  certain feature.  I've got everything right together as close as possible.  And you're starting to see this more and more on client  site frameworks as well.  For example, React is embracing this concept as well.  And instead of having things spread across services and  factories and factory service providers and blah, blah, blah,  we have everything together that has to deal with one single  component.  And this is just another implementation of that sort  of concept.  So to achieve this, it's really just renaming the views  folder to features.  And then making a little modification in my view  engine to be able to redirect those requests to go to the  views folder, the features folder.  So that's how I can then locate the views.  And the final piece then is in my JavaScript side, I want to  have individual modules for every single page.  I don't want to reuse my JavaScript across different  screens.  If there's something that needs to be reused, I'll extract  that and put it to something that's not specific to any of  my features.  And so every single JavaScript file is now an individual  required JS module per slice.  And so this part right here is taking the, I want to have on  every single page that loads up one single block that says,  go ahead and fetch my required module for this  individual page.  And instead of me copying that pasting into multiple views,  I have one spot that pulls out whatever control I'm looking  at, whatever action I'm on, and then goes into the features  folder and loads up that individual JavaScript file for  that individual page, and then builds and names a required  JS module around that.  So if I want to go see all the JavaScript that is related to  this one page, it's again in one single file, along side,  directly alongside everything else that has to do with that  one request.  So when I get to the end and look back at what my controller  became, we're moving all these layers, it becomes now  pretty simple.  It's really just taking in requests and via mediator  sending them out to the actual handlers that is that domain  specific handling.  But otherwise, this is just going to be UI logic.  And you could look at this and say, well, why do I need a  controller in the first place?  Well, I still need something to satisfy, in this case, routes  in MVC.  And I've also found that there are cases where I do have to  deviate from this model.  For example, if I'm doing something like file uploads,  that's really crazy MVC logic that does require me to get to  the bare metal of MVC itself and the actual HTTP request.  So in that case, I didn't go to this normal mediator request,  so I still need a controller to represent that's handoff  between the UI and my actual domain objects, or my actual  domain layer.  My end architecture now looks like this.  I've got a large number of features that are heavily  isolated from each other, that I don't have any sort of shared  responsibility between those.  I have some things that are cross-cutting concerns,  validation, authentication, authorization, logging, any  sort of things like that.  Those go across all the different features, but are not  built on top of different layers.  These are just built as cross-cutting concerns.  And the final piece is then some sort of persistence that I  typically have to share across my whole application anyway.  But again, this is not domain specific or not business  specific.  It's just another tool I'm using across all the layers in  my system.  So one thing I found about this is these top pieces are all  domain agnostic.  These are pieces that I can take from project to project, and  also very good cases for me to either build common shared  libraries, open source projects, or components that I share  across the different solutions I have in my company.  These are the pieces that are actually unique to my system,  and I don't try to share across different pieces.  So earlier when I said we were able to switch from  Petapoco to Enhybernate to Entity Framework, this is  really easier for us to do, because I could take one  individual feature size at a time, migrate it, test it,  make sure it works, and then move on to the next feature  without having a really long-lived branch to the  side that doesn't do this really big bang refactoring.  I don't actually care the technology used in each of  these feature sizes either.  They could be using store procedures.  I mean, if you're crazy.  They could be using micro-RMS.  They could be using anything.  I don't even care, because all the logic and behavior  associated with each individual request is contained in that  one set of request files, then those concerns don't leak  across the different features in my system.  I don't even worry about domain or design patterns anymore.  I don't worry about factories and strategies.  I mean, these feature folders, these feature sizes, can be  as procedural as you could possibly be, because who  cares at this point?  Just shovel the stuff in a file and just have it in one spot.  If it does get crazy, I can always refactor in the future,  but I'd actually prefer to have everything in one spot as  opposed to trying to break it out into  multiple abstractions.  So let's do a solid roundup to see how our architecture now  deals and addresses solid.  So looking at single responsibility principle, now  that I have one class per feature concept, requests,  results, commands, validators, I have now each class  responsible for one exact thing and only one thing.  On open-close principle, I extend my application through  cross-cutting concerns.  In this case, it would be things like the action filters,  extra results, but I don't do those things in the actual  meat of my application.  I do that in horizontal slices that go across all the  different features in my system.  The L just kind of goes away.  I don't have inheritance anymore, so I don't have to  worry about things getting substituted for other things.  I don't have really wonky repository hierarchies or  really crazy service hierarchies or base controller  classes.  All that kind of goes away if I just don't do inheritance.  And instead, focus on individual classes for  individual responsibilities.  And then this never comes up for me really ever again.  And the interface segregation principle, because every  single class is responsible for one individual thing and  queries are separated from commands, I don't have to worry  about having multiple people changing one individual type to  do multiple different things.  Every single request has an individual class, and so it only  has one reason to change.  And finally, on the dependency inversion principle, or  whatever it is, the thing that requires IOC containers, I  save this for actual real external dependencies.  So real dependencies like I have to interact with some  third-party web service or some third-party components.  This is something for things I don't write in my system.  So the only thing we saw so far in our system that I needed  a true dependency for was that entity framework DB context.  I want to have something else manage the creation of that  and management of that and not have that inside my type.  So what I see is that the number of dependencies in my  system are greatly reduced because they don't have things  like services and repositories to do with anymore.  It's just the actual meat of what's going on in my system  and nothing else.  I do have occasions where I have some things that are  injected that I actually build, but these are things that  are wrapping those things I can't control.  For example, I need to know who the current user is, and  instead of me doing something like going to the thread,  current user, whatever, then I'll have something like an  eye user context that can be filled in and supplied by  something else as well.  So thank you, everyone, for attending my solid architecture  of Slices Not Layers, and I hope you join me in the anti-crap  movement going forward.  Thank you very much.  We do have five minutes for questions.  If anyone has anything, yes?  Yeah, so the question is, I showed a CRUD application, which  I admitted I was doing a strawman at the beginning, so this  is being fully up front there.  So what happens when things actually get complex?  So I find in those cases I let those handlers themselves  tell me which direction to go.  This becomes like true sort of TDD style, where as things get  more complex in that handler, I can take that behavior and  push it down into my domain objects.  So my domain objects no longer become just sort of dumb  entity models that are just getting stuff in and out of  the database, but I push that down.  So if, for example, I was doing something like event  sourcing, I would see that handler just now hand off that  request straight to my aggregate route and have that  do all the behavior, and then my handler itself is now just  doing basically the handoff between data access and stuff  in the actual domain.  What is the domain object today?  So those domain objects don't live in the future folders  because those are one of those cross-cutting things I have in  my system.  Any other questions?  So this full example is of my GitHub, github.com.jbogaard,  and there's a Contoso University where we can find an  actual running example of everything you saw here.  So thanks, everyone, again.
SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_0_1583.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_1584_3791.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_3792_5579.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_5580_5891.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_5892_6683.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_6684_6827.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_6828_7115.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_7116_7715.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_7716_7847.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_7848_8711.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_8712_8819.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_8820_10559.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_10560_12335.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_12336_13571.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_13572_14147.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_14148_15383.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_15384_16679.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_16680_18191.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_18192_19307.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_19308_19439.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_19440_19511.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_19512_23723.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_23724_24347.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_24348_24743.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_24744_25703.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_25704_26375.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_26376_27947.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_27948_27995.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_27996_29927.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_29928_29975.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_29976_31463.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_31464_36263.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_36264_36359.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_36360_37955.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_37956_38531.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_38532_38939.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_38940_39215.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_39216_39863.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_39864_40247.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_40248_40859.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_40860_41627.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_41628_43583.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_43584_45371.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_45372_46355.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_46356_47915.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_47916_47963.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_47964_48263.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_48264_49379.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_49380_50183.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_50184_50783.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_50784_51971.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_51972_53735.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_53736_54251.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_54252_56447.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_56448_59123.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_59124_59279.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_59280_59747.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_59748_61007.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_61008_61343.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_61344_62495.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_62496_62687.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_62688_64619.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_64620_64847.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_64848_65051.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_65052_65123.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_65124_65711.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_65712_66623.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_66624_67451.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_67452_68075.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_68076_69563.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_69564_70319.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_70320_71663.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_71664_73007.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_73008_74135.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_74136_74507.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_74508_76571.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_76572_76691.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_76692_77135.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_77136_77627.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_77628_78743.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_78744_80459.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_80460_80999.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_81000_81047.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_81048_81659.png SOLID_Architecture_in_Slices_not_Layers_-_Jimmy_Bogard_81660_83346.png