Tag Archives: Clean Code

Plug-Ins und Instanzvariablen

Ein Plug-In für CRM implementiert das Interface “IPlugin” welches die Methode “public void Execute(IServiceProvider serviceProvider)” vorschreibt.
Diese Methode wird aufgerufen sobald das Plug-In ausgeführt wird und enthält die Logik. Aber wann wird die Plug-In Klasse instantiiert?

Auf MSDN ist im Artikel Write a plugin-in folgender Text, in einem mit “Important” markierten Abschnitt, zu finden:

For improved performance, Microsoft Dynamics CRM caches plug-in instances. The plug-in’s Execute method should be written to be stateless because the constructor is not called for every invocation of the plug-in. Also, multiple system threads could execute the plug-in at the same time. All per invocation state information is stored in the context, so you should not use global variables or attempt to store any data in member variables for use during the next plug-in invocation unless that data was obtained from the configuration parameter provided to the constructor. Changes to a plug-ins registration will cause the plug-in to be re-initialized.

Zusammengefasst heisst dass ein Plug-In wird einmal instantiiert und danach wird nur noch jeweils die Execut Methode ausgeführt.
Aus diesem Grund sollten keine Instanzvariablen verwendet werden.

Folgendes sollte also nicht gemacht werden.
Das Plug-In wird trotzdem funktionieren, es resultiert aber in einem unerwartetem Verhalten.

public class MyPlugin : IPlugin
{
    private ITracingService tracingService;
    private IPluginExecutionContext context;
    private Entity entity;

    public void Execute(IServiceProvider serviceProvider)
    {
        tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
        context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
        entity = (Entity)context.InputParameters["Target"];

        DoThis();
        DoThat();
    }

    private void DoThis()
    {
        // Do something (using tracingService, context and entity)
    }

    private void DoThat()
    {
        // Do something (using tracingService, context and entity)
    }
}

Der Code muss wie folgt geschrieben werden, damit er erwartungsgemäss funktioniert.

public class MyPlugin : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        var tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
        var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
        var entity = (Entity)context.InputParameters["Target"];

        DoThis(tracingService, context, entity);
        DoThat(tracingService, context, entity);
    }

    private void DoThis(ITracingService tracingService, IPluginExecutionContext context, Entity currentEntity)
    {
        // Do something
    }

    private void DoThat(ITracingService tracingService, IPluginExecutionContext context, Entity currentEntity)
    {
        // Do something
    }
}

Diese Lösung ist natürlich suboptimal und führt zu unleserlichem Code.
Eine bessere Option stellt die Verwendung einer privaten Klasse dar um die Logik zu kapseln. Somit können Instanzvariablen verwendet werden. Am besten werden gleich alle Abhängigkeiten zum Plug-In abstrahiert. D.h. anstatt den IPluginExecutionContext gebe ich nur die benötigten Eigenschaften über den Konstruktor von “PluginLogic” weiter. Somit lässt sich der Code auch ausserhalb eines Plug-Ins ausführen und/oder mit Unit Tests testen.

public class MyPlugin : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        var tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
        var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
        var entity = (Entity)context.InputParameters["Target"];

        var pluginLogic = new PluginLogic(tracingService, context, entity);
        pluginLogic.Run();
    }

    private class PluginLogic
    {
        private readonly ITracingService tracingService;
        private readonly IPluginExecutionContext context;
        private readonly Entity currentEntity;

        public PluginLogic(ITracingService tracingService, IPluginExecutionContext context, Entity currentEntity)
        {
            this.tracingService = tracingService;
            this.context = context;
            this.currentEntity = currentEntity;
        }

        public void Run()
        {
            DoThis();
            DoThat();
        }

        private void DoThis()
        {
            // Do something
        }

        private void DoThat()
        {
            // Do something
        }
    }
}

C# Keyword “var” – do and don’t

Seit C# 3.0 gibt es das “var” Keyword. Siehe MSDN.

Das var Keyword ist nichts anderes als eine implizite Typisierung, hat also nichts mit dem “dynamic” Keyword von C# 4.0 zu tun.

var i = 10; // implicitly typed
int i = 10; //explicitly typed

Eingeführt wurde das Keyword zusammen mit LINQ vorallem um anonyme Typen zu unterstützen.

var custQuery = from cust in customers
                where cust.City == "Phoenix" 
                select new { cust.Name, cust.Phone };

Das Keyword erfreut sich auch abseits von LINQ und anonymen Typen, in der Entwicklergemeinde, grosser Beliebtheit.

Anfangs dachte ich das “var” und ich keine Freunde werden können. Entwickler sind bekanntermassen Tipp-Faul und so wurde bald jede (mögliche) Variable mit “var” deklariert. Dieses Verhalten empfinde ich auch noch heute als nicht optimal da der Code unleserlich wird. Unter bestimmten Umständen lässt sich mit “var” die Lesbarkeit des Codes jedoch auch verbessern.

Do

Verwende “var” überall wo sich der Typ bei der Zuweisung erkennen lässt.

var sample1 = new myObject();
var sample2 = "myString";
var sample3 = 1;
var sample4 = (Response)myObject;

Don’t

Verwende “var” nicht, wenn sich der Typ bei der Zuweisung nicht erkennen lässt.

var sample1 = GetSomething();
var sample2 = MyFactory.CreateXY();

Auch sollte man nicht “var” anstatt Interfaces benützen, im glaube die Klassen-Kopplung werde dadurch reduziert. Als dankbares Beispiel sei List<T>, IList<T> und die “AddRange” Methode genannt.

Find Duplicates with Linq

Vorbei sind die Zeiten von “uneleganten” verschachtelten Schleifen!

public static class IEnumerableExtensions
{
    public static IEnumerable<Tuple<TKey, IEnumerable<TObject>>> Duplicates<TKey, TObject>(this IEnumerable<TObject> enumerable, Func<TObject, TKey> groupBy)
    {
        return enumerable
            .groupBy(GroupBy, (key, objects) => new Tuple<TKey, IEnumerable<TObject>>(key, objects))
            .Where(g => g.Item2.Count() > 1);
    }
}

Und hier noch ein Beispiel, wie die Methode angewendet werden kann.
Gegeben ist eine Collection von “Entity”.

var myDuplicates = entities.Duplicates(e => e.Id);
foreach (var myDuplicate in myDuplicates)
{
    Console.WriteLine(myDuplicate.Item1);
    foreach (var entity in myDuplicate.Item2)
    {
        Console.WriteLine("t{0}", entity["name"]);
    }
}