sobota, 16 sierpnia 2014

[C#|Visual Studio] Rhino Mocks

Idealny Unit Test to taki, który jest:
  1. atomowy (testujemy tylko jeden fragment funkcjonalności)
  2. deterministyczny
  3. powtarzalny
  4. niezależny od kolejności wywoływania innych testów 
  5. szybki (czas wykonania rzędu milisekund)
  6. łatwy do uruchomienia
 Problemem zawsze będą zależności. Przeważnie metoda poddawana testowi woła metody innych klas, które mogą wykonywać wolne operacje, np. łączenie się z bazą danych. Co więcej testowanie metod w ten sposób narusza zasadę atomowości Unit Testów.

W tym przypadku z pomocą przychodzi zasada Dependency Inversion. Zamiast wstrzykiwać do testowanego serwisu właściwe zależności, możemy na etapie UT wstrzyknąć inną implementację danego interfejsu wykonującą tylko tyle kodu, ile potrzebujemy. Problem polega na tym, że wraz ze wzrostem komplikacji właściwych serwisów musimy także utrzymywać kod mockowanych serwisów.

Tu z pomocą przychodzi Rhino Mocks - framework budujący dynamiczne mocki (wykorzystując obiekty proxy) na potrzeby naszych testów.

 Mockowanie rozpoczynamy od użycia klasy MockRepository, która stworzy nam mock dla dowolnego interfejsu. Mock taki będzie zawierał puste metody (dla metod zwracających void) lub metody zwracające wartość domyślną dla pozostałych metod z interfejsu.

Przykładowo mamy klasę InvoiceService, która woła jedną ze swoich zależności - InvoiceRepository.

public class Invoice
{
    public string Id { get; set; }
    public decimal Amount { get; set; }
    public string UserId { get; set; }
}

public interface IInvoiceRepository
{
    bool Store(Invoice entity);
}

public class InvoiceRepository : IInvoiceRepository
{
    public bool Store(Invoice entity)
    {
        //Long running SQL operation
        return true;
    }
}

public class InvoiceService
{
    private IInvoiceRepository _invoiceRepository;

    public InvoiceService(IInvoiceRepository invoiceRepository)
    {
        _invoiceRepository = invoiceRepository;
    }

    public void SaveInvoice(Invoice item)
    {
        var success = _invoiceRepository.Store(item);
        if(!success)
            throw new Exception("Unable to save");
    }
}

Chcemy zamockować interfejs IInvoiceRepository w ten sposób, by zwracał true, jeżeli podamy fakturę różną od null.

[Test]
public static void InvoiceService_ShouldCallInvoiceRepository()
{
    //Arrange
    IInvoiceRepository repositoryMock = MockRepository.GenerateMock<IInvoiceRepository>();
    repositoryMock.Stub(x => x.Store(Arg<Invoice>.Is.NotNull)).Return(true);

    Debug.WriteLine(repositoryMock.GetType().FullName);
    var service = new InvoiceService(repositoryMock);

    //Act
    service.SaveInvoice(new Invoice());

    //Assert
    repositoryMock.AssertWasCalled(s => s.Store(Arg<Invoice>.Is.Anything));
}

Na konsoli wypisze się: Castle.Proxies.IInvoiceRepositoryProxyc9859a0ce17d461faef8b8deb39a407c, ponieważ RhinoMocks korzysta z mechanizmu Castle.DynamicProxy.

Zamiast parametru Anything moglibyśmy podać referencję do obiektu faktury przekazywanej do metody SaveInvoice. Często zdarza się też tak, że metoda przyjmuje kilka parametrów, na podstawie których budowany jest obiekt. Tu z pomocą przychodzi mechanizm constraintów.

Rozszerzamy nasz serwis o dodatkową metodę:

public class InvoiceService
{
    //...
    public void SaveInvoice(string id, string userId, decimal amount)
    {
        SaveInvoice(new Invoice()
                        {
                            Amount = amount,
                            Id = id,
                            UserId = userId
                        });
    }
}

I za pomocą metody Matches podajemy warunki, jakie muszą być spełnione.


[Test]
public static void InvoiceService_ShouldCallInvoiceRepository_AndSaveInvoiceWithSameProperties()
{
    //Arrange
    IInvoiceRepository repositoryMock = MockRepository.GenerateMock<IInvoiceRepository>();
    repositoryMock.Stub(x => x.Store(Arg<Invoice>.Is.NotNull)).Return(true);
    string id = "12";
    string userId = "5";
    decimal amount = 100;

    var service = new InvoiceService(repositoryMock);

    //Act
    service.SaveInvoice(id, userId, amount);

    //Assert
    repositoryMock.AssertWasCalled(s => s.Store(Arg<Invoice>.Matches(d => d.Amount == amount 
        && d.UserId == userId)));
}

niedziela, 29 czerwca 2014

[C#|Visual Studio] AOP: Method Interception

Opakowanie metody możemy wykonać zarówno w Castle.DynamicProxy jak i przez Postsharp. Oba podejścia nieco różnią się od siebie.

W przypadku Castle zakładamy, że będziemy korzystać z kontenera IoC. Mamy prosty interfejs IMyInterface oraz prosty typ MyType. Rozpoczynamy od stworzenia interceptora, który będzie logował zdarzenia. Musi on dziedziczyć po interfejsie IInterceptor z przestrzeni nazw IInterceptor. Interfejs ten wystawia metodę Intercept.

public class LoggingInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("On Enter");
        try
        {
            invocation.Proceed();
        }
        catch (Exception)
        {
            Console.WriteLine("On Error");
            throw;
        }
        finally
        {
            Console.WriteLine("On Exit");
        }
    }
}

