design patterns

Design patterns: Circuit Breaker

Today I want to introduce a CircuitBreaker – one of the reactive design patterns, especially usefull in areas such as web services interop. To get you better understand on it’s concepts, lets consider following scenario:

You’ve built a successful web service, making use of another external services in order to handle user requests. During the big churn of end users requesting your site, one of them became overloaded, starting to respond with increasing delays. Ultimately while trying to satisfy all incomming requests, it has exhausted all resources and gone down, entailing your service with it.

I think it’s a well-known example and a good one to show a nature of the problem. Because of RPC nature, it’s characteristics differ from in-proc calls:

  • They operate on separate resources pool and might be used by more than one remote caller at the time.
  • Their internal state, available resources and performance may be hard to predict. In most cases, they neither can be controlled nor monitored by the caller.
  • Their life cycle is not bound to your local host. They may be reset/shut down while your service is still running and serving requests.

What reactive applications have to do with that? One of the key principles governing the Reactive Manifesto stands for quick responsiveness of the system, no matter if this response is possitive or not. Nowadays users are impatient. When they take action, they want a response, and they want it now.

This is when Circuit Breakers kicks in. They main role is to act as a decorator around your code to ensure, that you can quickly respond on any reliability problems:

  • First, Circuit Breaker defines a safe time delay given to the action to respond. Service which won’t fit specified timeout is considered to be unresponsive or working incorrectly. It’s better to inform your user about possible problems after a reasonable delay than to show him/her a smoke screen and spinner for the next 2 minutes.
  • Secondly it’s able to cut out the service in any sign of problems and give it a time to self repair. If you already know, that external service is not working properly, what is the point of calling it any way?

Most of the circuit breaker are realized as a state machines. Picture below presents a simple one:

where:

  • Closed – this is initial state. While closed, Circuit Breaker will simply pass any request to underlying function. However it also checks if response will met a specified timeout criteria or ended with failure i.e. due to external service overload or crash. Any of these will trigger Circuit Breaker to come into open state.
  • Open – while in this state, any request send through Circuit Breaker will follow fail fast semantic. Instead of forwarding request to the underlying function, CB will immediately throw an exception informing that it’s closed. Open state is not permanent – CB should automatically switch to half-open state after a specified time delay.
  • HalfOpen – this is a kind of the probing state, signing that CB is checking if undrelying function is responsive again. While in it, CB will pass first request call as if it was in Closed state, to eventually get the response. All subsequent calls will fail fast just like in Open state. If request failed again or response didn’t came in specified timeout, CB switches back to Open state. If response was successful, CB becomes Closed.

I’ve created a simplistic implementation of the CircruitBreaker pattern in C# (source code). It allows to perform multiple asynchronous calls through one CB instance in non-blocking, thread-safe manner. It has also attached a complete test suite describing it’s behavior. Feel free to use it and to modify as you wish.

