Saturday, November 22, 2014

Ember.js sucess story

http://www.talentbuddy.co/blog/building-with-ember-js-at-groupon/

Tuesday, March 18, 2014

Asynchronous Repository Pattern

I've been thinking a bit about network and other I/O latency problems and the traditional repository pattern. Started toying with the idea that a repository facade could explicitly expose a "promise-like" interface like the following.


public interface IRepository<T, in U> where T: class, new()
                                          where U: struct
    {
        Task<T> GetById(U id);
        Task<bool> Save(T entity);
        Task<bool> Remove(T entity);
        Task<IEnumerable<T>> GetAll();
    }

Where T is the DTO and U is the underlying identifier type (int, Guid etc.)

This is all essentially client-side whereas the client is communicating with a resource (and perhaps resource is a better name than repository). So for instance, if I was communicating with a ReSTful service - my resource (or implementation of this particular pattern) could look something like the following.(This is currently implemented using RestSharp client using the ServiceStack.Text serializers)


public class RestfulClient<T, U> : RestClient, IRepository<T, U> where T: class, new()
                                                                     where U: struct
    {
        private readonly string _resource;
        private readonly ServiceStackJsonDeserializer deserializer;
        private readonly ServiceStackJsonSerializer serializer;
        private const string requestString = "application/json";
        private const DataFormat requestFormat = DataFormat.Json;

        public RestfulClient(string baseUrl, string resource)
            : base(baseUrl)
        {
            this._resource = resource;
            this.deserializer = new ServiceStackJsonDeserializer();
            this.serializer = new ServiceStackJsonSerializer();
            ServiceStack.Text.JsConfig.EmitCamelCaseNames = true;
            this.AddHandler(requestString, new ServiceStackJsonDeserializer());
        }

        private string UrlWithId(U id)
        {
            return string.Concat(this._resource, "/", id);
        }

        private RestRequest FormatRequest(string resource, Method method, T entity)
        {
            var req = new RestRequest(resource, method);
            if (entity != null)
            {
                req.RequestFormat = requestFormat;
                req.JsonSerializer = this.serializer;
                req.AddParameter(requestString, this.serializer.Serialize(entity), ParameterType.RequestBody);
            };
            return req;
        }

        public Task<T> GetById(U id)
        {
            var t = Task.Factory.StartNew(() => 
                this.deserializer.Deserialize<T>(this.ExecuteGetTaskAsync(FormatRequest(UrlWithId(id), Method.GET, null)).Result), 
                CancellationToken.None);
            return t;
        }

        public Task<bool> Save(T entity)
        {
            var t = Task.Factory.StartNew(() => 
                this.Execute(FormatRequest(this._resource, Method.POST, entity)).ResponseStatus == ResponseStatus.Completed, 
                CancellationToken.None);
            return t;
        }

        public Task<bool> Remove(T entity)
        {
            var t = Task.Factory.StartNew(() => 
                this.Execute(FormatRequest(this._resource, Method.DELETE, entity)).ResponseStatus == ResponseStatus.Completed, 
                CancellationToken.None);
            return t;
        }

        public Task<IEnumerable<T>> GetAll()
        {
            var t = Task.Factory.StartNew(() =>
                this.deserializer.Deserialize<IEnumerable<T>>(this.ExecuteTaskAsync(FormatRequest(this._resource, Method.GET, null)).Result), 
                CancellationToken.None);
            return t;
        }
    }


Instantiating the implementation could be as simple as:



var rc = new RestfulClient<ToDo, int>("http://localhost:53327", "api/v1/todos");
Consuming looks like:
rc.GetById(id).ContinueWith((todo)=> Console.Write(todo.Result.Title));
The nice thing is that the consuming client gets all the benefit of .ContinueWith (etc.) I'm not sure if I'm chasing dragons at this point - but I'm mulling it over...thoughts?