Alexander Beletsky's Development Blog: 2012-01

Agile Base Camp 2012

Past Saturday I was a part of big Ukrainian event Agile Base Camp: From Idea to Product. It's been organized by ScrumGuides, pioneers on Agile in Ukraine and organizers of famous Agilee series of conferences.

The conference named "From Idea to Product" and focused on product development issues. There was 3 stages there: Main, XP, UX. Main is for more or less common topics as budgeting, motivation etc.. XP is practical stage for developers and UX for user experience engineers. The program of conference was really interesting, but I spend all my day on XP stage (no surprise).

There were great speeches by Dmytro Mindra, Sergey Kalinets. Probably most valuable for me were ones by Vitaliy Stakhov and Anatoly Kolesnik, Vitaliy shared Hypermedia concepts of RESTfull systems and that looks very promising. Anatoly did great NoSQL introduction that is very actual at the moment. I also enjoyed Dmitry Efimenko speech about testing in product company. He did it in quite tough style, so crowd was a little shocked and kept silence till the last words. I got some interesting points for myself.

I did a talk about - Continues Delivery / Deployment / Production. This practical field is very interesting to me not only because I'm trying to build a product for that and I want to adapt for all project I work to.


alexander beletsky

I've got very nice feedback and questions after my speech, totally collected 15 donuts (a special cards that listeners give to speaker if they like the speech), so I was quite happy about. If you interested, here is my slides on speaker deck.


I really much enjoyed after party and evening we spent in Work'N'Roll, the co-working office of ScrumGuides. Appreciate organizers for that job and wish you good luck of all next events.

Convention based IoC configuration

What's your favorite IoC container framework? For quite long time I stick to Ninject. First time I read about it in Steve Sanders ASP.NET MVC2 book and it's my favorite container since then. But this blog post does not aim particular IoC framework, rather approach you can use. For code examples I'll still be using Ninject, through.

What's are conventions?

Convention over configuration is very popular trend nowadays. Many frameworks trying to adopt it, including ASP.NET MVC. In short, that means you are relying on some front-know conventions, like names of files, folder or classes and system does something meaningful, based on those conventions. Like, all controllers in ASP.NET MVC should have "Controller" postfix, so the framework is able to find and instantiate it.

Conventions make a developer's life a little easier, you are no longer spending efforts on configuration, instead following some simple rules.

What we have for IoC?

My "Shu" level of IoC containers learning was configuration based. This is something you learn at very beginning. So, in case of Ninject, sooner of later you have huge file with dependencies configuration:

/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
 kernel.Bind<ISettingsManager>().To<SettingsManager>();
 kernel.Bind<IDirectoryProvider>().To<DirectoryProvider>().InSingletonScope();
 kernel.Bind<ISetupFactory>().To<SetupFactory>();
 kernel.Bind<ITargetsObjectBuilder>().To<DefaultTargetsObjectBuilder>();
 kernel.Bind<ITargetsBuilder>().To<TargetsBuilder>();
 kernel.Bind<IBounceFactory>().To<BounceFactory>();
 kernel.Bind<ITargetsRetriever>().To<TargetsRetriever>();
 kernel.Bind<IConfigObjectBuilder>().To<ConfigObjectBuilder>();
 kernel.Bind<ILoggerFactory>().To<LoggerFactory>();
 kernel.Bind<IHashService>().To<HashService>();
 kernel.Bind<IAuthentication>().To<Authentication>();
 kernel.Bind<IConfigurationsFactory>().To<ConfigurationsFactory>();
 
 // More, more, more...
}

As more your application grows, as more services, repositories, factories you have. As long RegisterServices method becomes longer, as more you forgot to correct correct it after some new dependency added, so you see YSOD during application run.

But please, put your attention to interface and class names. What we have here - ISettingsManager and SettingsManager; IDirectoryProvider and DirectoryProvider.. ILoggerFactory and LoggerFactory. Do you see pattern here? Exactly, it is ["I" + entity name] for interfaces and [entity name] for implementation.

Here we go for "Ha" level of IoC and apply convention based configuration.

Convention over configuration

Let's take an advance of the fact above and shrink our configuration code. First of all, you need to get great extension for Ninject, called ninject.extensions.conventions.

After the package is installed, the simples Ninject start-up code ever would be:

/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
 kernel.Scan(scanner =>
     {
      scanner.FromCallingAssembly();
      scanner.BindWithDefaultConventions();
     }
  );
}

What it does? It has an abstraction called "scanner". You instruct scanner what to do. In this example, I said - take calling assembly and bind all interfaces to implementation class having Default conventions. The default conventions are ones that I shown above.

That's it, all those lines of code are simply gone away, since we rely on conventions and Ninject is aware how to deal with those conventions. If you added new dependency and followed convention, nothing you should do manually any more.