Example usage:

    // this service could be a singleton, and could be called concurrently
    public class CurrencyExchangeProxy : ICurrencyExchangeProxy
    {
      private readonly CircuitBreaker<ExchangeCurrencies, ExchangeRate> exchangeRates;

      public CurrencyExchangeProxy(Configuration config)
      {
          exchangeRates = new CircuitBreaker<ExchangeCurrencies, ExchangeRate>(
              async req => HttpGetAsync<ExchangeRate>(config.ExchangeServiceUrl, req),    // async function, CB should take care of
              config.GetServiceTimeout(),         // time given to function to finish
              config.OpenTimeout());              // time given to function dependent component to restore in case of failure
      }

      public async Task<ExchangeRate> GetExchangeRate(Currency from, Currency to)
      {
          return await exchangeRates.Call(new ExchangeCurrencies(from, to));
      }
    }

    public class InvoiceController : Controller
    {
      private readonly ICurrencyExchangeProxy currencyExchange;

     [HandleError(ExceptionType=typeof(CircuitBreakerOpenException), View="UnresponsiveExternalService")]
      public async Task<ActionView> DisplayInvoice(int id)
      {
          ...
          var exchangeRate = await currencyExchange.GetExchangeRate(invoice.Balance.Currency, localization.Currency);
          ...
      }

[C#] A different look at service design

Today I want to present a different point of view on C# applications design. If you are programming in that language most of the time, it’s probably not what you’re used to see. However I found it interesting, because it allows to achieve a few important goals:

  • Decompose various, complex interfaces into few simpler, well build components.
  • Seriously reduce risk of common OO anti-patterns in your application i.e. God Object.
  • Make your code shorter and methods simpler.
  • Replace a lot of external assembly dependencies in your code with some simple design patterns.

If you’re ready, prepare to step down to the Wonderland. Let the Catepillar be our guide.

The basics

Step 1 – define an interface

Lets start with twisting our mindsets a little bit. Take the following example:

public interface IAuthService  
{
   Task<User> SignUp(string email, string password);
   Task<User> SignIn(string email, string password);
   Task ResetPassword(string email);
}

This is our new trendy-looking, non-blocking service interface. What’s also important here, it follows a Single Responsibility Principle.

Step 2 – separate responsibilities

Since SRP has no well-defined bounds and it is a matter of a personal taste, we could stretch it a little further:

public interface ISignInService  
{
    Task<User> Handle(string email, string password);
}

public interface ISingUpService  
{
    Task<User> Handle(string email, string password);
}

public interface IResetPasswordService  
{
    Task Handle(string email);
}

Now instead of one service responsible for three possible operations, we have a three atomic services, each one having only one operation to take care off. If you’re thinking, it’s overly complicated, you’re probably right. But right now we’re still in Objective Oriented world and the Wonderland awaits ahead.

Step 3 – more simplification

Now, when we have a three single-member services, take a look into the mirror. If you do, you’ll notice an important characteristic – interface with single method is almost indistinguishable from a delegate. It looks better now, see?:

public delegate Task<User> SignUpService(string email, string password);  
public delegate Task<User> SignInService(string email, string password);  
public delegate Task ResetPasswordService(string email);  

At this point you may want to turn back. This design is problematic. For example, it isn’t as easily composable with Dependency Injection frameworks as interfaces. Don’t worry. We will cover this up later. Now step in.

Step 4 – final generalization

Our service signatures are now almost ready. But to reach behind the mirror, we must apply two more rules:

  • Each service takes no more than one parameter.
  • Each service should always return a value.

Why does it matter? If each service will satisfy one input / one output rule, we may compose them together with ease.

public delegate Task<User> SignUpService(SignUpRequest request);  
public delegate Task<User> SignInService(SignInRequest request);  
public delegate Task<object> ResetPasswordService(string email);  

Now, all of our delegates could be abstracted away to a single generic definition:

public delegate Task<TRep> Service<in TReq, TRep>(TReq request);  

where:

  • TReq is type of request object passed to service.
  • TRep is type of service reply.

What we end up with is a highly abstracted – in Wonderland things looks different – and universal service signature.

Dependency Injection vs partial application

Walking down the object oriented road, often you could passed a view similar to this one:

public class TransportationService  
{
    private readonly ILocalizationService _localizationService;
    private readonly IOrdersRepository _ordersRepository;
    private readonly ICustomersRepository _customersRepository;
    private readonly IConfigurationProvider _configuration;

    public TransportationService (
        ILocalizationService localizationService,
        IOrdersRepository ordersRepository,
        ICustomersRepository customersRepository,
        IConfigurationProvider configuration)
    {
        _localizationService = localizationService;
        _ordersRepository = ordersRepository;
        _customersRepository = customersRepository;
        _configuration = configuration;
    }

    public async Task<TransportationDetails> PrepareTransportation(int orderId)
    {
        ...
    }
}

But now when you’re on the other side of the mirror, it looks more like:

public static TransportationServices  
{
    public static Service<int, TransportationDetails> PrepareTransportationService (
        ILocalizationService localizationService,
        IOrdersRepository ordersRepository,
        ICustomersRepository customersRepository,
        IConfigurationProvider configuration)
        {
            return async orderId => { ... };
        }
}

Here we simply return an asynchronous lambda. And because it’s nested inside, it can use all of the provided parameters directly in it’s scope.

Of course, there is still a matter of lifetime scopes. In case of singleton scopes, we simply may pass shared instance directly. But when more universal lifetimes are required, we can slide down the road along with the delegates to reach even higher abstractions – it’s twisted, but we’re in Wonderland, remember?

public static Service<LocalizationRequest, LocalizationReply> LocalizationService() { ... }

public static Service<MyRequest, MyReply> MyService(Func<Service<LocalizationRequest, LocalizationReply>> localizationServiceProvider) { ... }

// transient scope
var myService = MyService(() => LocalizationService());  
// or even shorter
var myService2 = MyService(LocalizationService);

// singleton scope
var localizator = LocalizationService();  
var myService = MyService(() => localizator);  
var myService2 = MyService(() => localizator);  

There is a one simple but powerful idea visible on the example above – an input parameter type has been changed from interface to another delegate. Now it’s delegates all the way down. This way we may start from the most atomic services and combine them into more complex ones without limitations.

Instead of complex, reflection-based DI frameworks we have one simple universal abstraction. You may find this more verbose, but it’s actually simpler, faster and more error-proof solution than any of IoC libraries. You don’t need to learn next DI framework or use StackOverflow guide to travel through the Wonderland.

There are other problems solved automatically:

  • No need to worry about cyclic references.
  • There is no risk, that our DI framework won’t know how to bind parameters to construct object. You’ll never get a runtime errors when walking this way.
  • Your application won’t inject bad interface implementation by mistake.

Repositories and testing

Another popular OO desing pattern is a repository and it’s most corrupted (and misunderstood) version – generic repository.

public interface IGenericRepository<T>  
{
    Task<IEnumerable<T>> GetAll();
    Task<T> GetById(int id);
    Task<T> Create(T entity);
    Task<T> Update(T entity);
    Task<bool> Delete(T entity);
}
public interface IUserRepository : IGenericRepository<User> {  
    Task<User> GetByEmail(string email);
}

Lets be honest – you’ll probably never use all of those methods at once. If you think it’s good abstraction, it’s not. It isn’t a good SRP example either. After we had stepped into the mirror, we’ve surely taken something from our world with us. So lets take a one of the things we’ve hidden in the pocket – changing user password.

public class UserService  
{
    private readonly IUserRepository _userRepository;
    public UserService(IUserRepository userRepository)
    {
        _userRepository = userRepository;
    }

    public async Task<PasswordChanged> ChangePassword(ChangePassword request)
    {
        var user = await _userRepository.FindByEmail(request.Email);
        if(IsValid(user, request.OldPassword))
        {
            user.PasswordHash = ComputePasswordHash(request.NewPassword);
            await userUpdater(user);
            return new PasswordChanged();
        }
        else throw new UnauthorizedException();
    }

    private byte[] ComputePasswordHash(string password) { ... }
    private bool IsValid(User user, string password) { ... }
}

Basically changing password would require only two out of six methods provided by IUserRepository – matching user and saving his/her state after changing. Now smoke the Catepillar’s hookah and take a look again:

public static Service<ChangePassword, PasswordChanged> ChangePasswordService(Func<Service<string, User>> userFinderProvider, Func<Service<User, User>> userUpdaterProvider)  
{
    var userFinder = userFinderProvider();
    var userUpdater = userUpdaterProvider();

    return async request => {
        var user = await userFinder(request.Email);
        if (IsValid(user, request.OldPassword))
        {
            user.PasswordHash = ComputePasswordHash(request.NewPassword);
            await userUpdater(user);
            return new PasswordChanged();
        }
        else throw new UnauthorizedException();
    };
}

private static byte[] ComputePasswordHash(string password) { ... }  
private static bool IsValid(User user, string password) { ... }  

We totally dealt with repository interface, introducing two service providers presented before.

Hint:

You can turn ComputePasswordHash (or even IsValid) into service on it’s own. All hail the modularity!

From testing perspective …

In traditional OO world, to test this feature, you’d probably include some mocking library, mock repository’s interface and check if correct method was called with correct arguments. You may also mock underlying database directly with something like Effort.

In Wonderland mocklibs are quite rare creatures. They are even harder to catch. We must find another way. Can we simply test it without any mocking library? Lets see:

// Arrange:
// if you abstracted ComputePasswordHash earlier, it'll be easier at this point
var testUser = new User(email, passwordHash);  
var db = new Dictionary<string, User> { { testUser.Email, testUser } };  
Service<string, User> userFinder = async email => {  
    User user;
    return db.TryGetValue(email, out user) ? user : null;
};
Service<User, User> userUpdater = async user => user;  
    var changePasswordService = ChangePasswordService(() => userFinder, () => userUpdater);

// Act:
await changePasswordService(new ChangePassword(email, oldPassword, newPassword));

// Assert:
Assert.NotEqual(passwordHash, testUser.PasswordHash);  

Actually, that’s all. Including mock initialization and result verification. No mocklib was harmed in the making of this test.

Aspect Oriented Programming vs lambda combinators

If you’re still interested in miracles of the Wonderland, we can go further. Next question: how can we bend reflection-based Aspect Oriented Programming to our will? There are possibly many ways, but I’ll focus only on the one.

Just like we used services to replace all of our interfaces, we replace aspects / attributes with filters:

public delegate Task<TOut> Filter<in TIn, TOut, out TReq, TRep>(TIn request, Service<TReq, TRep> service);  

where:

  • TIn is filter’s input type.
  • TOut is filter’s output type.

Filter is actually a wrapper around specific service, which may apply additional code before or after it, modify it’s input or output or even decide not to call it at all. In case when filter don’t change service’s in / out parameters, it’s signature is basically equal to public delegate Task<TRep> Filter<TReq, TRep>(TReq request, Service<TReq, TRep> service);.

Now, having those two types defines, lets create some utility methods, which can make our travel easier. Lets start with filter composer.

public static Filter<TIn, TOut, TReq2, TRep2> Then<TIn, TOut, TReq1, TRep1, TReq2, TRep2>(  
    this Filter<TIn, TOut, TReq1, TRep1> self,
    Filter<TReq1, TRep1, TReq2, TRep2> next)
{
    return (request, service) => self(request, req => next(req, service));
}

If we omit the method signature, this method is a pretty straightforward one liner which combines two filters together and gives another filter in return. As you can guess, with this trick we can join a whole chains of filters into one piece.

There is a second part of the puzzle missing. We still don’t have a well defined methods to work with both filters and services. This is the one:

public static Service<TReqIn, TRepOut> ApplyTo<TReqIn, TRepOut, TReqOut, TRepIn>(  
    this Filter<TReqIn, TRepOut, TReqOut, TRepIn> filter,
    Service<TReqOut, TRepIn> service)
{
    return request => filter(request, service);
}

Just like we were combining filters, now we combine a filter with a service to get service in return.

With this two methods (and basically two lines of code!) we can easily interop between filters and services. How will this weapon examine against aspects?

// logging example
public static Filter<TReq, TRep, TReq, TRep> LogFilter<TReq, TRep>(Action<string> logger)  
{
    return async (request, service) =>
    {
        logger("Log before: " + request);
        var reply = await service(request);
        logger("Log after: " + reply);
        return reply;
    };
}

// authorization example
public static Filter<UnauthorizedRequest, TReply, AuthorizedRequest, TReply> AuthorizeFilter<TReply>(  
    Func<Service<UnauthorizedRequest, Identity>> authorizationServiceProvider)
{
    return async (request, service) =>
    {
        var authService = authorizationServiceProvider();
        var authorizedIdentity = await authService(request);
        if (authorizedIdentity != null)
        {
            return await service(new AuthorizedRequest(authorizedIdentity, request));
        }
        else throw new UnauthorizedAccessException();
    };
}

// combine various filters together
var filters = AuthorizeFilter(AuthorizationService)  
    .Then(LogFilter(Console.WriteLine))
    .Then(MonitorFilter(MonitorService)
    .Then(UnitOfWorkFilter());

// apply all filters at once to the service
var enchancedService = filters.ApplyTo(myService);  

Again, thankfully to the power of composability we can join multiple filters into one and apply them to any number of services we wish to. Basically two simple types and two lines of code compiled upfront!

We ripped off (or seriously reduced) any runtime uncertainties, AOP, DI and mock libraries out of our code, as well as whole bunch of interfaces and abstraction layers. Did you enjoy the travel? Welcome in the Wonderland. Land of functional programming.

PS: presented concept is heavily inspired by Finagle library, originally written in Scala on a Twitter’s purposes.

More thoughts on Knockout.js and JavaScript MVVM

Today I want to share with my reflections on using Knockout.js and client side MVVM pattern. Some of them refer to my previous post on the same topic (in Polish language). These are my advices to all entusiasts of JavaScipt rich applications, especially to those, who want to try Knockout in production environment.

Layered structure

Most of the frontent application logic, I’ve got an occasion to look into, was pretty messy. Simple web pages usually are build of chunks of JavaScript code used to bound existing libraries and perform simple logic tasks. Everything is coupled, any kind of logic and DOM manipulations are mixed together. This is the place, where unicorns live and magic happens. But if you’re into rich client side applications and frameworks such as Knockout.js, this is not an option. Why?

Knockout.js, AngularJS, Backbone and other MV* frameworks are dedicated to create a web applications. This literaly means, that your client page is an application rather than an ordinary page, rendered only to display the data. There will be probably a lot of code and logic bound to HTML on the page. If you will manage your code in unstructurized manner, you’ll soon find yourself in spot, where any further changes will the a depressing, time-consuming nightmare.

To be able to manage a large chunks of code, you will need to decouple your JavaScript logic into layers. Beacuse Knockout doesn’t provide any application layers off hand, responsibility of creating them lies on you. In rest of the post bellow I want to share my personal experiences developed during many months spent of using Knockout in production environment. Layers described by me can be exactly mapped onto specific patterns/groups of patterns and are described from top to bottom, beginning from layer used for server communication, through data management, HTML page partitioning to core used to bound everything together.

Gateway

The main goal of the Gateway object is to abstract server API to look like an ordinary JavaScript function. We would like to call the service in form of usersApi.getUserById(1) rather than cryptic $.post(''api/users', { id: 1 }). In my opinion this is more natural and gives us an easier way for further refactoring. What else can gateways do?

First of all, they should be able to hide necessity of resolution parametrized URLs from view models. They should be able to resolve them or have some helpers attached (think about eqivalent of UrlHelpers, path methods etc.).

In most of the cases I’ve met, server communication is done by traditional ajax requests through jQuery ajax or similar calls. Since those functions always returns jQuery promises as a result, you may find that this is not what you want. Maybe you need a more detailed informations or a custom wrapper around promises. Or if you use RxJS, you probably may want Rx.Observable objects. For all of these cases Gateway is good place to implement.

Gateways could be also used to perform mapping of JSON into fully qualified JavaScript objects you may want to use. This includes things like serializing/deserializing dates, adding additional computed properties, adding/removing recursive dependencies or even changing entire structure of object to beter fit our needs. From Knockout point of view, we can wrap/unwrap objects into ko.observables directly at this layer.

When your data manipulation and mapping logic become more and more complex, consider using a dedicated Factory/Mapper objects to maintain code decoupling.

Data source

Data sources (or Data Access Objects) are alternatives to gateways, since they serve similar purpose, but provide much more complex mechanisms. When we speak about data represented on the page, we’ll probably see problems associated with incomplete data representation on client side. Paginated tables, autocomplete suggestions, calendar pages, infinite scrolls etc. When used with remote source, all of these use server side requests to get data to be shown to end users. But on large data volumes we never retrieve all of the informations, instead using only those records, which need te be displayed. One of the roles of data sources is to store and manage data received this way, so the next time user goes back to previously displayed page or gets subset of records already provided, we may restore it from the local cache rather than repeating request to the server.

If you want to see a possible ways to implement this pattern, I would recommend you to look at some of the existing implementations, like:

All of them provide interesting point of view of what separated data source managers are capable to.

Among other advantages of data source separation we could mention sharing of common data between view models, which should not reference too each other directly, but also managing data objects lifecycle. Fetching data from the server, and synchronizing changes made localy by the client could be done easily this way.

When it comes to data objects, I’ve noticed that for purposes of data manipulation on the client side it’s nice to have some kind of universal identifiers to manipulate enities. Those identifiers should uniquely identify single entity among all others on the page – this means, that database identifiers from the JSON object representing server side entities may not be sufficient, since in many cases the records id’s (at least when we speak about relational databases with non-UUID primary keys) are guaranted to be unique only in single table/collection scope.

In my case good solution of this problem seems to be an additional object property – lets call it $id – which serves only client side logic (server may ignore that value) and it’s combination of unique identifier of the entity type and single entity identifier. Since it’s called the same among all data objects in client side application, no matter of their type, we may also definie universal comparison operators and function for fetching and data integration. To do so it’s also necessary that $id has to be generated in deterministic way – no matter how many times we create a JavaScript representation of the same database record, it should allways have the same $id value.

Partial View Models

Partial view models are used to separate model-view binding in domains of interests. Instead of unorganized bindings of all observed properties to single God Object, remember to use smaller pieces which actually fits a concrete parts of your page – menus, navbars, forms, modal windows etc.

Don’t ever mix a multiple view models in scope of single view component. The only exception from that rule is when you need to manipulate current view model in it’s parent context, but even in that case you shouldn’t access higher than direct parrent of current VM. If you do, that usually means, something is wrong.

Avoid referencing between view models, especially when they share the same hierarchy level. View models should be an independent units of work. They don’t need to know details of other view models to perform requested operations. Use Knockout contexts or dedicated objects as an inter-communication layer and share them between view models, when some message passing is needed.

Don’t create large nested objects inside view models. Inject them through constructors instead. Knockout view models lifetime is much longer than AngularJS controllers, but it’s still a better solution to share large objects and – if they come with a lot of logic – to decouple them from view model. This also includes objects used to communicate with external world.

Application root

Since Knockout allows you to use only one View Model as root for whole page, my advice is to create dedicated view model, which won’t be used with any visible parts of the page itself. It’s role is to serve as a container for actual view models used to display data on the page and to provide universal features to be used by everyone. For me this option remains true even for small ingerention of Knockout logic into the page, because in the world of changing requirements formally small pages may grow rapidly in very short amount of time.

When comes to integration of partial view models and application root, usually it’s sufficient to create all partial VMs on root level. View models can be nested in large tree structures, but don’t overuse this feature. Try to keep your view models dependency scopes as flat as you can. Application root is a good point to handle inner components creation and lifecycle. That also means, it should be able to access and provide all objects – gateways, data sources, factories, event buses, AJAX handlers etc. – directly to view models.

Appendix: Events and Pub/Sub pattern

There are few more things I wish to present in this post. One of them is a Publish/Subscribe pattern and event processing. It isn’t bound to any specific layer since all of them can get advantage of using it. I also found it the best way of dealing with communication between various Knockout view models.

Below I will show one of the simplest implementation used to handling custom events. If you want to be able to use more advanced techniques, you probably want to look for some dedicated libraries such as RxJS.

var EventStream = function(){  
    this._channels = {};    // this could be made private

    // subscribe to channel
    this.$on = function(channelName, callback){
        if(typeof callback === 'function'){
            var channel = this._channels[channelName];
            if(!channel)
                channel = this._channels[channelName] = [];
            channel.push(callback);
        }
    };

    // unsubscribe from channel
    // this is tricky since anonymous functions, once subscribed cannot be removed
    this.$off = function(channelName, callback){
        var channel = this._channels[channelName], i;
        if(channel && (i = channel.indexOf(callback)) > -1){
            channel.splice(i, 1);
            if(!channel.length)
                delete this._channels[channelName];
        }
    };

    // publish an event
    this.$trigger = function(channelName, event){
        var channel = this._channels[channelName];
        if(channel)
            for(var i = 0; i < channel.length; i++){
                try {
                    channel[i](event);
                } catch(e){
                    // an error occurred in subscriber function
                }
            }
    };
}

Since we have whole event pub/sub feature in one separate prototype, we can now implement it in any object we wish, either through composition or as a mixin. Additionaly we can use globaly shared instances of EventStream in similar fashion we use an event buses. For Knockout applications there is also an alternative in form of knockout-postbox.

Final thoughs

I want to end with a few short advices:

  • All of my observations are based on observations of using Knockout and MVVM in non-SPA paradigm. As I’ve said in previous posts, I wouldn’t recommend Knockout for creating single page applications, because there are a lot of alternative frameworks, which suits better for this purpose.
  • Knockout-validation library – I’ve found it pain in the ass almost everytime, I’ve needed to create anything more complex than basic, flat structure validation. There are a lots of problems when it comes to nested objects validation, nullable objects and dealing with validation results caches – which btw. cannot be accessed via library API. So if you are determined to use it, consider yourself warned.
  • Use unit tests any time you can. This not only will allow you to catch more potential errors (which are more likely to exist in language such as JavaScript) but are also a nice way to check if your code blocks are properly separated. And better prepare yourself, because client side logic tests are much more difficult to write than their backend cousins.
  • Create a common prefix for properties used as helper fields and methods, but not directly responsible for view model page manipulations. I’ve already shown examples such as $id field and event stream methods with $ prefix. I’ve found them quite usefull, but I don’t want refer to them from view data-bind attributes or server side. They should remain transparent for both of these.
  • I didn’t mention about any kind of Service layer, used for performin business logic. The reason is simple – unless you’re creating SPA with offline editing capabilities, due to reliability and security reasons you probably never wan’t to inject a business logic into frontend.

And last but not least. There are no universal rules. Form your own point of view, appropriate to your problems.

O pomyłkach i wnioskach z pracy w ASP.NET MVC

O wzorcach projektowych w ASP.NET MVC słyszał chyba każdy. Większość z nas przynajmniej raz widziała jakiś filmik instruktażowy bądź wideokonferencję promującą stosowanie właściwych wzorców na tej platformie. Jednakże po opanowaniu teorii przychodzi wreszcie pora na to, aby wcielić ją w życie. Co się wtedy okazuje? Bardzo często wychodzi na jaw, że zastosowanie poznanych praktyk w prawdziwym życiu sprawia problem, a kolejne miesiące programowania w myśl jakiejś metodyki prowadzą do ostatecznej refleksji będącej zgubą programistów: zrobię cokolwiek byle zadziałało.

W tym poście spróbuję opisać najczęstsze błędy, z którymi przyszło mi się zmierzyć – również te wynikające z ograniczeń technologii, ale przede wszystkim będące skutkiem niewłaściwego podejścia do problemu.

Twoja encja ≠ Twój model

Zasadniczym błędem (lub raczej skrótem myślowym) jest założenie, że każda klasa mapowana przez ORM na tabele może służyć jako model przekazywany bezpośrednio do widoku. Nie znaczy to, że jest to nie możliwe, jednak opcja ta jest z reguły nadużywana. Wynika to poniekąd ze stylu programowania wyuczonego z tutoriali z cyklu “wyklep CRUDa w 5 min.”. Piękne i proste, jednak nie mające wiele wspólnego z problemami dnia codziennego. Z drugiej strony jest to wina samego lenistwa programistów oraz przeświadczenia, że faza projektowania z rozpiską architektury chociażby na kartce papieru jest tylko dla kobiet i leszczy ;)

Pytanie brzmi: kiedy należałoby porzucić modelowanie z encji na rzecz dedykowanych klas POCO? Prawda jest taka, że zależy to od przypadku i wymaga odrobiny doświadczenia.

  • Jedną z podpowiedzi może być poziom zagłębienia zależności. Im jest on głębszy, tym bardziej wykorzystywana przez nas klasa odbiega strukturą od modelu wymaganego przez widok. Przykładowo już 2 poziom zagłębienia np. Model.Products.SelectMany(p => p.Orders) może świadczyć o tym, że dana encja nie jest właściwym kandydatem i powinna zostać zmapowana na dedykowaną do tego celu klasę.
  • Innym przykładem może być sytuacja, w której nasz model wykazuje pewien związek z regułami biznesowymi. Przykładowo częstym sposobem reprezentacji okresu czasu powiązanego z danym obiektem jest dodanie do modelu dwóch pól określających granice czasowe. W tym momencie pojawia się jednak pewien dysonans między definicją biznesową (okres czasu jest pojedynczym obiektem) a rzeczywistą implementacją (okres czasu to dwa generyczne pola dat). Jeżeli logika biznesowa silnie bazuje na danej definicji np. przedział czasowy często pojawia się w kontekście wykonywanych operacji, wtedy możliwe, że lepiej byłoby wyodrębnić ją do osobnej klasy.
  • Jak powszechnie wiadomo, we współczesnym świecie aplikacji WWW wymagania klientów są jednymi z najbardziej zmiennych elementów systemu. Możliwość oddzielenia modeli od encji wspiera ten trend, ponieważ o ile encje są powiązane ze schematem bazy danych (przez co są znacznie mniej podatne na zmiany ze względu na konieczność utrzymania spójności z istniejącymi danymi), o tyle modele wykorzystywane przez nas w aplikacji mogą być swobodnie modelowane do naszych potrzeb.

Twój ViewData = Twój Model

W przypadku niektórych frameworków model jest zdefiniowany w sposób jasny i jednoznaczny. W przypadku ASP.NET MVC nie jest jednak tak łatwo, ponieważ otrzymujemy tutaj więcej niż jeden sposób dostarczenia danych do widoku. Mowa tu oczywiście o ViewData. Wg. mnie obiekt ten, jakkolwiek przydatny, jest podstawowym złamaniem wzorca MVC w ASP.NET MVC. Dlaczego? Ponieważ  prawda wygląda tak, że niezależnie od zdefiniowanych przez ciebie klas, prawdziwy model ma zawsze tylko jeden typ: ViewDataDictionary.

Czy to źle? Niekoniecznie, zależy od przyjętego podejścia. Co z tego wynika? W przypadku modeli zwracanych przez formularze zazwyczaj przyjmuje się, że generyczny model powinien zawierać tylko te dane, które zostały wprowadzone przez użytkownika. Tzn. że informacje takie jak opcja wybrana przez użytkownika z listy powinna być częścią modelu podczas gdy sama lista dostępnych opcji powinna być przekazywana za pośrednictwem ViewBag/ViewData. Naturalnie w przypadku, gdy parsujemy model do postaci JSON przekazywanej do klienta, ta zasada nie dotyczy.

Nic nie znaczące Error Messages

Jednymi ze gorszych chwil w życiu programisty, są sytuacje, kiedy trzeba obsłużyć zgłoszenie o błędzie w aplikacji. Zdarza się, że zaglądamy wtedy do logów (o ile taką informację zalogowaliśmy ;) ), aby odnaleźć jakieś przydatne informacje, które pozwolą nam zidentyfikować naturę problemu. Jakże wielkie jest rozczarowanie, gdy jedynym hintem jaki wtedy otrzymujemy jest: Object reference not set to an instance of an object. Bardzo rzeczowa i jednoznaczna informacja wśród kilkuset linii kodu wymagających zbadania.

Innym ciężkim przypadkiem jest logowanie niewystarczającej ilości informacji. Przykład (blok try-catch jest czysto poglądowy):

try  
{
    ...
    var product = productRepository.GetById(id);
    if(product.Status != ProductStatus.Finished)
        throw new InvalidStatusException("Provided product has invalid status");
    ...
} catch(Exception e) {
    logger.Log(e.Message);
}

Co jest złego w tym przypadku? Wyobraźmy sobie, że dostajemy zgłoszenienie, o błędzie a w logach jedyną informacją jest: Provided product has invalid status. Czy wiemy o jakim statusie mowa? Czy wiemy o jaki produkt chodzi? Nie mamy żadnych informacji pozwalających zidentyfikować dany przypadek, mimo że wszystko co potrzebne mamy 2 linijki wyżej w kodzie źródłowym naszej aplikacji.

Stąd mój apel: nie bądź leniwcem, minuta pracy teraz pozwoli ci zaoszczędzić godziny problemów później.

Too thin controllers, too fat services

Fat models, thin controllers jest zwrotem często używanym w świecie MVC. Często jednak wynikiem utrzymania tej reguły jest zjawisko, które sam określam jako papierowe kontrolery. Weźmy na przykład następującą akcję MVC:

[HttpPost]
public void ToggleUserBan(bool activate)  
{
    this.userService.ToggleUserBan(activate);
}

Na czym polega błąd? Prawdopodobnie metoda ToggleUserBan w serwisie jest przypadkiem zbyt szczegółowym. Daje to podstawy do przypuszczenia, że architektura aplikacji w którymś momencie się posypała. Zajrzyjmy więc do naszego hipotetycznego IUserService:

interface IUserService {  
    void ToggleUserBan(bool flag);
    IEnumerable<User> GetAllUsers();
    IEnumerable<User> GetActiveUsers();
    IEnumerable<User> GetBannedUsers();
    // ...kolejne 70 metod
}

Jeżeli widzisz taki interfejs, wiedz że coś się dzieje. To z czym mamy do czynienia to nic innego, jak zwykłe zamiatanie brudu pod dywan. Pseudorozwiązanie polegające na przeniesieniu proceduralnego makaronu w miejsce, w które rzadziej się zagląda. Jest to częsty rezultat braku rewizji kodu i testów jednostkowych, oraz samowoli programistów.

Garść innych porad

  • unikaj static classes – utrudniają one modularyzację systemu i wprowadzają twarde powiązania, z których bardzo ciężko jest potem zrezygnować. Extension methods są w zasadzie jedynym zastosowaniem dla statycznych klas, dla jakich sam znajduję użytek.
  • unikaj partial classes – dopuszczalne tylko w wypadku, gdy rozszerzasz klasę generowaną przez zewnętrzne narzędzia (co swoją drogą samo w sobie jest złym pomysłem ale o tym może kiedy indziej ;) )
  • w przypadku zmiennych używaj nazw, które pozwalają określić ich typ i przeznaczenie – różnego rodzaju skróty oszczędzają dosłownie kilka sekund podczas pisania tylko po to, aby w przyszłości przedłużyć rozszyfrowywanie kodu przez kogoś innego o kilka minut. Pamiętaj, że w życiu programisty kod czyta się częściej niż pisze.
  • podczas zwracania kolekcji zwracaj najmniejszy interface, który umożliwia wykonanie zadania – nie ma sensu wymagać aby argument był listą, jeżeli jedynym wykonywanym na nim działaniem jest foreach
  • jeżeli zwracasz string lub kolekcje nigdy nie zwracaj nulli – zawsze używaj string.Empty lub Enumerable.Empty<>
  • nie sprawdzaj czy enumerator jest pusty przy pomocy Count() – używaj Any(). W przypadkach kiedy potrzebujesz porównać ilość argumentów w enumeratorze z konkretną liczbą np. list.Count() > 3, warto zastanowić się nad użyciem wzorca LazyCounter

Garść pro tipów przydatnych podczas tworzenia aplikacji

Od jakiegoś czasu myślałem o zebraniu w garść przemyśleń związanych z rozwojem projektów, bazując na doświadczeniach w aplikacjach, przede wszystkim biznesowych, w produkcji których przyszło mi uczestniczyć. Ponieważ pamięć jest zawodna i nie wszystko co chciałem wymienić udało mi się spamiętać i ubrać w słowa, być może w przyszłości będę kontynuował ten wątek.

Z góry zaznaczam, że tematy takie jak testy jednostkowe czy automatyzacja, celowo zostały tutaj przeze mnie potraktowane marginalnie. Jest tak dlatego, ponieważ są one wałkowane bez przerwy w wielu artykułach i każdy programista powinien się z nimi do tej pory zapoznać. Punkty jakie tutaj poruszam mogłby dotyczyć także tych dziedzin, postanowiłem jednak skupić się na odrobinę innych aspektach.

1. “Jesteśmy jedną rodziną, mamy wspólne korzenie”

Naturalną cechą aplikacji webowych rozwijanych w ramach środowiska .NET jest ich podział na wiele różnych projektów. Nie jest to wymóg, jednakże z reguły zdecydowanie pomaga w organizacji oraz w trakcie późniejszego wdrażania rozwiązań. To co jednak uznałem za warte przypomnienia to wzajemne powiązania pomiędzy projektami. Mówiąc zaś dokładniej, przydatność stworzenia wspólnej biblioteki-korzenia, dowiązywanej przez wszystkie pozostałe projekty w aplikacji.

Ma to kilka prostych przyczyn. Po pierwsze zdaża się, że musimy zaimplementować pewną funkcjonalność w kilku bibliotekach, będących na podobnym poziomie zależności, których jednak nie możemy powiązać ze sobą np. ze względu na rekurencyjne zapętlenie zależności – tutaj wspólny “korzeń” okazuje się nieoceniony. Po drugie, w trakcie pracy z aplikacją nieraz powstaje chęć stworzenia własnego DSLa bądź zestawu rozszerzeń upraszczających pracę z daną platformą bądź językiem. Ileż to razy rodziła się ochota na dodanie extension method, której brakuje nam w istniejących już klasach .NET? Tutaj również możliwość współdzielenia tego typu funkcjonalności jest bardzo przydatna.

Idea wspólnego “korzenia” przydaje się również kiedy mowa o klasach wyjątków. Dobrą praktyką w trakcie definiowania aplikacji jest wywoływanie własnych wyjątków, które mogą informować nie tylko o błędach w operacjach logicznych systemu, lecz również logice biznesowej jako takiej. Moim zdaniem wszystkie takie customowe wyjątki powinny mieć wspólną klasę bazową. Dzięki temu w późniejszych fragmentach aplikacji będziemy mogli bez problemu wychwytywać te z nich, które stworzyliśmy sami na potrzeby naszego systemu i odpowiednio na nie reagować – przekształać do postaci czytelnej dla końcowego użytkownika, logować itp.

2. Atomic frontend design

Atomic design to koncepcja projektowania elementów HTML w sposób uporządkowany na bazie kompozytów. Nieraz w życiu codziennym zdarza się nam określać komponenty strony w dość ogólny sposób, pozostawiając szczegóły implementacji na “doprecyzowanie później” ;) W rezultacie kończymy w morzu (lub raczej szambie) znaczników o mgliście oznaczonych brzegach. Ponieważ HTML na stronach może mieć bardzo rozrośniętą postać, którą jako programiści też będziemy musieli utrzymywać, warto zadbać też o ten aspekt aplikacji.

