Init-only Properties

.NET 5 is out! And with it, C# 9, which adds a lot of new features to the language. In this post, I'm going to talk about one of my favorites, init-only properties.

Immutability Before C# 9

Before C# 9, we can make a class immutable by using getter-only auto properties together with a constructor whose arguments are used to populate those properties:


public class Product
{
    public Product(string name)
    {
        Name = name;
    }

    public string Name { get; }
}

This is an effective way for making classes immutable.

We cannot change the property's value after the class has been instantiated:


var product = new Product("Cool Product");

product.Name = "Cooler product"; // compile error

We even can't change it from within the class:


public class Product
{
    public Product(string name)
    {
        Name = name;
    }

    public string Name { get; }

    public void SomeMethod()
    {
        Name = "Cooler product"; // compile error
    }
}

Drawbacks

That all works great; immutability is enforced. It has a couple of drawbacks though:

  • There has to be an appropriate constructor. Having a constructor is fine if there are just a few properties. But if there are a lot of properties, the code will tend to become unreadable.
  • We can't use object initialization syntax. Constructing an object via object initialization is typically more readable than constructing it via a constructor.

These drawbacks may discourage developers from writing immutable code in this manner.

Init-only Properties to the Rescue

C# 9 addresses these drawbacks by introducing init-only properties.

An init-only property is a special variant of the set accessor. It can only be called during object initialization.

Here's an example of the Product class which uses the init-only property:


public class Product
{
    public string Name { get; init; }
}

Notice that we are using the init accessor instead of the set accessor.

Now, in addition to using an explicit constructor, we have the option to instantiate an object using the familar object initialization syntax:


// We can use object initialization!
var product = new Product
{
    Name = "Cool product"
};

But in terms of immutability, the code works exactly the same way as it did before.

We still can't change the property's value after the class has been instantiated:


var product = new Product
{
    Name = "Cool product"
};

product.Name = "Cooler product"; // still a compile error

And we still can't change the property's value from within the class:


public class Product
{
    public string Name { get; init ; }

    public void SomeMethod()
    {
        Name = "Cooler product"; // still a compile error
    }
}

Conclusion

Making classes immutable leads to code that is easier to reason about. C# 9 helps developers write immutable classes by introducing init-only properties. Init-only properties make it possible to instantiate immutable classes using the familiar and readable object initialization syntax.

Web API Without Controller

If the mantra of "thin controllers, fat models" is followed to the extreme, it would result in very short controller methods, sometimes even only a couple of lines long. Today I am experimenting with doing away with controllers entirely, and just mapping routes directly to methods that execute the business logic.

The code in this post can be found in: https://github.com/ojraqueno/web-api-without-controller

Setting Up the New Project

First, I created the web API project template using dotnet new:


dotnet new webapi -n ControllerLessWebAPI

That will create a new API project for me inside the ControllerLessWebAPI folder.

I can run that project by going into the directory and running dotnet run:


dotnet run

It will start the website, which in my case is located in localhost port 5001. If I go to https://localhost:5001/weatherforecast, I can see some random JSON data being returned.

Removing the Controller

The starter template contains a WeatherController class which is responsible for returning the hardcoded JSON data. We can tell the app not to use the controller for routing by removing the relevant line in Startup.cs:


public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        //endpoints.MapControllers(); // remove this line
    });
}

Using Our Own Route Handler

We can use app.UseEndpoints to create our own route handling logic. The endpoints parameter in the lambda expression is of type IEndpointRouteBuilder, which contains methods we can use to map routes to handlers.

We can use the MapGet method to map a GET request to the appropriate handler. The MapGet has two parameters: a string for the route pattern and a RequestDelegate which is nothing but a method that takes an HttpContext parameter and returns a Task.

Here is an example which mimics the logic of the Get method inside WeatherController.cs:


using Microsoft.AspNetCore.Http;
using System.Text.Json;

// ...

// Inside Configure
app.UseEndpoints(endpoints =>
{
    endpoints.MapGet("/weatherforecast", async context =>
    {
        string[] summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        var rng = new Random();
        var returnData = Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = summaries[rng.Next(summaries.Length)]
            })
            .ToArray();
        var jsonData = JsonSerializer.Serialize(returnData);

        context.Response.ContentType = "application/json";
        await context.Response.WriteAsync(jsonData);
    });
});

