Otwórz gita w odpowiednim folderze

Taka mała rzecz a cieszy (dobra, dwie małe rzeczy).

Pod skrótem klawiszowym „Win+2” (czyli druga aplikacja która jest „pinned” do paska w Windows) otwiera mi się konsola gita. Moje podstawowe narzędzie pracy. I teraz trzeba tylko zmienić folder, w którym się uruchomi na ten, w którym projekcie aktualnie pracuję.

Klikamy właściwości tego programu (wprost z paska) i ustawiamy:

start-git-in-folder

Opublikowano Tip of the day | Otagowano | Dodaj komentarz

Immutable Value Object przesyłany/serializowany (np po SignalR)

Najbardziej popularnym Value Object jest Money. Dzisiejsza implementacja jest okrojona, bo chciałbym pokazać tylko jedną rzecz. W tym przykładzie instancje możemy tworzyć tylko poprzez metode Create() (taka fabryka). Konstruktor jest prywatny.

public class Money
{
    public static Money Create(decimal value, string currency)
    {
        // some additional checks
        return new Money(value, currency);
    }

    Money(decimal value, string currency)
    {
        Value = value;
        Currency = currency;
    }

    public decimal Value { get; }
    public string Currency { get; }
}

Pewnie dla tego przykładu lepiej mieć po prostu publiczny konstruktor z dwoma parametrami, ale mam wiele przykładów innych bardziej skomplikowanych Value Objects, gdzie podejście z prywatnym konstruktorem i kilkoma fabrykami walidującymi różne przypadki ma sens.

Czy można przesyłać immutable Value Object poprzez SignalR?

Taki obiekt nie przejdzie serializacji JsonSerializerem i nie może być przesłany SignalR’em. Uważam, że nie ma nic złego w przesyłaniu takiego immutable Money między clientem a serverem (obydwa w .NET, nie tylko webem żyje człowiek 😉 ). Czy ktoś uważa, że to złe podejście i trzeba tworzyć do tego DTO? Postawiłem na prostotę.

Rozwiązanie

Trzeba dodać attrybut [JsonConstructor] do konstruktora.

public class Money
{
    public static Money Create(decimal value, string currency)
    {
        // some additional checks
        return new Money(value, currency);
    }

    [JsonConstructor]
    Money(decimal value, string currency)
    {
        Value = value;
        Currency = currency;
    }

    public decimal Value { get; }
    public string Currency { get; }
}

Źródło: JSON.net: how to deserialize without using the default constructor?

Jak testować/rozkminiać takie rzeczy

Szlak by mnie trafił gdybym miał takie moje przemyślenia, przypuszczenia, POC testować na żywym projekcie, który się ileś tam uruchamia i potem muszę jeszcze sie przeklikać, żeby coś wywołać.

Izolujemy co istotne od tego co nieistotne i testujemy 🙂

Opublikowano Programowanie | Otagowano , , , | 2 komentarze

TypeScript – deklaruj explicite zwłaszcza dane z JavaScriptu

Dzisiaj podczas przeklikiwania jednego ze scenariuszy w przeglądarce, coś poszło nie tak. Sprawdzam Unit Testy – wszystko działa. Trudno, tak bywa w „realu”. Debuguję i okazało się na końcu, że porównujemy:

"8" === 8

Skąd tam ten string???

Okazało się, że dane przychodzą z kontrolki x-editable dla angulara.

<span edit="4" onbeforesave="onbeforesave($data)"></span> 
$scope.onbeforesave = (value) => {
    return myService.update(value);
}

export class ChangeMaterialService {
    update(numberValue: number): boolean {
        // boom, in runtime value can be of type string
    }
}

typescript logo

Zadeklarowaliśmy elegancko, że value jest typem ‚number’ więc dlaczego przepuszcza stringa? Przy kompilacji (transpilacji?) TypeScriptu typ value to any. Zasady są takie, że any pasuje do wszystkiego. W runtime, mimo że value jakby nie pasuje do sygnatury metody update() to już nic nie jest sprawdzane – jesteśmy w świecie JavaScriptu i tam nie ma statycznego typowania.

Rozwiązaniem jest explicit ustawienie typu dla danych przychodzących w metodzie onbeforesave()

$scope.onbeforesave = (value) => {
    return myService.update(value);
}

powyższy kod się nie skompiluje więc musimy zmienić na:

$scope.onbeforesave = (value: string) => {
    return myService.update(Number(value));
}

lub na:

$scope.onbeforesave = (stringValue: string) => {
    let value = Number(stringValue);

    return myService.update(value);
}

Btw możecie podbić tą odpowiedź TypeScript Converting a String to a number na SO bo IMHO ta druga odpowiedź jest bardziej poprawna dla TypeScript.

Opublikowano Programowanie | Otagowano , , | Dodaj komentarz

Stack technologiczny w aktualnym projekcie

  • MVC 5 + WebApi 2 (najnowsze ale nie .NET Core)
  • Angular 1.5 (nie SPA, wtedy gdy trzeba na pojedynczej stronie) + TypeScript
  • TypeLite – biblioteka generuje DTO w TypeScript na podstawie DTO w C#. Gdy zmieniłem coś w C# to dostaję błędy kompilacji w TypeScript.
  • Bootstrap
  • AutoMapper
  • EntityFramework 6
  • MediatR – implementacja wzorca Command
  • SignalR – zarówno między ServerJS Client, jak i WindowFormServer, działa super.
  • Ninject
  • xUnit, Moq, AutoFixture
