Wednesday, February 1, 2012

Specialize C++ constructor template parameter by base type

If we want to restrict C++ templated member function type, we can use return type:

class A
{
   template <typename T>
   typename std::enable_if<std::is_base_of<base, T>::value>::type function(T arg) {}
};

function will be considered only if T is derived from base. But what in case of A::A() constructor? There's no return value.

In this case we can use a dummy parameter with default value:

class A
{
   template <typename T>
   A(T arg, typename std::enable_if<std::is_base_of<base, T>::value>::type *dummy = 0) {}
};

This constructor will be used only for types derived from base, and we can still invoke it with single parameter. Even more, this constructor will still be used in implicit type conversions:

A variable = derived_from_base();

Friday, September 23, 2011

Char is not string

Did you know that
(list.Count() + ' ').ToString()
produces "33"
and
list.Count() + " "
produces "1 "?

Monday, March 28, 2011

Bind to entity Id

Since I started to use ASP.NET MVC, I enjoy model binders. They take a huge amount of irrelevant infrastructure code out sight, out of code, and out of mind, making it easier to create and maintain.

Now, one of the most helpful custom binders that I use if the one that binds entity by id.

The basic idea is that if we have
  public ActionResult Action(Entity entity) {}
or in view model
  public Entity EntityProperty { get; set; }
we don't have to write any code - entity will be bound to data by the binder, and we get either object and no errors, or null and failed ModelState.

  public ActionResult Action(Entity entity)
  {
    if (!ModelState.IsValid) { return ... }
  }

Here we have model state errors for all failed entities (invalid IDs from page, not found in DB, etc), without any single line of code (except our one-for-all binder).

In the views, I have something like
  ${Html.HiddenFor(x => x.EntityProperty)}

I can't use .EditorFor(x => x.EntityProperty.Id) because I will get wrong name in POST, so how do I get id in the input value? There're two approaches:
1. Tweak view template or html helpers, so that, when entity (derived from BaseEntity, for example) is passed to HiddenFor, it uses .Id instead of .ToString()
2. Override Entity.ToString() to return .Id.ToString()

Now, even if we do Html.EditorFor(Model) - for entire model - we get proper IDs for entities, and we get them back on POST - without any additional code at all.

Sometimes, we want to bind by another property, not Id. E.g. in REST/urls we want product name as parameters, not ids - because it looks better in URLs. Hard? Not at all, we just apply a different binder:

  public ActionResult Action([ModelBinder(typeof(EntityNameBinder))] Entity entity) {}

where our EntityNameBinder is:
   public class EntityNameBinder : EntityBinder
   {
      public EntityNameBinder() : base("Name") { }
   }
- that is, we just pass property name to bind to. Internally binder uses repository to find entities (simplified):
  var rep = ServiceLocator.Current.GetInstance(typeof(IBaseRepository<>).MakeGenericType(entityType));

  var boundValue = rep.GetType().GetMethod("FindOne").Invoke(rep, new object[]{ new Dictionary<string, object>{{propertyName, valueFromView}} });

This method works even for lists, we just tweak our custom binder a bit to detect IList<Entity>/Entity. And so we can use this in view models:
  public IList<Entity> EntityListProperty { get; set; }
once again without any single line of additional code.

Another usefull aspect of this approach, is that controllers code is very clean - model in, model view out - and thus very easy to test.

And, last but not least, one should never bind to entities directly - because it is not safe (remote user can bind to non-desired public properties, etc). With this custom binder, this is completely eliminated - there's no way to fill entity properties with values from the page, period. The workflow is always to create view model (whose properties get values from the page) and then use it populate entity (using AutoMapper, for example).

Wednesday, February 16, 2011

Matryoshka

Opening remote ftp in VirtualBox guest though virtualbox shared folder that points to /home/user/.gvfs is how we all work today.

I mean, virtualization über alles.

Friday, February 4, 2011

Moving to git

Yes, everybody did this already. And if you did not, hurry up! There's limited number of git repositories in the world, don't be late!

Git is a fantastic tool, and the only problem is that it looks too complex at first. But it is not, really, at least if you don't do fancy branching and merging within your 10 people scrum team. If you work alone (or in pair) it's much simpler and you can still benefit from it.

Here's why: whygitisbetterthanx.com/

Well, I just don't want to repeat what has been said so many times. But for me, it allows for much easier branching and merging. Often customers need a small fix to existing production version while I'm working on next sprint. git seems to have a lot of tools to make it easy - stash, easy branching, etc.

And it's fast.

Thursday, January 13, 2011

What matters

And frankly, ASP.NET MVC v1 is enough to go. No need for fancy stuff.

Because, what really matters is domain logic and code. ASP.NET MVC is just a thin framework, almost infrastructure. If it is >50% of your project, then your're doing it wrong. Move all the infrastructure out of the way (attributes, IoC, etc).

Wednesday, December 15, 2010

Verison

For many times I type to fast and get "verison" instead of "version" in my sources.

I wonder if that's how they got the name.