Idea atomic designu skupia się własnie na wiązaniu elementów HTML w kompozyty, które z kolei są łączone ze sobą dalej w kolejne, bardziej abstrakcyjne struktury. Więcej szczegółów na ten temat możecie dowiedzieć się tutaj. W praktyce warto poznać to podejście już teraz – w obecnej chwili widać wyłaniający się coraz mocniej trend, który w przyszłości może poskutować nowym standardem umożliwiającym definiowanie własnych znaczników HTML, mających bezpośrednie wsparcie ze strony silnika renderującego.

Chcąc wspomóc developerów i przygotować współczesne aplikacje webowe do nadchodzących standardów, inżynierowie Google’a stworzyli projekt polymer (czerpiący m.in. z koncepcji atomic designu), którego zadaniem jest zbudować odpowiednią platformę abstrakcji z istniejących już rozwiązań: HTML, Javascriptu oraz CSS. Zgodnie z ich przewidywaniami wraz z rozwojem przeglądarek funkcje oferowane przez tą bibliotekę mają w przyszłości zostać zastąpione specjalizowanymi, natywnymi odpowiednikami, zaś zadaniem polymeru jest umożliwić obecnym aplikacjom kompatybilność z dopiero powstającymi technologiami. Ciekawostka: mimo, że AngularJS stanowi oddzielny projekt, zapowiedziano już że w kolejnych wersjach będzie on coraz bardziej integrowany z polymerem.