Pozostaje jeszcze skonfigurować odpowiednio kontener i można korzystać z typu opakowanego w intereceptor.

using (var windsorContainer = new WindsorContainer())
{
    windsorContainer.Register(Component.For<LoggingInterceptor>());
    windsorContainer.Register(Component.For<IMyInterface>()
                                    .ImplementedBy<MyType>()
                                    .Interceptors<LoggingInterceptor>());

    var type = windsorContainer.Resolve<IMyInterface>();

    type.Run();
}

W Postsharpie dziedziczymy po bazowej klasie OnMethodBoundaryAspect, która definiuje potrzebne nam metody wirtualne. Ważne, by nasz aspekt oznaczyć atrybutem Serializable.

[Serializable]
public class LoggingInterceptor2: OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs args)
    {
        Console.WriteLine("On Entry");
        base.OnEntry(args);
    }

    public override void OnException(MethodExecutionArgs args)
    {
        Console.WriteLine("On Error");
        base.OnException(args);
    }

    public override void OnExit(MethodExecutionArgs args)
    {
        Console.WriteLine("On Exit");
        base.OnSuccess(args);
    }
}

Nasza klasa jest atrybutem, który możemy umieścić nad definicją dowolnej metody.

[C#|Visual Studio] AOP: Wprowadzenie

Programowanie aspektowe powstało niejako w odpowiedzi na powtarzające się schematy pisania kodu takie jak na przykład instrukcje try-catch, transakcje, logowanie itd. Aby uniknąć kopiowania kodu wprowadzono komplementarne do OOP pojęcie aspektów. AOP wprowadza kilka ważnych pojęć:
  • cross-cutting concerns - funkcjonalności używane w wielu miejscach w systemie, np. logowanie zdarzeń
  • advice - kod wykonujący cross-cutting concern
  • pointcut - miejsce występowania aspektów (np. wyjście metody abc)
  • tangling - określenie opisujące wymieszanie kodu typu advice z logiką biznesową
  • weaving (dzierganie) - proces wstrzykiwania kodu związanego z aspektem do logiki biznesowej
Cała idea polega na tym, że chcemy oddzielić cross-cutting concerns od właściwej logiki. Często nie wystarczy wydzielenie do nowej klasy, bo mamy np. do czynienia z konstrukcjami języka typu try-catch-finally. AOP daje nam kod czystszy i napisany w bardziej deklaratywny sposób. Programowanie aspektowe zapewnia zachowanie Single Responsibility Principle, a co za tym idzie znacznie ułatwia refaktoryzację. W wielu przypadkach można je porównać do wzorca dekoratora (np. opakowujemy wywołanie metody w dodatkowy kod).

Przykładowe lokalizacje aspektów:
  • przed wywołaniem metody
  • po pomyślnym zakończeniu metody
  • przy rzuceniu wyjątku
  • zawsze po metodzie (wewnątrz bloku finally)

Najpopularniejsze narzędzia związane z  AOP to Postsharp oraz Castle Dynamic Proxy. Postsharp działa na zasadzie postkompilacji modyfikując wytworzone przez Visual Studio assembly. Dodaje on instrukcje IL w wybranych przez nas miejscach. Jest zintegrowany z VS tak, że możemy przeprowadzać dzięki niemu np. walidację postkompilacyjną. Jeżeli assembly nie przejdzie takiej walidacji, to VS zwróci błąd kompilacji.
Instalujemy go NuGetem, przy czym za pełną wersję trzeba zapłacić.



Drugie narzędzie co Castle Dynamic Proxy. Wstrzykiwanie aspektów odbywa się tu runtime-owo i jest powiązane z kontenerami IoC. Odpytując kontener o dany interfejs dostajemy jego implementację opakowaną w kod przerywający wykonanie metody i dodający do niej kod aspektowy. Jest częścią większego frameworka Castle, w którym kontenerem IoC jest Castle Windsor.

sobota, 21 czerwca 2014

[HTML|JS|CSS] HTML: Transformaty XSLT

Transformaty XSLT to popularny mechanizm przetwarzania plików XML. Wynikiem może być HTML, inny XML lub dowolny plik tekstowy. Arkusz XSL zawiera zestaw reguł określających, które fragmenty wejściowego XML-a transformować do wyniku i w jakie dodatkowe informacje je uzupełnić. Ścieżki podajemy za pomocą XPATH-a.

Najprostszy przykład użycia XSLT to hostowanie pliku XML. Nie chcemy wyświetlać go bezpośrednio użytkownikowi, dlatego decydujemy się na prostą transformację do HTML-a. W tym celu w drugiej linii XML-a umieszczamy link do transformaty.

<?xml version="1.0"?>
<?xml-stylesheet href="mytransform.xsl" type="text/xsl"?>

Szablon powinien składać się z tzw. template'ów czyli fragmentów kodu dopasowanych do elementów XML-a, które mają one przetwarzać. Przykładowo template, który zastosuje się do roota XML-a:

<xsl:template match="/">
  <html>
  <body>
  <h2>My books</h2>  
  <xsl:apply-templates/>  
  </body>
  </html>
</xsl:template>

Instrukcja apply-templates spowoduje wykonanie się pozostałych szablonów pasujących do elementów wewnątrz root-a. Wewnątrz tego pliku mamy jeszcze zdefiniowany szablon pasujący do elementów typu catalog.

<xsl:template match="catalog">
  <table>
   <thead>
    <tr>
     <th>Title</th>
     <th>Author</th>
     <th>Price category</th>
    </tr>
   </thead>
    <xsl:for-each select="book">
     <xsl:if test="./attribute::id != $hiddenId">
     <tr>
      <td>
       <xsl:value-of select="title" />
      </td>
      <td>
       <xsl:value-of select="author" />
      </td>
      <td>
       <xsl:choose>
        <xsl:when test="price &gt; 10 and price &lt; 50">
         cheap
        </xsl:when>
        <xsl:when test="price &gt; 50 and price &lt; 100">
         medium
        </xsl:when>
        <xsl:otherwise>expensive</xsl:otherwise>
       </xsl:choose>
      </td>
     </tr>
     </xsl:if>
    </xsl:for-each>
  </table>
</xsl:template>

Szablon taki buduje tabelę przechodząc po wszystkich elementach typu book za pomocą instrukcji for-each. Mamy także do dyspozycji dwie instrukcje sterujące: prostszą xsl-if (sprawdza tylko, czy dany fragment kodu ma się wykonać) oraz bardziej złożoną xsl-choose (z uwzględnieniem wielu warunków, odpowiada switchowi z języka C). Zapis ./ oznacza odwołanie do obecnie przetwarzanego elementu, natomiast poprzez /attribute::nazwa możemy wyciągać wartości z atrybutów. XSLT pozwala także na definiowanie własnych zmiennych, do których odwołujemy się przez $zmienna, np.

<xsl:variable name="hiddenId" select="'bk101'"/>

niedziela, 15 czerwca 2014

[C#|Visual Studio] Threading: Interlocked

Interlocked to klasa wystawiająca statyczne metody, które pozwalają uczynić pewne podstawowe operacje atomowymi. W atomowość możemy obłożyć operacje arytmetyczne:

var task1 = Task.Factory.StartNew(() =>
{
    for (int i = 0; i < 50000; i++)
        Interlocked.Increment(ref _variable);
});

var task2 = Task.Factory.StartNew(() =>
{
    for (int i = 0; i < 100000; i++)
        Interlocked.Decrement(ref _variable);
});

var task3 = Task.Factory.StartNew(() =>
{
    for (int i = 0; i < 25001; i++)
        Interlocked.Add(ref _variable, 2);
});

Task.WaitAll(task1, task2, task3);
Console.WriteLine(_variable); //2

, a także operacje podstawienia lub warunkowego podstawienia (jeżeli zmienna ma wartość x, to podstaw y).

private static void Exchange()
{
    Thread thread1 = new Thread(new ThreadStart(A));
    thread1.Start();
    thread1.Join();

    // Written [2]
    Console.WriteLine(Interlocked.Read(ref _value));
}

private static void A()
{
    // Replace value with 10.
    Interlocked.Exchange(ref _value, 10);

    // CompareExchange: if 10, change to 20.
    long result = Interlocked.CompareExchange(ref _value, 20, 10);

    // Returns original value from CompareExchange [1]
    Console.WriteLine(result);
}

Mając do dyspozycji te metody, możemy budować bardziej skomplikowane równoległe algorytmy.

[C#|Visual Studio] String, ToString()

Typ System.String znany także pod aliasem string towarzyszy nam przez całe nasze .NET-owe życie. W tym poście przedstawione zostaną pewne mniej znane konstrukcje, które mogą przydać się w codziennej pracy z C#.

W C# ciągi znaków są immutable, co oznacza, że nie można ich modyfikować. Każda operacja modyfikująca utworzy na stercie nową instancję. Typ System.String dziedziczy po object i implementuje takie interfejsy, jak IComparable, ICloneable, IConvertible, IEnumerable, IEquatable. Dodatkowo w C# można deklarować tzw. verbatim strings - ciągi znaków wewnątrz których każdy znak ma być traktowany jako część ciągu znaków - przed takim stringiem umieszczamy @.

String interning

Jest to technika optymalizująca zużycie pamięci w .NET. Polega ona na tym, że dla każdego ciągu znaków liczony jest hash i taki ciąg znaków wkładany jest do specjalnego słownika, gdzie kluczem jest właśnie ten hash. Słownik istnieje w obrębie całej AppDomain i podczas alokacji nowego string-a, jeżeli wyliczony hash znajduje się w słowniku, to instancja jest reużywana.

Konstruktory

Warto znać przeciążenia konstruktora. Poniżej przykład na to,  jak utworzyć ciąg 10 zer na 4 sposoby. Sposób wpisania literal-u wydaje się najprostszy, ale możemy to zrobić na inne, bardziej wygodne sposoby za pomocą konstruktorów.

char[] array = new char[10];
for (int i = 0; i < array.Length; i++)
    array[i] = '0';

char[] array2 = new char[12];
for (int i = 0; i < array2.Length; i++)
    array2[i] = '0';

Console.WriteLine(new string(array));
Console.WriteLine(new string(array2, 1, array2.Length -2));
Console.WriteLine(new string('0', 10));
Console.WriteLine("0000000000");

StringBuilder

W C# możemy sklejać stringi za pomocą operatora +. W pewnych sytuacjach (wiele sklejeń) jest on jednak bardzo niewydajny, dlatego zaleca się korzystać z klasy StringBuilder. Obiekt taki zawiera pole, które wskazuje na tablicę struktur typu Char. StringBuilder pozwala na manipulowanie taką tablicą. Jeżeli przekroczymy zaalokowane miejsce, to StringBuilder automatycznie skopiuje znaki i zbuduje nową tablicę. Wywołanie ToString spowoduje stworzenie nowego obiektu String na stercie i zwrócenie referencji do niego. Domyślna pojemność StringBuildera to 16 znaków. Jeżeli operacje wykonywane na nim próbują przekroczyć pojemność, to StringBuilder podwaja zaalokowane miejsce.

var random = new Random();
var sb = new StringBuilder();
var next = random.Next() % 100;
while (next % 2 == 0)
{
    sb.Append(next);
    next = random.Next() % 100;
}
Console.WriteLine(sb.ToString());

Instancyjne metody


var str = "Jambalaya";
//IEnumerable extension methods
Console.WriteLine(new string(str.Distinct().ToArray()));

//Walidacja
if(str.EndsWith("ya") && str.StartsWith("Ja") && str.Contains("ala"))
    Console.WriteLine("Matches");

Console.WriteLine(new string(str.Except("aya").ToArray())); //Jmbl
//traktuje aya jako IEnumerable<char>

//Analiza
Console.WriteLine(str.IndexOf('a'));
Console.WriteLine(str.IndexOfAny(new char[] {'a', 'J'}));
Console.WriteLine(str.LastIndexOf('a'));
Console.WriteLine(str.LastIndexOfAny(new char[] { 'l', 'y' }));

//Tworzenie nowych instancji
Console.WriteLine(str.Insert(3, "error")); //Jamerrorbalaya

//Uzupełnia podanym znakiem do zadanej długości (20), domyślnie spacja
Console.WriteLine(str.PadLeft(20, '_')); // ___________Jambalaya
Console.WriteLine(str.PadLeft(20)); //           Jambalaya

//3 oznacza maksymalną liczbę itemów
var items = str.Split(new char[] {'a'}, 3, 
    StringSplitOptions.RemoveEmptyEntries); //J,mb,laya
foreach (var item in items)
    Console.WriteLine(item);

str += "\n \t";
Console.WriteLine(str.Length); //12
//usuwa wszystkie biale spacje
str = str.Trim();
Console.WriteLine(str.Length); //9

Statyczne metody


var s1 = "me";
var s2 = "Mark";
Console.WriteLine(string.Compare(s1, s2)); //1

var s3 = string.Format("{0} and {1} went to school", s1, s2);
Console.WriteLine(s3);

Console.WriteLine(string.IsNullOrEmpty("")); //true
//drugi argument to params
Console.WriteLine(string.Join(",", s1, s2));

 

Numeryczne konwersje


float price = 99.99f;
Console.WriteLine("C - currency: " +
    price.ToString("C")); //99.99 zł
Console.WriteLine(price.ToString("C", 
    CultureInfo.CreateSpecificCulture("en-US"))); //$99.99

int num = 70;
Console.WriteLine("D - decimal: " + num.ToString("D4")); //0070

long number = 70000000000000000;
Console.WriteLine("E - exponential: " + 
    number.ToString("E")); // 7,000000E+016

Console.WriteLine("N - number: " +
    number.ToString("N")); // 70 000 000 000 000 000,00

double perc = 0.02;
Console.WriteLine("P - percent: " + perc.ToString("P")); //2,00%

int value = 1024;
Console.WriteLine("X - hexadecimal: " + value.ToString("X4")); //0040

poniedziałek, 28 kwietnia 2014

[C#|Visual Studio] C#: Reflection

Reflection to potężne narzędzie, za pomocą którego można zrobić wiele dobrego jak również i wiele złego w każdej .NET-owej aplikacji. Najważniejsze klasy, to Type, Assembly, Activator oraz wszystkie opisujące składowe typów, czyli MethodInfo, PropertyInfo, ConstructorInfo, FieldInfo, EventInfo itd. Poza swobodnym przeglądaniem assemblies za pomocą kodu, reflection ma zastosowanie w operacjach wykonywanych dynamicznie na starcie aplikacji. W każdym innym wypadku musimy liczyć się ze sporym spadkiem wydajności w stosunku do kodu statycznie typowanego.

Klasa assembly pozwala na odczytywanie metadanych z różnych assemblies a także ładowanie ich.

var current = Assembly.GetExecutingAssembly();

Console.WriteLine("Current assembly: " + current.FullName);

var fromGac =
    Assembly.Load("System.Xml.Linq,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089");

var restSharpAssembly = Assembly.LoadFrom("RestSharp.dll");

Console.WriteLine("\nLoaded assembly: " + restSharpAssembly.FullName);
var dependant = restSharpAssembly.GetReferencedAssemblies();

Console.WriteLine("\nReferenced assemblies:");
foreach (var assemblyName in dependant)
    Console.WriteLine("\t" + assemblyName.FullName);

Metoda GetExecutingAssembly zwróci nam informacje o assembly, w którym ją wywołujemy (np. plik exe). Za pomocą metody Load możemy ładować assemblies z Global Assembly Cache, podając full name. Z kolei dla assemblies bez strong name możemy użyć metody LoadFrom lub LoadFile szukających na dysku. Jeżeli interesują nas zależne assemblies, możemy uzyskać do nich dostęp przy użyciu metody GetReferencedAssemblies.

Mając obiekt typu Assembly możemy pobrać wszystkie publiczne typy w nim zdefiniowane - służy do tego metoda GetExportedTypes..

Console.WriteLine("\nPublic types:");
            var types = restSharpAssembly.GetExportedTypes();

            foreach (Type type in types)
                Console.WriteLine("\t" + type);

            var stype = (from type in types
                        orderby type.GetCustomAttributes(true).Count() descending
                        select type).First();

            var instance = Activator.CreateInstance(stype);
            Console.WriteLine("\nCreated type instance:" + stype.FullName);

            var props = stype.GetProperties();
            Console.WriteLine("Properties:");
            foreach (var propertyInfo in props)
                Console.WriteLine("\t" + propertyInfo.Name);

            var tfields = (from type in types
                           let fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
                           orderby fields.Count() descending
                           select fields).First();

            foreach (var fieldInfo in tfields)
                Console.WriteLine("\t" + fieldInfo.Name);

Na każdym z typów możemy sprawdzić, jakie zdefiniowano atrybuty (GetCustomAttributes), a także pobrać wszystkie properties (GetProperties) czy pola (GetFields), także te prywatne, ustawiając odpowiednie flagi. Klasa Activator pozwala nam na tworzenie instancji dowolnego typu (rzutowanej do object). Mając taką instancję możemy pobrać MethodInfo i wywołać taką metodę przekazując do niej parametry.

var sw = new Stopwatch();
sw.Start();
var jsonArray = new JsonArray();
for (int i = 0; i < 1000000; i++)
{
    jsonArray.Add(i);
}
Console.WriteLine("Invoking instance method: {0} ms", sw.ElapsedMilliseconds);
sw.Restart();

var methodInfo = stype.GetMethod("Add");
for (int i = 0; i < 1000000; i++)
{
    methodInfo.Invoke(instance, new object[] {i});
}
Console.WriteLine("Invoking method via reflection: {0} ms", sw.ElapsedMilliseconds);
sw.Reset();

Porównanie takie wypada zdecydowanie na niekorzyść Reflection, głównie przez iterowanie po metadanych i boxing parametrów wejściowych.

Invoking instance method: 83 ms
Invoking method via reflection: 2241 ms