.NET i takie tam

Archive for the ‘Design patterns’ Category

Nagrania z Øredev

with one comment

oredev

Wyszperałem w sieci nagrania z ubiegłorocznej konferencji Øredev. Dostępne są pod tym adresem i być może kogoś zainteresują.

Øredev odbywa się już od kilku lat i ma miejsce w Szwecji. Skupia się na zagadnieniach dotyczących Javy, .NET, Agile, DDD, architektury aplikacji.

Reklamy

Written by sakowicz

Kwiecień 26, 2009 at 9:33 pm

Dynamic Proxy

with one comment

Jednym z popularnych wzorców projektowych jest wzorzec Proxy. W skrócie, obiekt pełniący rolę proxy, implementuje interfejsy i zarządza, zgodnie z jakąś logiką, wywołaniami metod jakiejś innej klasy. Przykładowo, załóżmy, że mamy następujące klasy:

Kod:

public interface IMessageSender
{
    void Send(string message);
    void Send();
}

public class SimpleSender : IMessageSender
{
    public virtual void Send(string message)
    {
        Console.WriteLine("Send() - with praram: " + message);
    }
    
    public virtual void Send()
    {
        Console.WriteLine("Send() - no praram");
    }
}

public class Sender : IMessageSender
{
    private readonly IMessageSender _sender;
    
    public Sender(IMessageSender sender)
    {
        _sender = sender;
    }
    
    public void Send(string message)
    {
        // tutaj implementujemy dodatkową logikę sterującą wysyłaniem wiadomości
        Console.WriteLine("Send action controlled by Sender object.");
        _sender.Send(message);
    }
    
    public void Send()
    {
        // tutaj implementujemy dodatkową logikę sterującą wysyłaniem wiadomości
        Console.WriteLine("Send action controlled by Sender object.");
        _sender.Send();
    }
}

W powyższym przykładzie Sender jest klasą proxy dla klasy SimpleSender. Obie klasy implementują interfejs IMessageSender, przy czym tylko klasa SimpleSender ‚wie’ jak wysłać wiadomość. Obiekt proxy (Sender) implementuje dodatkową logikę sterującą wywołaniem poszczególnych metod klasy SimpleSender. Przykładowe wywołanie metody Send():

Sender proxy = new Sender(new SimpleSender());
proxy.Send();

Istnieje możliwość automatycznego generowania klas proxy w trakcie działania aplikacji – zwana Dynamic Proxy. Przy korzystaniu z tej techniki zwykle korzysta się z dodatkowych bibliotek jak Castle DynamicProxy czy LinFu.DynamicProxy. W poniższym przykładzie wykorzystałem tą ostatnią bibliotekę:

using LinFu.DynamicProxy;

public interface IMessageSender
{
    void Send(string message);
    void Send();
}

public class SimpleSender : IMessageSender
{
    public virtual void Send(string message)
    {
        Console.WriteLine("Send() - with praram: " + message);
    }
    
    public virtual void Send()
    {
       Console.WriteLine("Send() - no praram");
    }
}

public class MessageSenderInterceptor : IInvokeWrapper
{
    private readonly IMessageSender _sender;
    
    public MessageSenderInterceptor(IMessageSender sender)
    {
       _sender = sender;
    }
    
    public void BeforeInvoke(InvocationInfo info)
    {
       Console.WriteLine("We are about to call method: " + info.TargetMethod);
    }
    
    public object DoInvoke(InvocationInfo info)
    {
       return info.TargetMethod.Invoke(_sender, info.Arguments);
    }
    
    public void AfterInvoke(InvocationInfo info, object returnValue)
    {
    }
}

IMessageSender i SimpleSender są dokładnie takie same jak w poprzednim przykładzie, nowością jest klasa MessageSenderInterceptor implementująca interfejs IInvokeWrapper. Jak widać z implementacji definiuje on metody określające co się stanie przed, w trakcie i po tym jak w kodzie wywołamy metody zawarte w naszym bazowym interfejsie IMessageSender. Na koniec, sposób wywołanie metody Send():

var proxy = new ProxyFactory();
var senderInterceptor = new MessageSenderInterceptor(new SimpleSender());
var finalSender = proxy.CreateProxy<IMessageSender>(senderInterceptor);
finalSender.Send("Hello World!");