3. Stwórz własną platformę abstrakcji…

Kolejna kwestia wynika z prostej tendencji uzależniania logiki aplikacji od wykorzystywanych bibliotek. W praktyce skutkuje to twardym związaniem naszego systemu z konkretnymi rozwiązaniami – które w przyszłości mogą stracić wsparcie, okazać się przestarzałe lub niewystarczające do naszych potrzeb. Taka monolityczna budowa nie jest przychylna zmianom, a jak powszechnie wiadomo klienci lubią wpadać na nowe pomysłu i zmieniać swoje zdanie.

Stąd też idealnym rozwiązaniem jest stworzenie klasycznej płaszczyzny abstrakcji, całkowicie izolującej naszą logikę biznesową, która stanowi jądro każdej aplikacji biznesowej, od zewnętrznych platform, realizowanych pośrednio jako obiekty proxy/adaptery. Piszę idealnym, w praktyce jednak rzadko takie rozwiązanie okazuje się w 100% możliwe. Warto jednak poświęcić mu trochę uwagi – również z perspektywy modularyzacji i możliwości testowania.

4. … ale nie przeginaj z warstwami

Pamiętaj, że każda dodatkowa wartwa abstrakcji z jednej strony umożliwia ci podzielenie problemu na prostsze, bardziej ogólne definicje (a ludzie z natury lubią pojmować świat ogólnikowo), z drugiej strony jednak stanowi jednocześnie kolejną barierę w optymalizacji.

