Avatar

Blog (pg. 8)

  • Published on
    The Lodash memoize function caches a function call and can vary the cache items based on the parameters. By default the "cache key" is the first parameter, but often it's useful to vary by all parameters. Here is a simple wrapper that will use a custom resolver to always cache based on all args passed to the function. With this code in place, simply import this file instead of lodash version into your consuming code.
    
    import _memoize from 'lodash-es/memoize';
    
    export default function memoize(func)
    {
        const resolver = (...args) => JSON.stringify(args);
    
        return _memoize(func, resolver);
    }
    
  • Published on
    To reduce the payload size of individual calls when loading up resources by ID, sometime you want to send multiple async requests in smaller batches. If we don't need to worry about local/remote resources (i.e. don't need intelligent partitioning or resource friendly approach), the easiest way is to fire off a load of tasks which consume a small batch from the superset. Here is a simple re-usable implementation:
    
    public class BatchContentRequestor<TId, TValue>
    {
        private readonly int _batchSize;
        private readonly Func<IEnumerable<TId>, Task<IEnumerable<TValue>>> _getContentAsyncFunc;
    
        public BatchContentRequestor(int batchSize, Func<IEnumerable<TId>, Task<IEnumerable<TValue>>> getContentAsyncFunc)
        {
            if (batchSize <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(batchSize), "Batch size must be a positive integer value.");
            }
    
            _batchSize = batchSize;
            _getContentAsyncFunc = getContentAsyncFunc ?? throw new ArgumentNullException(nameof(getContentAsyncFunc));
        }
    
        public async Task<IEnumerable<TValue>> GetContentBatchedAsync(IEnumerable<TId> allContentIds)
        {
            var allContentIdsList = allContentIds?.ToList();
    
            if (allContentIdsList == null || !allContentIdsList .Any())
            {
                return await _getContentAsyncFunc(allContentIdsList );
            }
    
            var allContentValues = new List<TValue>();
    
            var getBatchTasks = new List<Task<IEnumerable<TValue>>>();
            for (var batchStart = 0;
                batchStart < allContentIdsList.Count;
                batchStart += _batchSize)
            {
                var batchIds = allContentIdsList
                    .Skip(batchStart)
                    .Take(_batchSize)
                    .ToList();
    
                getBatchTasks.Add(_getContentAsyncFunc(batchIds));
            }
    
            await Task.WhenAll(getBatchTasks).ConfigureAwait(false);
    
            foreach (var completedBatch in getBatchTasks)
            {
                allContentValues.AddRange(await completedBatch.ConfigureAwait(false));
            }
    
            return allContentValues;
        }
    }
    
    You can call it with your superset and it will automatically hit your callback function with the batches of IDs, will collect the results and return the superset of values. If the calling code passes a null or empty value this will still be passed to your callback for handling, making this a transparent proxy for the calling code. e.g.
    
    var items = await new BatchContentRequestor<int, Item>(10, GetItemsByIdAsync).GetContentBatchedAsync(allItemIds).ConfigureAwait(false);
    
  • Published on
    Often when you create a class you need to override the the GetHashCode method, to easily compare instances using a custom Equals operator or to use the class as a key in dictionaries etc. I've seen various ways of doing this, but they are usually either wrong, slow, complex or difficult to remember (things like string concatenation, bit shifting, xor, using prime numbers etc.) As ever with programming, if there is a complex problem to solve then somebody has probably already solved it (and I don't mean copy/pasting GetHashCode algorithms from stack overflow!). One place this has already been done within the .NET framework is the Tuple type. The algorithm is fast, we don't need to understand it's complexity and given that it in the framework we can assume it's well tested. So my new favourite way of implementing GetHashCode is to simply project the fields into a Tuple!
    
    public class Example
    {
      private string someField1;
      private int someField2;
    
      public override int GetHashCode()
      {
          return (someField1, someField2).GetHashCode();
      }
    }
    
    This isn't quite so straightforward when one of your fields is a collection type, however it can be worked around using IStructuralEquatable as per this MSDN link: https://docs.microsoft.com/en-us/dotnet/api/system.collections.istructuralequatable?redirectedfrom=MSDN&view=netcore-2.2#remarks So as long as your collection types are backed by an Array, you can use the following syntax to generate your hash code based on the array values:
    
    public class Example
    {
      private string someField;
      private int[] someArrayField;
    
      public override int GetHashCode()
      {
          return ((someField, someArrayField) as IStructuralEquatable).GetHashCode(StructuralComparisons.StructuralEqualityComparer);
      }
    }
    
  • Published on
    From the beginning of 2018 I have taken the leap into self-employment. I am now working as a consultant/contract software developer through Pragmatech Software Solutions. Primarily I expect this will involve applying more of my technical expertise in coding and software development which is what I really enjoy and where I excel. I also hope to be able to help clients in any way I can such as providing input on solution architecture, software design, performance optimization, Azure cloud, VSTS, CI/CD, Agile or any other areas where I have experience!
  • Published on
    I was recently working with a React developer on a data driven single page application using an ASP.NET WebAPI backend. I wanted the API to be RESTful to simplify the design, since React can provide client side state and in fact is driven by application state and the API was only there to provide data and persistence. We decided to use the HATEOAS convention, of simply adding a "links" section to each of the objects, in order to inform the client of the available associated resource URIs. Based loosely on the HAL standards we agreed that we simply wanted to add some basic links within the normal JSON response as opposed to negotiating new media types etc. For this very basic requirement then, comes a very simple solution. I created a base class in my API Models folder which would support links:
    
    public class LinkModel
    {
        public LinkModel()
        {
        }
    
        public LinkModel(string href, string method, string rel)
            : this()
        {
            this.Href = href;
            this.Method = method;
            this.Rel = rel;
        }
    
        public string Method { get; set; }
        public string Rel { get; set; }
        public string Href { get; set; }
    }
    
    And then a generic class which would contain the payload object, or "content" and the "links":
    
    public class ContentWithLinks<T>
    {
        public ContentWithLinks()
        {
        }
    
        public ContentWithLinks(T content, IEnumerable<LinkModel> links)
            : this()
        {
            this.Content = content;
            this.Links = links;
        }
    
        public T Content { get; set; }
        public IEnumerable<LinkModel> Links { get; set; }
    }
    
    Each of my actions that wanted to use this strategy would return this type with the calculated links:
    
    [HttpGet]
    [Route]
    public IEnumerable<ContentWithLinks<DataSetModel>> GetAllDataSets()
    {
        return new ContentWithLinks<DataSetModel>[]
        {
            new ContentWithLinks<DataSetModel>(new DataSetModel("Example"), this.GetLinks("Example"))
        };
    }
    
    private IEnumerable<LinkModel> GetLinks(string dataSetName)
    {
        return new LinkModel[]
        {
            new LinkModel(this.Url.Link(nameof(this.GetAnalysisSchemaForDataSet), new { dataSetName = dataSetName }), "GET", "Schema"),
            new LinkModel(this.Url.Link(nameof(FiltersController.GetAllFilters), new { dataSetName = dataSetName }), "GET", "Filters"),
            new LinkModel(this.Url.Link(nameof(FilesController.GetAllFiles), new { dataSetName = dataSetName }), "GET", "Files")
        };
    }
    
    Using the "Url.Link" syntax ensure the route is calculated by ASP.NET. In fact, I went ahead and used the "nameof" operator too, to ensure any code refactorings of these methods would be taken in account automatically. In the client side the various links were then bound to the different actions a user could perform, which would trigger a call to the next URI in the workflow, generating more links and actions for the React components to bind.