Quick Start

1. Install NuGet package


The best way to get AppTonic is to install it from nuget.org using NuGet.exe or the package manager console. You can also right click on your project or solution in Visual Studio and click "Manage NuGet Packages..." and search for AppTonic.

PM> Install-Package AppTonic

2. Create a request message


Messages are at the heart of AppTonic. For this guide, we'll be creating a message with just a simple POCO implementing the IRequest marker interface from the AppTonic package.

The most fundamental request interfaces are IRequest and IRequest<TResponse>, each indicating whether or not there is a response expected. While no additional request types are functionally nescessary, marker interfaces for commands and queries, as well as handling mechanisms for async requests are included to reduce boilerplate and create intention-revealing application code.

public class CreateUser : IRequest
{
    public string Name { get; set; }
}

Choose your style.

AppTonic supports two styles of composing your application. Take advantage of either your dependency injection container and/or use partial function application. We'll keep our focus on one style for the rest of the guide.

3. Implement a message handler (using dependency injection)


Add the IHandle<TRequest> interface to a class and implement your desired application logic in the Handle(CreateUser request) method. This class is the application service for handling this particular request.

SRP FTW

You can easily have just one class per message handler, encouraing clean code. Or, when it makes sense, combine a few message handlers on the same service. Since the design of your message handlers is decoupled from the service contract (defined by your message/request), you're free to change this as time goes on.

Composition Over Inheritance

Notice there is no base class to inherit from, and you are liberated from any inheritance your UI or web framework may impose on you, thus avoiding the pains and dangers of the Framework Superclass Anti-Pattern.
public class UserService : IHandle<CreateUser>
{
    public void Handle(CreateUser request)
    {
        var user = new User { Name = request.Name };
        _userRepository.Add(user);
        _userRepository.Save();
        _logger.Info("UserService: User Created");
    }

    // Rest of class ommitted for brevity
}

4. Initialize and configure the AppDispatcher (for use with dependency injection)


Dependency Injection Prerequisites

In addition to your desired dependency injection framework, you will need to install the AppTonic.CommonServiceLocator package.

PM> Install-Package AppTonic.CommonServiceLocator

Our first step before we configure the AppDispatcher instance is to have our dependency injection framework perform its usual composition, including resolving any our handler interfaces with its implementation. In this case, resolving IHandle<CreateUser> with our UserService application service. We also need to create the Common Service Locator adapter, using the appropriate NuGet package for our preferred dependency injection framework.

class Program
{
    static void Main()
    {
        // Configure your dependency injection container (Unity in this example)
        var container = new UnityContainer();
        container.RegisterType<IUserRepository, InMemoryUserRepository>();
        container.RegisterType<ILogger, ConsoleLogger>();

        // Register our application service - this process can automated, 
        // depending on your dependency injection framework
        container.RegisterType(
            typeof(IHandle<CreateUser>), 
            typeof(UserService));

        // Create common service locator adapter
        var unityServiceLocatorAdapter = new UnityServiceLocator(container);

        // Initilaize the AppDispatcher
        AppDispatcher.Initialize(app =>
        {
            app.UseCommonServiceLocator(unityServiceLocatorAdapter);
        });

        // Create a request
        var request = new CreateUser { Name = "Jane Smith" };

        // Dispatch your message to your service
        AppDispatcher.Handle(request);
    }
}

3. Implement a message handler (for use with partial application)


Although we haven't seen where partial application comes in yet, all we need to do to handle our message is to create a method that our request CreateUser as a parameter, along with any dependencies. That's it - no additional interfaces to implement.

Testability FTW

Static classes may make you cringe - but we're not using any static variables here. This style is normal in languages, such as F#, where first-class functions are grouped into modules. Aside from any statefulness our dependencies may have, our method is compeltely stateless. It's incredibly testable - our dependicies are clearly deterermined via our method parameters and are easily faked or mocked. Again, no framework base class or UI dependencies to make testing our software difficult.
public static class UserServiceModule
{
    public static void CreateUser(CreateUserRequest request, 
        Func<IUserRepository> userRepositoryFactory, ILogger logger)
    {
        using (var userRepository = userRepositoryFactory())
        {
            var user = User.Create(request);
            userRepository.Add(user);
            userRepository.Save();
            logger.Info("UserServiceModule: User Created");
        }
    }
}

4. Initialize and configure the AppDispatcher (using partial appliction)


Configuring our AppDispatcher without dependecy injection is very simple. In this example, the composition root of our application, we create any instances or define factories that will be used for our application. Finnally, all that is required is that we the appropariate RegisterHandler method on our configurator object, passing in closure that calls our application service, creating a partially applied function that is registered in our AppDispatcher instance. Now we can simple call AppDispatcher.Handle and pass in our request, and it will be handled using the dependencies passed in by the function closure we initially registered.

class Program
{
    static void Main()
    {
        // Look ma, no dependency injection container! 
        var logger = new ConsoleLogger();
        Func<IUserRepository> userRepositoryFactory = 
            () => new InMemoryUserRepository();

        AppDispatcher.Initialize(app =>
        {
            app.RegisterHandler<CreateUser>(createUserRequest =>
            {
                UserServiceModule.CreateUser(createUserRequest, 
                    userRepositoryFactory, logger);
            });
        });

        var request = new CreateUser { Name = "Jane Smith" };

        AppDispatcher.Handle(request);
    }
}

5. ASP.NET Web API Example (using either approach)


Using the AppDispatcher in our program is easy. We can use the AppDispatcher static class helper (as seen here), or we resolve an instance of the IAppDispatcher from our dependency injection framework.

AppDispatcher creation options

You can use the AppDispatcher.Initialize method, which creates a single instance of the AppDispatcher accessible from AppDisptacher.Instance, or you can use the AppDisptacherFactory.Create method, which is used in the exact same manner as the AppDispatcher.Initialize method, to create multiple IAppDispatcher instances, or to create an instance for injection into your IoC framework.

AppDispatcher.Initialize(app => {
    // configuration
})

IAppDispatcher dispatcherOne = AppDispatcher.Instance;


IAppDispatcher dispatcherTwo = AppDispatcherFactory.Create(app => {
    // configuration
})
public class UserController : ApiController
{
    public void Post(CreateUser request) {
        AppDispatcher.Handle(request);
    }
}
public class UserController : ApiController
{
    private readonly IAppDispatcher _app;

    public UserController(IAppDispatcher app) {
        _app= app;
    }

    public void Post(CreateUser request) {
        _app.Handle(request);
    }
}

© 2014 Craig Smitham · Apache 2.0 License