To co warto przypomnieć, to fakt, że tworzenie aplikacji to proces, w którym wymagania zmieniają się w czasie. Produkcja oprogramowania nie jest jednym z konkursów algorytmicznych, gdzie wszelkie bariery i wartości graniczne są niezmienne i podane z góry. To co dziś świetnie się sprawdza, jutro może okazać się niewystarczające.

Ważnym czynnikiem jest odpowiednie zdefiniowanie problemu i dobór właściwych wzorców i rozwiązań. Jako programiści nieraz generalizujemy pewne problemy tak, aby dało się je rozwiązać przy pomocy istniejących technologii, kosztem rzeczywistej złożoności całego systemu. Dla zainteresowanych proponuję obejżeć wykład Grega Younga na ten temat.

Wielowarstwowe aplikacje stanowią pewien problem, kiedy przychodzi do optymalizacji. Nie oznacza to jednak, że budowa z podziałem na warstwy jest zła. Jest wygodna z punktu widzenia programisty i projektowania koncepcji rozwiązań dla problemów postawionych przed systemem. Z drugiej strony jednak każda aplikacja posiada pewne punkty zapalne – wymagające dużej wydajności – które będą wymagać niestandardowego trakowania, w tym też odejścia od wcześniej przyjętych koncepcji i zwrotu w stronę rozwiązań bardziej nisko poziomowych. Dobrze, aby aplikacja umożliwiała pewien sposób na osiągnięcie tego celu bez zaburzania reszty konstrukcji.