I have some questions!?

Ok, typically you have something little more complex. I'll try to predict some questions you might have.

I have a lot of assemblies in my application, but want only particular ones to be scanned?

You can easily use only assemblies that matches particular patterns, like:

private static void RegisterServices(IKernel kernel)
{
 kernel.Scan(scanner =>
     {
      scanner.FromAssembliesMatching("Candidate.*");
      scanner.BindWithDefaultConventions();
     }
  );
}

Is it only default conventions I can use?

No, you can specify your own rules. Scanner has BindWith method, that receives IBindingGenerator type. You can implement your own binding generator for custom conventions.

private static void RegisterServices(IKernel kernel)
{
 kernel.Scan(scanner =>
     {
      scanner.FromAssembliesMatching("Candidate.*");
      scanner.BindWith<MyCustomConventionsGenerator>();
     }
  );
}

What if I have several cases of convention violations?

You are still able to bind in exactly same way as before:

private static void RegisterServices(IKernel kernel)
{
 kernel.Scan(scanner =>
     {
      scanner.FromAssembliesMatching("Candidate.*");
      scanner.BindWith<MyCustomConventionsGenerator>();
     }
  );

    // classes that violates conventions
    kernel.Bind<IMyInterface>().To<MyImpl>();
}

What is I have dependencies in different assemblies?

Best thing is to go with Ninject modules. First, correct the scanner:

private static void RegisterServices(IKernel kernel)
{
 kernel.Scan(scanner =>
     {
      scanner.FromAssembliesMatching("Candidate.*");
                        scanner.AutoLoadModules();
      scanner.BindWith<MyCustomConventionsGenerator>();
     }
  );
}

Now, each assembly should include module instance:

namespace Candidate.Core
{
    public class CoreModule : NinjectModule
    {
        public override void Load()
        {
            // place convention-violation classes here
   // Bind&lt;IMyInterface&gt;().To&lt;MyImpl&gt;();
        }
    }
}

Another one good feature of Convention based IoC is - "Config and forget". Once done, use always and forget about manual binding once and for all.

I've heard about this on XP Days 2011 conference, by Mark Seemann. I think it's nice approach.. I adopt it and going to use in my projects.

Pre-announce of Release "Candidate"

For those, who already forgot what the candidate is I'll do a small reminder :). This is an application for Continues Deployment for .NET projects. I started the project at Hackatone that took place in summer 2011, in Kyiv. I liked the results I got there, so I didn't throw it away after the contest, but slowly progressed on that through last several months.


welcome

The goal of application is very simple. Provide you with easy to setup and use tool Continues Deployment. I'm still very confused now with all those terms - Continuous Deployment/Delivery/Production/Release.. but in general it is nothing more as next step of Continues Integration. Rebuild and retest the application and deploy it in case of successful results.


welcome

I'm building that in mind of my own needs, how I see it might work for my projects. My own projects are really simple ones, so the candidate is really simple now. Of cause, I would like to be as general as possible, to cover common needs. I'm pretty much sure it would be rewritten hundred of times to reach the level of mass adoption and I'm looking forward to that.


config

Yesterday, I reached very important milestone of candidate.net. It is now feature completed. I would like to stop on current functionality and show it to you. It would take some time to prepare website and instructions, but please stay tuned for official release of project!


config

By the way, I'm still looking for new name! It turns out that finding the good name, could be even harder than finding process running bugs. I would be really happy if you do such early contribution proposing some nice name. Please do not hesitate and share your ideas just in comments.

Using ASP.NET MVC Validation Mechanism without ASP.NET MVC

I get used to DataAnnotations for model validation very quickly. Indeed, it is great approach. You attribute you model with corresponding attributes, rest is done by framework. It is only ModelState.IsValid, all you have to do before starting working with model.

During implementation of some feature for candidate I thought to myself, that I need need exactly same validation for my model class, but out of MVC framework. Namely, for some model class, like Github.cs I just want to know, is it "configured" or not. And configured == valid in my context. Instead of writing custom code with checking all required properties to have some values I wished to do the same as ASP.NET MVC does, through DataAnnotations. It turned out to be possible and really easy.

Basic start

Assume you have such model:

public class SimpleModel
{
 [Required]
 public string SomeProperty { get; set; }
 
 [Range(0,50)]
 public int SomeAnotherProperty { get; set; }
}
    

If your goal is just to get answer "yes or no", you can create such function:

public bool ValidateSimpleModel(SimpleModel validate)
{
 return Validator.TryValidateObject(validate, new ValidationContext(validate, null, null), null);
}
    