Opublikowano Programowanie | 2 komentarze

Jaki wyjątek rzucać gdy mamy nieobsłużonego enuma

Gdy sterujemy przepływem sterowania za pomocą switcha i tym co sprawdzamy jest enum to warto obsłużyć też przypadek default. Czyli co stanie się gdy enum ma wartość spoza tych wymienionych w case‚ach. Warto wtedy rzucić wyjątek.

Taki kod wygeneruje nam ReSharper (i jest to niezły kod):

void Execute(DocumentStatus documentStatus)
{
    switch (documentStatus)
    {
        case DocumentStatus.Draft:
            // Do sth
            break;
        case DocumentStatus.Released:
            // Do sth
            break;
        default:
            throw new ArgumentOutOfRangeException(nameof(documentStatus), documentStatus, null);
    }
}

Dlaczego jest to ważne? Poniższy kod zarówno się skompiluje jak i wykona poprawnie w runtime, mimo że żadna z wartości nie przyjmuje 111:

DocumentStatus AssignInvalidValue()
{
    return (DocumentStatus) 111;
}

Więcej w Rzutowanie na Enum z niepewnego źródła

Błąd, który dotychczas robiłem to wypełniałem 3-ci argument w konstruktorze klasy ArgumentOutOfRangeException. Pisałem tam coś w stylu:

throw new ArgumentOutOfRangeException(nameof(documentStatus), documentStatus,
    $"Enum '{documentStatus.GetType().Name}' has invalid value '{documentStatus}'");

Dzięki czemu przechwycony wyjątek wyglądał tak:

enum exception

Jest to dla tego przepadku zupełnie zbędne. Gdy przekażemy tam nulla to przechwycony wyjątek będzie wyglądał tak:

enum exception without message

A mając stack trace zobaczymy gdzie co i jak się podziało.

Metoda fabrykująca takie wyjątki

Jednak najlepszym sposobem jest jednak opakowanie tworzenia tego wyjątku. Dla mnie też kiedyś dziwne było żeby zwracać z funkcji wyjątek który dopiero później będzie rzucany. Przekonałem się jednak, że to dobra praktyka, takie scentralizowane tworzenie np message dla wyjątku. Np taka klasa:

public static ArgumentOutOfRangeException CreateMissingEnumException<T>(string paramName, T value)
    where T : struct 
{
    return new ArgumentOutOfRangeException(paramName, value,
        $"Enum '{value.GetType().Name}' has invalid value '{value}'");
}

i wywołanie oraz podgląd przechwyconego wyjątku:

enum create missing enum exception

Opublikowano Programowanie | Otagowano , , | 2 komentarze

Przykład fajnej Extension Method

Kod, który mnie natchnął:

var propertiesToDelete = someEntity.Properties
    .Where(x => x.PropertyName == "NAME")
    .ToList();

foreach (var property in propertiesToDelete)
{
    someEntity.Properties.Remove(property);
}

Natchnął bo zmieniłem na:

foreach (var property in someEntity.Properties.Where(x => x.PropertyName == "NAME"))
{
    someEntity.Properties.Remove(property);
}

To było słabe… gdybym sprawdzał po kimś takie coś, to bym może zauważył, ale sam to zrobiłem i nie zauważyłem: modyfikowanie kolekcji po której się iteruje, leci wyjątek. Code Review – wiele oczu patrzy – naprawdę się przydaje, żeby takich problemów unikać. Anyway, nie o tym.

Szerszy kontekst

Properties z powyższego kodu to ICollection<T>, które oznacza zależność jeden do wielu i Entity Framework zmapuje to i dobrze zapisze/wyciągnie z bazy, podobnie będzie też wyglądać odpowiadające mu DTO lub ViewModel:

public class SomeEntity
{
    // składnia C# 6
    public virtual ICollection<Property> Properties { get; } = new List<Property>();
}

Pod spodem jest jednak List<T>. A na typie List jest metoda RemoveAll(Predicate<T> predicate).

Napisałem więc coś takiego

Kod do odpalenia i testy

Dzięki temu wywołanie kodu z którym wystartowaliśmy będzie wyglądać tak:

someEntity.Properties.RemoveAll(x => x.PropertyName == "NAME");

Co zdecydowanie zwiększa czytelność. Ominiemy też wywołowanie LINQ i wszystko odbędzie się na bardziej wydajnej RemoveAll() z klasy List<T>.

Problemy

Wydaje mi się to fajnym kawałkiem kodu. Czy może ktoś widzi tutaj jakiś potencjalny problem?

Opublikowano Programowanie | Otagowano , , , | 1 komentarz

Zbyt zajęty? Czyżby zapierdol w projekcie?

too busy

busy

are-you-too-busy-to-innovate1

Jakie mogą być efekty:

the-busy-bee-paradox-agile-tour-lille-2014-4-638

Co może pomóc:

small-batches

Moja opinia jest taka:

ZAWSZE są pilne rzeczy do zrobienia, ZAWSZE biznes oczekuje, że dostarczasz wartość.
I Ty ją oczywiście dostarczaj, ale to od Twojego profesjonalizmu i kultury pracy zależy czy tylko bezmyślnie napierdalasz Lines Of Code, czy może zastanawiasz się co i w jaki sposób najlepiej zrobić.

Opublikowano Tip of the day | 2 komentarze