Jednym z możliwych kompromisów jest wielopoziomowy caching. Zamiast przebijać sie przez kolejne płaszczyzny abstrakcji w celu możliwości operowania na bardziej niskopoziomowych mechanizmach, cache’ujemy uzykiwane wartości na poszczególnych warstwach. Wielopoziomowy cache umożliwia też przyrostowe skalowanie wydajności w zależności od potrzeb.

5. Kradnij…

… moc obliczeniową maszyn klienta. Jest to bardzo dobre podejście, ponieważ wykonywanie części logiki po stronie przeglądarki nie dość, że odciąża serwery, za które musimy płacić, to dodatkowo stanowi rozwiązanie o wiele bardziej skalowalne, ponieważ ogólna ilość dostępnej mocy obliczeniowej rośnie wraz z liczbą maszyn wysyłających żądania na serwer. Stąd też część obliczeń, takich jak renderowanie dynamicznego HTMLa, czy preprocesowanie modelu danych od razu do postaci przystępnej do obliczeń po stronie serwera, można wykonywać bezpośrednio w przeglądarce.

6. Oszukuj

Co mam przez to na myśli? Po pierwsze powtarzam: cache’uj dane. W świecie aplikacji na platformie .NET często jest to opcja marginalizowana. W wielu przypadkach dopuszczalne jest, aby użytkownik zobaczył przybliżone dane. A co jeżeli nie są one aktualne? Keep calm and oj tam oj tam ;)