Wszystko prosto ładnie, tylko nasuwa się pytanie po co? Po co dodawać dodatkowe referencje do nowych bibliotek, po co korzystać z ProxyFactory i innych interfejsów, skoro można napisać to wszystko prosto samemu?

Fakt jeśli mamy jedną, dwie klasy implementujące interfejs IMessageSender których zachowanie chcielibyśmy w jakiś sposób zmodyfikować – to jasne, nie ma sensu bawić się w Dynamic Proxy.

Jeżeli natomiast klas tych jest więcej Dynamic Proxy zaoszczędzi nam sporo fatygi w implementowaniu obiektów proxy dla poszczególnych klas implementujących IMessageSender, nie mówiąc już o mniejszej ilości klas do przetestowania. Co więcej zastosowanie dowolnego Dependency Injection Framework pozwoli nam uczynić Dynamic Proxy niewidoczne dla programisty korzystającego z naszego kodu.

Written by sakowicz

Grudzień 16, 2008 at 1:52 pm

Mobile Architecture Pocket Guide

leave a comment »

pnp_logo

Microsoft w ramach ‚Patterns & Practices’ opublikował – ‚Mobile Architecture Pocket Guide’ – przegląd zalecanych praktyk i wskazówek przy projektowaniu aplikacji mobilnych. Przewodnik wcale nie nie wydaje się ‚pocket’ gdyż porusza wszystkie ważne tematy, od architektury aplikacji mobilnych poprzez poszczególne warstwy aplikacji (presentation, business, data access, service) po wskazówki dotyczące komunikacji ze światem zewnętrznym i schematy rozpowszechniania aplikacji.

Written by sakowicz

Listopad 27, 2008 at 10:42 am

PDC 2008 Video

with one comment

Może to tylko ja jeszcze nie miałem możliwości, zapozna się z nowościami z PDC. Gdyby jednak, ktoś jeszcze się znalazł, tutaj może znaleźć nagrania z prezentacji z załączonymi plikami PowerPoint.

Written by sakowicz

Październik 31, 2008 at 9:52 am

W obronie singletonu

leave a comment »

Singleton jest jednym ze wzorców projektowych. Jego zadaniem jest zapewnienie istnienia tylko jednej instancji danej klasy i umożliwienie globalnego dostępu do niej. W C# przykładowo może wyglądać to tak:

public sealed SingletonClass
{
  private SingletonClass() {}

  public static readonly SingletonClass Instance = new SingletonClass();
}

Wiele osób uważa, że stosowanie singletonów jest przejawem złej architektury gdyż wprowadzają one ścisłe powiązania między poszczególnymi klasami, co z kolei utrudnia pisanie testów. W zupełności się z tym zgadzam, jednak, jeśli mam wybierać pomiędzy zmiennymi globalnymi to z dwojga złego wolę wykorzystać singleton. Przynajmniej pomoże pogrupować ‚zmienne’ w jakąś logiczną strukturę.

Poza tym nie tak naprawdę singleton’ów, nie da się całkowicie uniknąć, z dwóch powodów:

  • Pomimo tego, co niektórzy twierdzą, istnieją sytuacje wymagające ich zastosowania jak na przykład interakcja z hardwarem.
  • Wydajność – i nie chodzi mi tu o aplikacje serwerowe itp. – ale te mniejsze pracujące przykładowo na urządzeniach przenośnych.

Written by sakowicz

Lipiec 16, 2008 at 9:32 am

Napisane w .NET, Design patterns

Object Thinking

leave a comment »

Będąc w Galway wysłuchałem prezentacji ‚Object Thinking’ Alan’a Deana. Początek prezentacji, trzeba to powiedzieć, był zniechęcający, pojawiło się sporo akademickich formalizmów, mających nikłe odzwierciedlenie w codziennym życiu. Przykładowo przydługawe, dywagacje o tym który z terminów jest właściwy: software developer czy software engineer? Dość mistrzu, nie po to tu przyszedłem, nawijaj o obiektach.

Jednak gdy doszliśmy do meritum prezentacji, przestałem ziewać i zacząłem słuchać . Otóż padła propozycja aby odrzucić dotychczasowy sposób myślenia o klasach jako o zbiorze pól i właściwości, no i metod ale o nich za chwilę, i zastąpić je koncepcją samo-opisywalności. Zgodnie z propozycją, najprostsza, definicja klasy wyglądała by następująco:

public class Customer : Dictionary<Uri, Object> {}

Ciekawe prawda, ot taki pojemnik na wszystko. Metody, rzecz jasna, pozostają a ich celem jest opisywanie intencji klasy.

Uzasadnieniem takiego podejścia do klas, jest twierdzenie, że zdecydowana większość modyfikacji jakie, jesteśmy zmuszeni wprowadzać, dotyczy właśnie sposobu reprezentacji danych. Oczywiście tego typu zmiany zwykle, powodują reakcję łańcuchową i pociąga modyfikacje w innych klasach. Więc po co się z tym męczyć? Umożliwmy przechowywanie dowolnych danych i wszyscy będą szczęśliwi.

No chyba niezupełnie. Nie twierdzę, że idea jest pozbawiona sensu, bo widzę logikę tego rozumowania, jednak dostrzegam również kilka potencjalnych problemów.

Przede wszystkim porzucamy strong typing, wszystko może być obiektem więc konieczna jest walidacja elementów przechowywanych w naszym pojemniku. Oczywiście bez jawnego określenia typów, intellisense Visual Studio, przestanie nas ostrzegać o potencjalnych problemach. Dalej z punktu widzenia bazy danych, tabele też miały by zostać tylko pojemnikami na dane? Żadnych kluczy, indeksów etc. ? Już widzę jak przystają na to administratorzy baz danych.

Kolejnym problemem może być czynnik ludzki i nie chodzi mi tu o mentalne reperkusje przestawienia się na nowy sposób myślenia, a czysto pragmatyczne podejście. Nie oszukujmy się większość ludzi jest leniwa, a programiści to już w szczególności;) . Wcale nie jest takie nieprawdopodobne, że niektóre wartości mogą być przechowywane w klasie po kilka razy (szczególnie jeśli pracujemy w zespole). Co może prowadzić do wszelakiej maści problemów.

Jak na razie nie oceniam, czekam, aż tęższe głowy od mojej wypowiedzą się w tej sprawie. Może za jakiś czas pojawią się jakieś study case, projektów wykorzystujących to podejście. Poczekamy zobaczymy. Tymczasem dla zainteresowanych slajdy i przykłady z prezentacji są dostępne tutaj.

Written by sakowicz

Maj 7, 2008 at 11:14 am

UserControl, MVP i interfejs aplikacji mobilnych

leave a comment »

Stworzenie dobrego interfejsu aplikacji mobilnej jest wyzwaniem, szczególnie jeśli chcemy wykorzystać całą dostępną przestrzeń ekranu i nie bazować, tylko na właściwościach Anchor i Dock. W zależności od złożoności okna możemy próbować – manualnie, w kodzie, zmieniać położenie kontrolek – jednak jest to podejście pracochłonne i utrudniające przyszłe modyfikacje.

Mimo wszystko żyjemy w dobie wizualnych narzędzi programistycznych i szybciej przyjdzie nam utworzenie odpowiedniego interfejsu użytkownika przy użyciu designer’a wbudowanego w Visual Studio niż ręczne kodowanie położenia poszczególnych elementów okna.
Dlatego też lepszym rozwiązaniem może być utworzenie dwóch różnych form dla tego samego ekranu i wyświetlanie ich w zależności od aktualnej orientacji. To rozwiązanie ma jednak dość poważną wadę – otóż, nie możemy go zastosować do głównego ekranu naszej aplikacji (gdyż jest ono powiązane z podstawowym wątkiem programu). Aby wyeliminować tą niedogodność możemy umieścić zawartość naszego okna w kontrolce UserControl i mając dwie takie kontroli dla jednego ekranu (orientacja horizontal/landscape) możemy je wyświetlać w zależności od potrzeby.

Kolejnym problemem z jakim, w powyższym przypadku, przyjdzie się nam borykać jest to, iż musimy umieścić taki sam kod w dwóch różnych miejscach. Ale i na to jest rada – zastosowanie wzorca Model – ViewPresenter (MVP). Przykład wykorzystania tego wzorca w tym konkretnym zastosowaniu można pobrać stąd.

MVP - UserControl example

O dobrym screencast‚cie traktującym o wzorcach Model – ViewPresenter i Model – ViewController pisałem tutaj.

Written by sakowicz

Sierpień 6, 2007 at 11:02 am

Napisane w .NET CF, Design patterns