That code will map the "/weatherforecast" route to the provided handler, which just returns some hardcoded JSON data.

If we now go to https://localhost:5001/weatherforecast again, we can see that it behaves exactly like before.

We just handled an API call without using a controller. Cool!

A Little Cleanup

If we put all the route handling logic in Startup.cs, the code would quickly become difficult to maintain. But because the handlers themselves are just regular methods, they can be placed in other files.

For example, we can create a class named WeatherService and copy the logic into a Get method on the class:


using System;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;

namespace ControllerLessWebAPI
{
    public class WeatherService
    {
        public static async Task Get(HttpContext context)
        {
            string[] summaries = new[]
            {
                "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
            };

            var rng = new Random();
            var returnData = Enumerable.Range(1, 5).Select(index => new WeatherForecast
                {
                    Date = DateTime.Now.AddDays(index),
                    TemperatureC = rng.Next(-20, 55),
                    Summary = summaries[rng.Next(summaries.Length)]
                })
                .ToArray();
            var jsonData = JsonSerializer.Serialize(returnData);

            context.Response.ContentType = "application/json";
            await context.Response.WriteAsync(jsonData);
        }
    }
}

In Startup.cs, we can declare a dictionary mapping routes to handlers:


private static readonly Dictionary<string, RequestDelegate> getRouteHandlers = new Dictionary<string, RequestDelegate>
{
    ["/weatherforecast"] = WeatherService.Get
};

Finally, we can call MapGet on each item in the route handler dictionary:


app.UseEndpoints(endpoints =>
{
    foreach (var (route, handler) in getRouteHandlers)
    {
        endpoints.MapGet(route, handler);
    }
});

Conclusion

The starter project template for ASP.NET Core web applications already come with controller classes to help us get up and running easily. In this post, we saw that we can create our own route handlers if we wanted to. This is also a small showcase of just how easily extensible and customizable the ASP.NET Core framework is.

Getting Started with Python

I usually talk about .NET topics, but today I want to talk about Python. Big shout out to my partner, who is a Python developer, for inspiring me to write about Python.

Python Summary

For the .NET people out there, here is a quick summary of the Python programming language:

  • Concise and readable syntax, suitable for programmers of all levels
  • Dynamically typed and interpreted, ideal for rapid application development and prototyping
  • Consistenly rated as one of the most popular programming languages in the TIOBE Index and StackOverflow survey
  • Widely used for web and data science applications

To install Python, go to https://www.python.org/downloads/ and download the version you want. I would recommend getting the 3+ version. I am using version 3.9.0 for this post.

During installation, it might ask you if you want to add Python to the PATH. I would recommend checking this option so that you can run Python from any location in your command prompt or terminal.

Python Hello World

Python code live in .py files, much like how C# code live in .cs files. But to try Python out, we don't actually need something saved in a file.

To try it out, type python in your command prompt or terminal. When you press Enter, you should see the '>>>' prompt, which is the Python REPL. You'll also see some info about Python and your environment and some helpful commands:


C:\>python
Python 3.9.0 (tags/v3.9.0:9cf6752, Oct  5 2020, 15:34:40) [MSC v.1927 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

On the >>> REPL, you can type Python code already. For example, type print('Hello, world!') to print to the console:


>>> print('Hello, world!')
Hello, world!

To exit, just type Ctrl+Z and press Enter.

Python Hello World Using a File

The Python REPL is a great way to try out Python features and play with the language. But for real projects, it would be ideal to put the code into files.

Create a file named helloworld.py, with the following contents:


print('Hello, world!')

This is the exact same content we tried out in the prompt.

Back in the prompt, type the following to run the program:


python helloworld.py

You should see the exact same output as we saw in the terminal.

Comparision with C#/.NET

This is only a small example, but already we can see some differences between C#/.NET and Python.

The difference that stands out to me the most is that because Python is an interpreted language, there is no compile step. In C#, there is a compile step which results in the creation of the bin folder and the resulting .exe or .dll file. In Python, there are no such artifacts.

There's also less ceremony in creating a simple program in Python. In .NET land, the simplest console app requires a lot of fluff to be present: using statements and declarations of the namespace, class, and Main method. Those stuff could be intimidating for someone who's a complete beginner to programming. Note though that that's changing in .NET 5.

Conclusion

Getting started with Python is very easy. You just install it and it's ready to use with your command prompt and/or your favorite text editor. Check out https://www.python.org/ for more information about Python.

ASP.NET MVC vs ASP.NET Core: Practical Differences

ASP.NET Core has been around for a while, but not everyone is using the new framework yet. If you're someone who's migrating from ASP.NET MVC to ASP.NET Core, you might be wondering what the differences between the two frameworks are. In this post, I will share the main differences between the two, from the point of view of a developer who has worked with both.

Here is an overview:

  1. Dependency injection is built-in.
  2. Controllers are unified.
  3. Client-side assets are centralized.
  4. And more - read below!

Dependency injection is built-in

Dependency injection is a popular pattern in object-oriented languages that helps make code maintainable. With ASP.NET MVC, developers had to make use of 3rd-party NuGet packages to enable dependency injection in their projects.

In ASP.NET Core, dependency injection is baked into the framework. There is no need to use any NuGet package, although using 3rd party DI packages is still supported.

Dependency injection is supported not only for your own custom code, but also with the built-in classes used in ASP.NET Core.

For example, take a look at the following code from Startup.cs, straight out of the template of a new ASP.NET Core API web application:


public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

You can see dependency injection at work by looking at the constructor, where a parameter of type IConfiguration is passed as a parameter. You can also see dependency injection at work on the ConfigureServices and Configure methods.

Controllers are unified

In ASP.NET MVC, there were two types of controllers that you normally inherit from: Controller for controllers that return views, and ApiController for controllers that return data.

It was possible to mix the two in the same project, but there is additional configuration involved. For example, the route configuration should be done carefully so that the route goes to the correct controller type. And if you wanted to use custom filters, it would have to be written twice, one for the normal controller, and one for the API controller.

In ASP.NET Core, there is only one Controller base class that's used for returning anything, whether views or data. There is no ApiController anymore.

The main benefit is that it allows reuse of codes that are common to methods that return views and data. One example are custom filters, and even built-in filters like the [Authorize] filter.

Overall, the unification of controllers require less code plumbing and allow the developer to focus more on busienss logic concerns.

Client-side assets are centralized

In the default folder structure of an ASP.NET MVC project, CSS and JavaScript files are located in the Content and Scripts folder. These folders are on the same level as other server folders like the Views folder and the Controllers folder.

For a new ASP.NET Core project, all client side assets like CSS files, JavaScript files, favicon, images, and others are located in a folder called wwwroot.

wwwroot folder structure with static assets inside

Since all the client-side assets are in one place, the code structure is easier to understand and maintain out-of-the-box.

More importantly, it works well when using front-end technologies, including module bundlers such as webpack.

On a related note, code for server-side bundling and minification is not included out-of-the-box on the default ASP.NET Core project. Any bundling and minification has to be added manually. One popular solution for front-end bundling and minification is webpack.

And more!

Here are some more differences:

  • Global.asax is gone. Instead, it has been replaced with Program.cs for setting up the web host and Startup.cs for setting up the services (see the sample code above).
  • web.config is gone. Instead, configuration is controlled by appsettings.json.
  • It is cross platform. .NET Core and ASP.NET Core runs on Windows, Mac, or Linux.

Conclusion

ASP.NET Core is an exciting framework with many changes and improvements over ASP.NET MVC. Three practical differences between ASP.NET Core and ASP.NET MVC revolve around dependency injection, the controller programming model, and handling of static assets. These differences make the default code structure easier to work with and compatible with the current best practices in the web programming world.

Solved: Unable to publish to Azure App Service from Visual Studio

I recently created an Azure App Service and tried to publish a new ASP.NET Core web app using its publish profile downloaded. When i did that, I encountered an error:

Web deployment task failed. (Could not connect to the remote computer ("[redacted].scm.azurewebsites.net"). On the remote computer, make sure that Web Deploy is installed and that the required process ("Web Management Service") is started. Lear more at: http://go.microsoft.com/fwlink/?LinkId=221672#ERROR_DESTINATION_NOT_REACHABLE.)
The requested resource does not exist, or the request URL is incorrect.
Error details:
Could not connect to the remote computer ("[redacted].scm.azurewebsites.net"). On the remote computer, make sure that Web Deploy is installed and that the required process ("Web Management Service") is started. Lear more at: http://go.microsoft.com/fwlink/?LinkId=221672#ERROR_DESTINATION_NOT_REACHABLE.
The remote server returned an error: (404) Not Found.

Here's how to solve that error:

  1. Go to the app service on the Azure portal.
  2. Go to configuration.
  3. Add an app setting with name WEBSITE_WEBDEPLOY_USE_SCM and value false.
  4. Save changes.
  5. Download a new publish profile.

You should be able to do publish from Visual Studio now.

Immutability

Last time, we looked at pure vs impure functions and we said that functional programming favors pure over impure functions.

Using pure functions leads to another concept: immutability.

Immutability means that a variable can only have its value set once. After that, the value never changes. So much so that in functional programming, the phrase "assigning to a variable" is often replaced by "binding to a symbol", since the word "variable" is not applicable anymore.

Let's consider a non-immutable example:


// Declare a class named Car
public class Car
{
    public string Color { get; set; }
    public bool IsStarted { get; set; }
}

// Instantiate a new instance
var myCar = new Car
{
    Color = "Red",
    IsStarted = true
};

// After that, change the values of the car's properties
myCar.Color = "Blue";
myCar.IsStarted = false;

The properties inside of the Car class are not immutable since they can be changed after the Car object has been instantiated.

Now, consider an example of a similar class whose properties are immutable:


// Declare a class named Car
public class Car
{
    // Use the readonly keyword to enforce the rule that the variables can only be assigned to once, during instantiation
    private readonly string _color;
    private readonly bool _isStarted;

    public Car(string color, bool isStarted)
    {
        _color = color;
        _isStarted = isStarted;
    }

    public string Color => _color;
    public bool IsStarted => _isStarted;
}

// Instantiate a new instance
var myCar = new Car("Red", true);

// After that, the values of the car's properties cannot be changed
myCar.Color = "Blue"; // compile error
myCar.IsStarted = false; // compile error

This is an example of a class whose properties are immutable. Their values are only assigned one time (during instantiation), and can no longer be modified afterwards.

What if we wanted to stop the car? We can't simply set myCar.IsStarted = false. How do we go about doing that in a functional way?

The workaround to "modify" something that has immutable properties is to create a new instance of it, initialize the new instance with the changes desired, copy the values of all other properties, and then return that new instance.

Here's how that might look for our immutable Car class:


// Declare a class named Car
public class Car
{
    // Use the readonly keyword to enforce the rule that the variables can only be assigned to once, during instantiation
    private readonly string _color;
    private readonly bool _isStarted;

    public Car(string color, bool isStarted)
    {
        _color = color;
        _isStarted = isStarted;
    }

    public string Color => _color;
    public bool IsStarted => _isStarted;

    public Car SetIsStarted(bool isStarted)
    {
        return new Car(this.Color, isStarted);
    }
}

Notice that we added a method SetIsStarted that returns a new instance of Car. The value of isStarted for that new instance comes from the parameter that we pass in the method. All other properties of the new instance (like its color) are just copied from the current instance.

Notice also that the SetIsStarted method is a pure function. It doesn't have side effects; it doesn't modify the car instance where it's called from.

In a similar way, there could also be a similar method for setting the car's color:


// Declare a class named Car
public class Car
{
    // ...

    public Car SetColor(string color)
    {
        return new Car(color, this.IsStarted);
    }
}

That method also returns a new car instance while not modifying the instance where it's called from.

Here's an example of how those methods can be used:


// Instantiated a red, started car
var redStartedCar = new Car("Red", true);

// "Change" the car to a blue one
var blueStartedCar = redStartedCar.SetColor("Blue");

// "Change" it again to a stopped one
var blueStoppedCar = blueStartedCar.SetIsStarted(false);

// Since our Set methods return a new instance of Car, we can chain them together
// "Change" the car one last time to an orange started car
var orangeStartedCar = blueStoppedCar.SetColor("Orange").SetIsStarted(true);

And that shows an example of how immutability can be achieved in C#.

Pure vs Impure Functions

My partner, who is also a developer, once asked me what the difference between functional and object-oriented programming is. There are many differences, and this post explores one of them: the usage of pure and impure functions.

What are pure and impure functions?

A pure function does not have side effects. A side effect is a change in state that happens outside of a function that gets persisted even after the function goes out of scope. Impure functions are everything else.

Here are some examples to clarify. First, a pure function:


// Pure
int GetSum(int a, int b)
{
    return a + b;
}

That is a pure function, because it does not affect any state that is outside the scope of the function.

Consider this impure equivalent:


// Impure
int sum = 0;

void ComputeSum(int a, int b)
{
    sum = a + b;
}

That is an impure function, because it modifies the sum variable, and the modification persists even after the method has gone out of scope.

When using an object-oriented language, it is very easy to write and see examples of impure functions.

Consider the following:


// Impure
void ComputeFullName(Person person)
{
    person.FullName = person.FirstName + " " + person.LastName;
}

That is impure, because it modifies the person.FullName property, and the change persists even after the method has gone out of scope.

This is the pure equivalent:


// Pure
string GetFullName(Person person)
{
    return person.FirstName + " " + person.LastName;
}

That is pure, because it does not modify any property or variable.

Side effects are not only limited to modifying data. Consider this method that writes to the console:


// Impure
void Print(string message)
{
    Console.WriteLine(message);
}

Even though no modifications were made, this is still an impure function, because some outside state was affected.

In this particular case, the state we are talking about is the state of the console window. Before the function was called, there was no message printed on it. But afterwards, there will be. And the message there will persist even after the method has gone out of scope.

What does pure and impure functions have to do with functional programming?

When programming in a functional style, pure functions are preferred over impure functions.

F# logo

There are functional programming languages that make this easy, like Haskell and F#. And while you can program in a functional way using an object-oriented language, the resulting syntax is usually verbose and hard to read.

Regardless of language used, the bottom line is that pure functions dominate the code base of a program that is written in a functional style.

My Vue.js Experience

Last year I wrote about Getting Started with Vue.js. I've been using Vue.js extensively from around that time up until now. In this post I will share my experiences with using the framework.

It's Still Very, Very Easy

With other JS frameworks I've tried, building simple apps and tutorial-type apps were easy. But, as the application's complexity grew, the development effort grew as well.

For example, when working with AngularJS, it sometimes wasn't easy to use 3rd party plugins. Because AngularJS was a framework, any 3rd party plugins had to have an AngularJS port for them to work properly. If such a port doesn't exist, extra work is involved in order for them to work with AngularJS (eg. calling $scope.$apply() in appropriate places).

That problem simply doesn't exist in Vue.js (at the very least, I haven't experienced that yet). I can use popular JS packages such as axios,lodash, even jQuery and integrate them into my app with absolutely no extra work.

Vue.js vs AngularJS

When it comes to HTML markup, Vue.js is very similar with AngularJS. For example, in AngularJS there is a ng-repeat directive, while in Vue.js there is a v-for directive, and both do pretty much exactly the same thing. Other similarities include ng-show (v-show in Vue.js) and ng-model (v-model in Vue.js).

However, as I mentioned above, the backend is extremely different. While in AngularJS everything has to be done in the "AngularJS way", there is no such restriction in Vue.js. That makes it very easy to learn Vue.js and also easy to integrate 3rd party plugins.

For reasons stated above, I would recommend not to use AngularJS for new projects. Instead, use a newer framework / library like Vue.js, React, or even Angular.

Moving Forward

I've only scratched the surface of Vue.js. I haven't used its component system in a production application yet, mainly because I've been working on a non-SPA and there are no use cases for reuse. I'm looking forward to using it though because I really like how the style, template, and script are encapsulated into single vue files (aka single-file components). So far, I'm pretty happy with using Vue.js.

Conclusion

If you're an AngularJS developer and are thinking about learning a new JS framework, I strongly suggest you look at Vue.js. There are many similarities between AngularJS and Vue.js that would make transitioning very easy. Also, Vue.js is very easy to learn in itself. You can also take a look at the other two major JS frameworks today, React and Angular.

The Tyranny of Horizontal Architectures (and How You Might Escape): Part 2

In part 1 of this series, I talked about the pains that I and my colleagues have experienced when working in code bases that used N-tier data-centric architectures. In this post, I will detail one approach which has allowed me to escape that madness.

Lasagna Code

We've all heard the term "spaghetti code". But there's also "lasagna code":

I use that statement to remind myself that layers can sometimes do more harm than good. That also reflects my experience.

Of course, it's not really the number of layers that's the problem, but rather, how the dependencies between those layers are set up and what abstractions those layers represent.

Consider this familiar diagram of a data-centric N-tier architecture:

Or even a diagram of a DDD-inspired but still horizontally-designed architecture:

These are okay architectures, with the domain-centric architecture being preferred over the data-centric one. However, when talking about horizontal layers, they both present the same difficulties.

Whenever you want to make a change, you have to cut across all layers (like a lasagna). If the service / repository classes reflect the database structure, the code you have to write to support non-CRUD actions become complex rather quickly.

I wrote about the pain points in more detail in the first post, so I won't repeat those here. I just shared those images so we can contrast it with the solution I've been using.

Vertical Slices to the Rescue

In 2015, Jimmy Bogard gave an excellent talk in the NDC Oslo conference entitled "SOLID Architecture in Slices not Layers" that covered this very problem. He shared how he and his colleagues flipped the architecture to something that looks like this:

Image source: https://lostechies.com/jimmybogard/2015/07/02/ndc-talk-on-solid-in-slices-not-layers-video-online/

You can view the entire talk here. But it can be clearly seen from the diagram that some of prominent horizontal layers, particularly the business logic and data layers, are gone.

In this design, every vertical slice encapsulates a user action, a business requirement. Regardless if that requirement is CRUD or non-CRUD in nature, all of the logic is handled in just one isolated part of the code.

Also, it's important to note that the persistence layer as depicted on the diagram are generic repositories, such as the one provided by Entity Framework via DbSet<T> out-of-the-box. There are no custom repository classes per entity that are shared. That way, changing a vertical slice does not entail change to the repository layer.

Going one step further, the persistence layer could be replaced by an infrastructure layer. The infrastructure layer would contain the generic repositories, and it would also cross-cutting concerns, like logging and email. All of these pieces can then be injected as seen fit to each individual vertical slice.

An important part of this design is that there are no dependencies between the feature slices.

Example implementation

One library I found that really helps implement vertical slices is MediatR. With MediatR, a vertical slice is represented by three classes: a class encapsulating input parameters, a class representing the implementation, and a class representing the output.

I previously wrote in detail about how to use MediatR. As a summary, take a look at this example trio of request / response / handler classes, and we will inspect them afterwards:


namespace MyAwesomeApp.Products
{
    public class Search
    {
        public class Query : IRequest<QueryResult>
        {
            public int PageNumber { get; set; }
            public int PageSize { get; set; }
        }

        public class QueryResult
        {
            public IEnumerable<Product> Products { get; set; } = new List<Product>();

            public class Product
            {
                public string Name { get; set; }
                public int Id { get; set; }
            }
        }

        public class QueryHandler : IRequestHandler<Query, QueryResult>
        {
            private readonly ApplicationDbContext _db;

            public QueryHandler(ApplicationDbContext db)
            {
                _db = db;
            }

            public async Task<QueryResult> Handle(Query query, CancellationToken token)
            {
                var products = await _db
                    .Products
                    .OrderBy(p => p.Id)
                    .Skip((1 - query.PageNumber) * query.PageSize)
                    .Take(query.PageSize)
                    .ProjectToListAsync<QueryResult.Product>(); // This is just using AutoMapper to map the entity class to our result class

                return new QueryResult
                {
                    Products = products
                };
            }
        }
    }
}

The request class here is Query, the response class is QueryResult, and the class that does all the logic is QueryHandler. Inside the handler, classes from the infrastructure layer (ApplicationDbContext in this case) can be injected.

If and when a need for a domain layer arises, usually to encapsulate common business logic, they can be injected in the handler class as well.

Then, the controller could look something like this:


namespace MyAwesomeApp.Products
{
    public class ProductsController : Controller
    {
        private readonly IMediator _mediator;

        public ProductsController(IMediator mediator)
        {
            _mediator = mediator;
        }

        [HttpGet]
        public async Task<ActionResult> Search(Search.Query query)
        {
            var queryResult = await _mediator.Send(query);

            return Json(queryResult);
        }
    }
}

The dependency injection container could be set up such that MediatR finds the correct handler classes based on the parameter.

What ends up happening is that each controller action's implementation essentially just becomes a call to MediatR's Send command. You automatically get adherence to "thin controllers, fat models" for free, and the controller ends up looking much nicer.

Each controller action gets a corresponding request-response-handler class trio that represents the vertical slice.

The Differences and Implications

Okay, now to note the differences between that approach and the layered approach.

1. Domain-Specific Layers are Mostly Gone

The handler class in that example takes the place of what was previously the business logic class and custom repository class. All logic is implemented there.

2. ...But They Could Come Back If and When Needed

Yes, I know what you're thinking right now: "but what about reuse?"

Going back to the pain points about using layers, one of the tradeoffs of reuse is coupling. When you successfully reuse a method, you also successfully couple all the callers of that method.

Now, that may or may not be a good thing; it depends on the situation. But the beauty of using vertical slices is this: since reuse is not the "default" position, there's less chance of messing it up by introducing bad coupling.

This is a very important point that's worth repeating: reusable code is written as the need for them is discovered, and not sooner. Starting with vertical slices essentially means you get adherence to YAGNI and KISS.

Perhaps more importantly, the reusable abstractions that eventually get created tend to be the best abstractions needed in that specific domain. This of course is a natural side effect of creating abstractions based on actual need and not just based on what are essentially predictions, however thought-out those predictions may be.

3. Representing Non-CRUD Operations, and Any Kind of Operation in General, are So Much Easier to Design

When dealing with non-CRUD operations using entity-centric service / repository classes, you have to spend some amount of brainpower on which class to put the implementation in. This is also something I talked about more fully in part 1 of this series. But when using vertical slices, particularly with the MediatR library, there's really no effort involved: you spin up a request-response-handler trio every single time.

4. Some Technology Decisions are Easy to Reverse

Here's an example: Suppose you have a repository class (eg. ProductRepository) that uses an ORM under the covers. Now, you find that you need to use raw SQL for one particular action. You can make the change in the particular method in the repository, but if you do, that method will be the odd one out in terms of implementation. All of a sudden, you find the consistency of the class breaking down. This is a broken window that may consume the entire project if not addressed.

This, of course, is another example of coupling: technology decisions that are applied across an entire layer. Technology decisions are difficult things to reverse and require much preparatory thought. But when implementations are encapsulated in vertical slices, with each slice being independent from one another, new technologies can be tried in an isolated context without fear of breaking other existing functionality.

Conclusion

This was the second and final part of my series "The Tyranny of Horizontal Architectures (and How You Might Escape)". The design I've been using to solve the layer madness is to ditch the layers entirely. Instead, I focus on creating isolated vertical slices per feature, utilizing the help of infrastructure classes as necessary. Shared layers are only introduced as the need for them arises.

If you're interested in trying this out, Jimmy Bogard has provided some example templates on his GitHub site. I'm also working on my own templates that use MediatR.

Give it a shot, and let me know what you think in the comments below!

The Tyranny of Horizontal Architectures (and How You Might Escape): Part 1

You've seen it before. You have been tasked to make a seemingly simple change on a web page. Add a couple of fields, perhaps. Or add new functionality, but still CRUD-like in nature. "Piece of cake," you say.

You then proceed to make a change to the HTML. Then to the viewmodel. Then to the business logic layer, which I will also call service layer. Then to the repository layer. Then to the database. (You could also do it in reverse.) All those steps just to add a couple of fields. Which is kind of okay, maybe no big deal. But, as the infomercial says, "Wait, there's more!"

Exhibit A: Implementing Functionality Involving Multiple Entities

Before we immerse ourselves in the madness, let's set up the domain: an online retail site.

In your database, there are Product and Order tables, which have a many-to-many relationship between them. You are following a data-centric N-tier architecture, and therefore there is a repository layer with classes such as ProductRepository and OrderRepository. The product repository contains methods for reading and writing to the product table, and the order repository contains methods for reading and writing to the orders table. You also have a business logic layer with classes such as ProductService and OrderService. The web app architecture is not that important, but let's say it's written in ASP.NET MVC.

Now, these are the tasks assigned to you. Can you identify what parts of the application to change? Specifically, do you change the Product-related classes, the Order-related classes, or do something else entirely? Think about those questions as you read the tasks:

  1. Add a new product.
  2. Retrieve all pending orders of a product.
  3. Check which products had the most associated orders in the last 7 days.

What are your answers? Here's how one could think about it:

1. Add a new product - This one's a gimme. ProductService / ProductRepository, for sure.
2. Retrieve all pending orders of a product. - Hmm, this one's a bit tougher. The input is related to products, so maybe change the Product classes? But the output is related to orders... I'm not really sure, but I have to finish this fast. I think I'll go with changing the OrderService / OrderRepository for this one.
3. Check which products had the most associated orders in the last 7 days. - Well this is a bit similar to number 2. Maybe I'll stuff it in the OrderService / OrderRepository. But it's getting crowded there... Aha, I have an idea! I'll just create new classes called ProductOrderService and ProductOrderRepository. Or maybe they should be named OrderProduct? I guess I'll just do a coin toss.

After a long debate with yourself, and possibly with other people, you settle for a design and go ahead with its implementation. You go through the motions of changing the database, the repository layer, the service layer, and any other layers that might be involved.

All the while, you are wondering if you did the right thing, or if this decision will not come back to haunt you or someone else down the road.

Exhibit B: Implementing Functionality that is Very Similar to Existing Functionality

Let's say that there's existing functionality to fetch the newest products. This is used in Page X. The signatures in the product service and repository might look like IEnumerable<Product> GetNewestProducts();

Now, on Page Y, you need to display the newest products as well as how many orders each one has. How would you modify the code to achieve this?

Some common choices are:

  1. Modify the existing method by changing the implementation to cover the widest use case. In our example, that means changing the implementation of GetNewestProducts so that it retrieves all the associated order counts. Both Page X and Page Y would then use that same method.
  2. Modify the existing method by passing a flag argument whose value will dictate the implementation. In our example, that could mean passing a boolean parameter indicating if the associated order count should be retrieved. Page A would pass false and Page B would pass true.
  3. Create a different method altogether.

Which method would you go with?

I find that for a small change like the one I described above, developers typically opt to go with either option 1 or option 2.

One big reason is that they're usually easier to implement. For option 1, all you have to do is add an Include or JOIN statement and logic for summing. For option 2, you just add an if switch. You can even set a default value for the boolean parameter so that Page X does not need to change how it calls the method.

Another reason is that it gives a chance to reuse an existing service / repository method. Reuse is touted as one of the benefits of designing using layers, and it feels good to see that benefit in action.

Now, if you have been developing software with layered architectures for any reasonable amount of time, you know all the bad things that could happen here.

For example, you come across a feature where it's not clear-cut whether it's better to write a new method or not. You spend an inordinate amount of time deciding what to do, and may still feel discontent with whatever implementation you went ahead with.

More commonly, you come across multiple variants of the same method where the implementation (widest use case or flag argument) gets mixed and matched, leading to code that's a nightmare to change.

In addition, both of those the two options are, in the first place, code smells. It's true that you get the benefit of reuse, but you also get the downside of tight coupling.

With the widest use case implementation, you get the code smell of a client depending on functionality it doesn't need: Page X doesn't need order counts, but gets them anyway. With the flag argument implementation, you get method signatures that are difficult to reason about and change.

Exhibit C: Look at the Size of It!

Let's face it: software can get, and is often, complex. What this means for our code is that we can end up with business logic layers or repository layers that have dozens of methods on them. Business logic layer methods are often accompanied by corresponding repository layer methods, so as one layer grows, the other grows with it.

We can get clever by implementing generic repositories, but that breaks as soon as an unsupported scenario comes up, which comes too early too often.

And what about the code in the web app? Depending on the extent of reuse, MVC controller actions can each also have a corresponding method in the business logic layer.

Now, having a lot of methods doesn't necessarily make for a bad design. We have to look at the context: are all the methods related to one another, in an abstraction that makes sense?

The "in an abstraction that makes sense" part is key here. One could argue that all the methods are related, since they all deal with a single entity. But is that how we should be thinking about the design?

If we are just talking about purely CRUD operations that deal with one entity at a time, without associated business logic, then yes, data-centric abstractions make sense. But for more complex operations, a new way of coming up with abstractions might just be warranted.

Conclusion

You're still with me; that must mean that you've gone through one or all of those issues!

For the longest time, I thought that nothing could be done to change how things were. Last I checked, N-tier architectures are still widely being taught. So they must be good, right? I concluded that the problem must be with me, and not with the design. Still, there was a nagging feeling that there had to be a better way.

The good news is that there is. Stay tuned for the second part of this series as I detail how I escaped, and how you can, too.

(P.S. - I'll also reveal why I used a picture of a lasagna here. :))

UPDATE: The second part is now out! View it here.