Problem, z którym się też spotkałem, to stosowanie prymitywych cache’ów w miejscach, w których ciężko określić górną granicę przyrostu danych. Tak, zwykły .NETowy słownik może wystarczy w twoim środowisku developerskim, ale w momencie, gdy za rok dane pompowane do niego na produkcji będą liczone w setkach tysięcy (lub więcej) obiektów, wszyscy na własne oczy zobaczą, że wyprodukowałeś trabanta w cenie porsche. Technologie sprawdzone na polu walki, takie jak Memcache i Redis są tutaj, gotowe cię wesprzeć. Korzystaj z tej możliwości.

Po drugie pamiętaj o złotej zasadzie – czego user nie dotknie, tego sercu nie żal. Przykład-anegdota: swego czasu aplikacje na urządzenia Apple były podawane jako wzór szybko uruchamiających się programów. Aplikacja, która na innych systemach uruchamiała się w kilka sekund, na iPhone była gotowa w ułamku tego czasu. Na czym polegał sekret? Otóż w rzeczywistości to, co widział użytkownik, było w rzeczywistości zrzutem ekranu z działającej aplikacji, bez jakichkolwiek możliwości interakcji. Dzięki temu użytkownik miał wrażenie, że aplikacja uruchamia się niemal natychmiast. W rzeczywistości, zanim wykonał on jakąkolwiek akcję w UI, mijało parę sekund, w trakcie których program miał czas, aby się załadować i podstawić pod “zaślepkę” faktyczny interfejs użytkownika.

Liczę na to, że lektura ta okazała się ciekawa i być może uda mi się w przyszłości opisać dalsze koncepty i przemyślenia.