Tuesday, April 26, 2016

LIMO - LeastInMostOut methods

I've been experimenting with different guidelines to help me construct better code. In particular I've been pondering 'how to decide the best arguments for a method'. I started to consider this question a little more, while reviewing another colleagues code. I was struggling to understand what I didn't like about their code, and why. Finally I think I have a 'reason' why their code has a bad flavor to me.

The code was simple enough, but it took large, full agg-roots as parameters. What smelt funny was, only one little VO was needed, yet the class was now coupled to the full AR, without much reason.

As a result the class method was now coupled to the full AR, though it could have been much more reusable, simply by taking just the bit(s) needed. After some googling, and asking other seniors, I couldn't find anything to 'point at' and say, see this guy recons it's better not to couple the classes like that.

So now, here a post to 'point at'.

Guideline:

Methods should take least in arguments to do their job. They should return most out to callers (LIMO).

Why?
Taking the Least-in reduces coupling by only requiring the information needed by the method. It also improves readability by making it clear what the method needs. 

Return the Most-out data you can, this improves re-use of the method while reducing the need for change in the future (Open-closed principal).

Notes:

This does not mean every argument should be a string or some other native type. An arguments type help describes the constraints. For example a method "GetDataFromAServer()" should take a URI rather than just a String.

Another Trick I find useful is to look at how a method argument is used directly inside the method. If the argument is immediately converted to something else, then sometimes this is a clue that some refactoring may be needed.

I tend to return the 'most-data' so the caller can decided what is relevant to them. Some might think this leads to exposing internal class-structure, and I would agree. In my code 'returning the most' helps with unit tests, it also reduces re-coding. If / when I want to return less information, I generally have an interface to express this.

One last trick; at the moment I'm returning this on methods which would normally be void-return. The idea is that by returning this, I'm providing some info to the caller and making caller code flow more. I'm not wed to the idea, this does have a down-side. I now have some difficulty knowing if a method returns a new instance, or the same instance.


Thursday, April 14, 2016

Lifetime trick when migrating to mvc.net core 1

Recently while migrating projects from MVC.Net 5 to core 1 rc1 (mvc6 / vNext) I ran into an IoC problem. I was using Autofac as my container, and had just migrated some MVC filters. The filters were registered in the container using Autofac, and bound to MVC as global filters using ServiceFilterAttribute; following the post http://www.strathweb.com/2015/06/action-filters-service-filters-type-filters-asp-net-5-mvc-6/>here
Unfortunately at run time Autofac threw an error “No Scope with a Tag Matching ‘AutofacWebRequest’ “ . There is a reference to the problem on the Autofac site here
The error indicates either
  1. Trying to bind a long-life (singleton) object with a short-life (per request) object.
  2. Trying to resolve a per-request object before there is a request scope.
With these clues I finally worked out the problem, I have a combination of ‘binding’ approaches in my project.
Some services are bound using Autofac modules, here I was using InstancePerRequest() lifetimes. Other services were bound using the MVC container interface, in particular using IServiceCollection.AddScoped().
Using the Autofac MVC extensions, I add the MVC container bindings to the Autofac continer via ContainerBuilder.Populate(). This method maps the service registrations into Autofac. The mapping converts IServiceCollection Scoped bindings to InstancePerLifetimeScope().
Bingo
So some services were bound with InstancePerReqest(), while others with InstancePerLifetimeScope(). After consolidating my bindings to all use InstancePerLifetimeScope(), problem solved.

A short list of C# coding issues.

Injecting services into entities It been bugging me for a while now that to use services in a entity can be a bit of pain. It usually starts...