Validator is a static class in DataAnnotations namespace. It takes target object, validation context and validation results collection. But due, to it just "tries" to perform validation, most of all parameters could be null.

Use validation results

If you need more specific information, like which field is exactly invalid you need to have ICollection<ValidationResult>

public ICollection<ValidationResult> ValidateSimpleModel(SimpleModel validate)
{
 var validationResults = new List<ValidationResult>();
 Validator.TryValidateObject(validate, new ValidationContext(validate, null, null), validationResults);
 
 return validationResults;
}
    

In case of invalid object it would return non-empy collection of ValidationResult, that would contain all relevant information.

Wrapping up to extension method

Finally, you can create simple extension extension method and apply DataAnnotations validation to any kind of object:

public static class ValidatorExtensions
{
    public static bool TryValidateObject(this object validate)
    {
        return Validator.TryValidateObject(validate, new ValidationContext(validate, null, null), null);
    }
}
    

So, the model could just have IsValid() method, like:

public bool IsValid()
{
 return this.TryValidateObject();
}
    

It works great for such simple task I need to accomplish.

Approval Tests: Locking down an output

We have seen how Approval Tests are useful for locking down some legacy code. You might say, that on practice we are having much more bigger problem, like some code that executes queries against the database. We need somehow to be able to work with that code, without worries of brake it down. Approvals could help here.

The case

Again I just imagine some legacy code that works with DB, it might look something like that:

public class ClassThatOutputsSomething
{
 private static Connection _connection;

 public void MethodThatProduceSomeResults(string parameterOne, int parameterTwo)
 {
  if (!IsConnectionOpened())
  {
   OpenConnection();
  }

  var connection = GetConnection();

  var value = HugeAndScarryLegacyCode.TheUgliesMethodYouMightEverSeen(parameterOne, parameterTwo, 'c');

  var query = string.Format("INSERT INTO TableName (SomeColumn) VALUES ({0})", value);
  connection.ExecuteQuery(query);
 }

    // ...
    

The MethodThatProduceSomeResults takes some arguments, call another method to get value and then store value to database. It will be problematic to tests what exactly is happening there. We might consider approach to check the difference in TableName before code execution and after, but we will go smarter and easier way.

Let's prepare the test for that code.

Tests

The great thing with Approvals is the tests are really elegant. Just 2 steps - DO and VERIFY.

[Test]
public void should_be_able_to_test()
{
 // DO
 var some = new ClassThatOutputsSomething();
 some.MethodThatProduceSomeResults('some_input', 221);

 // VERIFY
 Approvals.Approve(...);
}
    

But you can see, the problem here is that we don't have any return value of that method. Instead, it does something inside and keep that action in secret. We need some how to log all internal activities and than verify that log. Approval.Utilities contains exactly what we need.

[Test]
public void should_be_able_to_test()
{
 // DO
 var output = ApprovalUtilities.SimpleLogger.Logger.LogToStringBuilder();
 new ClassThatOutputsSomething().MethodThatProduceSomeResults('some_input', 221);

 // VERIFY
 Approvals.Approve(output);
}
    

I have just added logger ApprovalUtilities.SimpleLogger.Logger.LogToStringBuilder and do approve against it. But if I run this test I could see that output is just empty. Sure, we need to change MethodThatProduceSomeResults a little.

public class ClassThatOutputsSomething
{
 private static Connection _connection;

 public void MethodThatProduceSomeResults(string parameterOne, int parameterTwo)
 {
        // ...

        connection.ExecuteQuery(query);
        ApprovalUtilities.SimpleLogger.Logger.Event(query);
 }
    

So, in the place where query is being executed, we placed the logger and put exact some query inside it. Now if I run the test I will got application output, that I will approve and use those approved results after.

I'm not limited with only one place I could put logger. On practice, would more that one places to grab the results, as well as more that one argument for MethodThatProduceSomeResults method. By analysis of particular practical case, it is possible to place logger exactly where it's needed, plus prepare best matching inputs. Just for example: after code examination it might happen that parameterOne is ProductId, but parameterTwo is ProductPrice. In my test I could query the database to select all products and prices and call MethodThatProduceSomeResults in loop, to get all potential output. That approved test will give me much confidence during refactoring.

Conclusion

Locking down output is very powerful technique, you can use it for any kind of objects that are "hidden" inside legacy classes, like SQL or console outputs.

On Herding Code episode Llewellyn describes the case of some legacy project he worked on. There was a kind of report generator and it's code was just a big mess. He did copy of production database and put it in "Read-Only" mode. By running the report, he was able to find all places where code was accessing DB, since exception is thrown in that place. Putting in just the same log instructions as I did above, he managed to grab all SQL queries that run for that particular report. Everything were just in one file.

That's the good example of reaching 100% code coverage just with one test.