Pierwsze zabawy z MongoDb

Już od dłuższego czas chciałem poznać jedną z baz NoSql-owych. Niestety zawsze jak się zabierałem za poznawanie jakiejś miałem nad głową termin skończenia projektu i wolałem zrobić coś szybko w znanych mi już relacyjnych bazach danych. Teraz zacząłem projekt, którego zakończenie przewiduje na marzec, więc mam jeszcze trochę czasu żeby pobawić się czymś nowy. Jedną z nowości, które zamierzam lepiej poznać to darmowa, NoSql-owa baza danych MongoDB. Jest to baza dokumentowa, więc wszystkie dane przechowuje w postaci plików json. Podejście to projektowania danych jest trochę inne niż w bazach takich jak MS SQL Server, ponieważ nie ma tutaj relacji. Oczywiście można sobie zamodelować przechowywanie kluczy, ale lepiej jest trzymać wszystko w jednym dokumencie.

Czego potrzebujemy żeby zacząć przygodę z MongoDB?

Przede wszystkim musimy pobrać bazę ze storny producenta (http://www.mongodb.org/downloads). Następnie rozpakowujemy pobrane archiwum i właściwie już możemy odpalić bazę. Aby to zrobić uruchamiamy konsole (cmd/powershell), wchodzimy do katalogu bin i piszemy:

.mongod.exe -dbpath sciezka_do_katalogu_z_danymi

Nie zamykamy konsoli, gdyż spowoduje to zamknięcie bazy. Domyślnie nasza baza zostanie uruchomiona na 127.0.0.1:27017. Niestety nie możemy uruchomić żadnego panelu admina ani nic co pomoże nam zarządzać bazą poprzez przeglądarkę. Do tych celów polecam program Robomongo. Dzięki niemu będziemy mogli podejrzeć dane, dodać, aktualizować czy wywoływać własne skrypty.

 

Czas połączyć to z .NET-em

MongoDB świetnie integruje się z .NET-em. Cała dokumentacja jak zrobić bardziej zaawansowane rzeczy znajdziecie na stronie http://docs.mongodb.org/ecosystem/drivers/csharp/ Przede wszystkim warto przeczytać CSharp Driver LINQ Tutorial, żeby zobaczyć jak używać LINQ do wyciągania danych z bazy.

Do używania mongo potrzebne są dwie biblioteki: MongoDB.Bson.dll oraz MongoDB.Driver.dll, obie można zainstalować poprzez Package Manager z lini poleceń:

PM> Install-Package mongocsharpdriver

lub poprzez wizualny manager NuGet’a (Official MongoDB C# Driver). Tyle wystarczy żeby móc już używać mongoDB w swoim projekcie.

Jako bonus dołączam moją implementację wzorca Repository skierowanego specjalnie dla MongoDB. Klasa ta posiada, kilka moich zdaniem kluczowych funkcjonalności takich jak:

  • zwraca nie cała listę obiektów, a obiekt IQueryable, który pozwala na tworzenie kwerend LINQ,
  • zwraca obiekt po jego Id,
  • przy dodawaniu nowego obiektu generuje mu nowe Id,
  • jeśli nie podamy nazwy kolekcji stworzy automatycznie kolekcje odpowiadającą nazwie typu obiektu, który zapisujemy w bazie.
/// <summary>
/// This class provides Id property
/// </summary>
public abstract class ModelBase
{
    public string Id { get; set; }
}

public class MongoRepository<T> 
    where T : ModelBase
{
    public MongoDatabase Database { get; private set; }

    private string _tableName;

    public MongoRepository(string tableName)
    {
        this._tableName = tableName;
        CreateDatabase();
    }

    public MongoRepository()
    {
        CreateDatabase();
    }

    private void CreateDatabase()
    {
        MongoClient client = new MongoClient();
        MongoServer server = client.GetServer();
        Database = server.GetDatabase("databasename");
    }

    public IQueryable<T> GetAll()
    {
        var col = GetTColection();
        return col.AsQueryable<T>();
    }

    public T GetById(string id)
    {
        var col = GetTColection();
        return col.AsQueryable<T>().Single(e => e.Id == id);
    }

    public void Add(T obj)
    {
        if (obj.Id == null )
        {
            obj.Id = ObjectId.GenerateNewId().ToString();
        }
        var col = GetTColection();
        col.Insert(obj);
    }

    public void Remove(string id)
    {
        var col = GetTColection();
        col.Remove(Query.EQ("_id", id));
    }

    public void Update(T obj)
    {
        var col = GetTColection();
        col.Save(obj);
    }

    private MongoCollection<T> GetTColection()
    {
        if (!string.IsNullOrEmpty(_tableName))
            return Database.GetCollection<T>(_tableName);
        else
            return Database.GetCollection<T>(typeof(T).Name);
    }
}

ABB DevDay 2013

Brak czasu, który doskwiera mi odkąd tylko rozpocząłem pracę, niestety przekłada się również na mojego bloga. Nie mam za bardzo czasu pisać czegokolwiek, dlatego relację z konferencji, która odbyła się w poprzedni piątek piszę dopiero dzisiaj. Ponieważ na DevDay’u była całkiem spora ekipa ludzi, którzy prowadzą blogi, o tym wydarzeniu możecie już przeczytać tututu i jeszcze tu. Ponieważ jednak w tym roku sesje zostały podzielone na 2 sale, każdy mógł wybrać różne sesje. Miało to niewątpliwie swoje wady i zalety, bardzo chciałem zobaczyć niekiedy obie sesje, które odbywały się w tym samym czasie. Mam nadzieję, że niedługo będę mógł zobaczyć je online :)

devday2013

Krótko o sesjach, na których byłem:

Jon Skeet – Back to basics: the mess we’ve made of our fundamental data types
Pierwszą sesję prowadziła największa gwiazda stackoverflow, człowiek który nawet na devday’u zaraz po swojej sesji odpalał laptopa i udzielał odpowiedzi na pytania zadawane na stack’u. Jego sesja dotyczyła pułapek jakie czekają na programistów C#, w typach prostych takich jak, kiedy powinno używać się double a kiedy decimal, czy dane przechowywane w stringu można zawsze traktować tak samo oraz o tym, że daty w historii bywają zwodnicze i nie zawsze luty ma 28 lub 29 dni… Ogólnie sesja była poprowadzona bardzo profesjonalnie, z odrobiną humoru, którą zapewniał Tony the Pony, czyli pacynka, z którą Jon prowadził czasami rozmowy. Była to świetna sesja na rozpoczęcie, niewiele kodu oraz całość podana w bardzo przystępny sposób. Uwagę mogę mieć tylko, do tego, że rzeczy przedstawione przez Jona zdarzają się niezwykle rzadko, zwłaszcza te z datami, natomiast rozumiem że sesja miała nieść głębsze przesłanie, żeby czasami skupić się również na szczegółach, bo tam może równie często tkwić problem.

Patric Kua – Implementing Continuous Delivery
Wybrałem tą sesję ponieważ zaciekawił mnie jej temat, miałem nadzieję że Patric opowie jakieś praktyczne rzeczy, jak rozwijać duże projekty tak, aby dostarczać nowe funkcjonalności i nie zginąć w starym kodzie. Usiadłem nawet na schodach, żeby tego posłuchać, bo cała sala była już zapełniona, kiedy wszedłem. Co prawda dowiedziałem się podczas sesji, jakie rzeczy kryją się pod nazwą Continuous Delivery, natomiast brakło przykładów i historii z życia, może dlatego że było zbyt mało czasu, temat zaś jest niezwykle obszerny. Mimo wszystko Patric’a bardzo dobrze się słuchało i widać było że wie o czym mówi.

Andreas Hakansson – Guerilla Framework Design
Ponieważ Andreas jest z firmy Tretton37, tej samej co zeszłoroczny prelegent Martin Mazur, próbowałem porównać jego prezentacje z zeszłoroczną. Ciężko było doścignąć Martina, który w zeszłym roku zrobił na mnie ogromne wrażenie. Po kilku minutach przestałem porównywać ich sesji, ponieważ Andreas mówił o rzeczach bardziej technicznych, więc porównanie byłoby niesprawiedliwe. Pokazywał jakie ciekawe rzeczy zastosowali we frameworku Nancy, między innymi poprzez zastosowanie dynamicznych obiektów oraz automatyczne ładowanie zależności.

Ben Hall – Building Startups and Minimum Viable Products
Wiele osób wybrało inną sesję o jakże ostatnio popularnym angularJS, sam też przez chwilę zastanawiałem się nad tym, ale nie żałuje, że poszedłem na sesje Bena. Sesja mówiła całą prawdę o tym jak powstają startupy. Ben ma spore doświadczenie pracując z nowymi firmami, które chcą podbić rynek i sam wie bardzo dobrze na czym należy się skupić, a co powinno zejść na dalszy plan. O ile na wszystkich innych sesjach słyszeliśmy że pisanie testów jest bardzo ważne, o tyle w przypadku startupów, testy nie mają zbyt wielkiego sensu. “Program może być napisany tak świetnie że nie będzie potrzebna do niego dokumentacja, ale co z tego skoro nikt go nie używa”. Wielkie brawa dla niego za otwarcie oczu :)

Paul Stack – Windows – Having its ass kicked by Puppet and PowerShell since 2012
Paul opowiadał o sprawach nie do końca związanych z deweloperką, temat bardziej interesował IT-prosów, nie było jednak tego widać po sali. Jego sesja zgromadziła również komplet w sali i znowu połowę przesiedziałem na schodach, mimo to była to na prawdę świetna prezentacja. Paul śmiał się z produktów Microsoftu, i pokazywał jak zamiast pisać wielostronicowe Install Guide’y (kto z nas tego nie zna), napisać jeden skrypt PowerShellowy instalujący cały system i uszczęśliwić przy tym programistów.

Marco Cecconi – The Architecture of StackOverflow
Temat, którego nie mogłem przegapić, między innymi również dlatego, że moja praca inżynierska opierała się w dużym stopniu na tym jak działa stackexchange. Prawda okazała się jednak znacznie prostrza niż sobie wyobrażałem. Tak na prawdę stackoverflow składa się z 9 projektów. Zaś serwerów obsługujących 3.5 mln użytkowników jest zaledwie 25… są to wszystkie serwery wraz z dwoma load balancerami, i 4 serwerami bazodanowymi. Marco mówił, że pisząc stackoverflow nie skupiali się zbytnio na czytelności kodu, bardziej na tym, żeby to szybko działało. Jak widać udało im się to osiągnąć, bo nawet Jon Skeet nie potrafi ubić ich serwerów. Z ciekawostek dodam, że cały zespół stackexchange liczy sobie tylko 10 developerów!

Rob Ashton – The software journeyman’s guide to being homeless and jobless.
Na koniec, wisienka na torcie, czyli człowiek, który mimo że wszyscy już zasypiali i czekali tylko na afterparty spowodował, że chciałem aby nie przestawał swojej prezentacji i mówił bez końca. Pamiętam Rob’a z poprzedniego roku, kiedy to opowiadał o JSie, lecz tegoroczny Rob to całkiem inna osoba. Biła z niego taka energia i radość z tego, że jest… bezrobotny :) Opowiadał o tym, jak rzucił pracę, tylko po to, by znów odkryć radość z programowania. Teraz mimo, że jest bezrobotny, nie brakuje mu ofert pracy i pracuje przy tym przy czym chce. Rob swoje przygody opisał na swoim blogu (tu), więc jeśli chcecie poczytać zachęcam do lektury.

Na koniec, krótkie podsumowanie… Już w zeszłym roku uważałem, że DevDay to konferencja o wysokim standardzie, po tegorocznej edycji, wszystko zostało ulepszone. DevDay dorównuje o ile nie przewyższa niejedną płatną konferencje. Wielkie podziękowania należą się osobom, które organizowały tą konferencję: Rafałowi,Michałowi i całej ekipie DevDay. Jedyna uwaga co do tegorocznej edycji, jest taka, że nauczyłem się mniej niż poprzednio. Sesje były bardziej ogólne i nie były prawie wcale skierowane do programistów .NET, niemniej cały dzień i jak i noc spędziłem w bardzo miłej atmosferze.

Zdjęcia z konferencji możecie znaleźć na profilu facebookowym abbdevday, natomiast nagrania z sesji będą dostępne na kanale youtube.

Custom Xml Generator

Dzisiaj chciałbym przedstawić Wam kolejną moją bibliotekę, której kod możecie znaleźć na githubie. Do napisania jej natknął mnie ostatnio problem przed którym stanąłem pisząc jedną z aplikacji. Jak zapewne się domyślacie z nazwy posta, będzie to biblioteka mająca związek z XML-em. Otóż standardowy XmlSerializer, dostępny w .NET-cie pozwala nam w bardzo prosty sposób serializować obiekty do XML-a. Niestety serializer ten ma swoje wady, gdyż jako nazwę elementu w XML-u przyjmuje nazwę parametru w klasie. Można to oczywiście zmienić, niestety trzeba to robić za pomocą atrybutów. Mój problem polegał na tym, że dostałem obiekt z WCF’a, więc i klasa leżała po stronie WCF’a, nie mogłem więc dodać sobie dowolnych atrybutów, tak aby nadać nazwy wybranym elementom. Jedynym sposobem jest tworzyć ręcznie całą strukturę XElement. Dlatego postanowiłem stworzyć cos na kształt generatora XML, który bardzo upraszcza tworzenie struktury XML-a. Poniżej przedstawiam sposób działania tej biblioteki.

Załóżmy, ze otrzymujemy z zewnętrznego serwisu obiekt klasy User. Wszystkie potrzebne modele przedstawione są poniżej.

public class User
{
    public string Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
    public List<Teacher> Teachers { get; set; }
    public SchoolClass Class { get; set; }
}

public class SchoolClass
{
    public string Name { get; set; }
    public Teacher Tutor { get; set; }
}

public class Teacher
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Chcąc wygenerować XML-a musimy nadać nazwy interesującym nas właściwościom. Możemy bindować właściwości na 3 sposoby: jako atrybut, jako element oraz jako kolekcję służą do tego kolejno metody: BindAttribute, BindTag i BindCollection. Wszystkie jako pierwszy parametr pobierają Expression, które wskazuje jaki parametr ma zostać zbindowany, zaś drugi parametr to string oznaczający nazwę elementu bądź atrybutu. Dodatkowo metody BindTag moze przyjąć jako drugi parametr innego XmlBuilder’a, który zajmie się dalszym prasowaniem elementu zaś metoda BindCollection potrzebuje jeszcze trzeciego parametru który albo oznacza nazwę tagu pojedynczego elementu w kolekcji, bądź XmlBuilder’a.

var dbBinder = new XmlBuilder("u"); //1
dbBinder.BindAttribute(e => e.FirstName, "fName");  //2
dbBinder.BindTag(e => e.Age, "a"); //3
dbBinder.BindTag(e => e.Class, classBuilder) //4
dbBinder.BindCollection(e => e.Teachers, "ts", "t"); //5
dbBinder.BindCollection(e => e.Teachers, "ts", teacherBuilder) //6
  1. Tworzymy nasz główny XmlBuilder podając w konstruktorze jako parametr nazwę głównego elementu.
  2. Bindujemy właściwość FirstName jako argument o nazwie fName.
  3. Bindujemy właściwość Age jako oddzielny element o nazwie ‘a’.
  4. Bindujemy właściwość Class jako oddzielny element określony przez innego XmlBuildera.
  5. Bindujemy kolekcję Teachers, gdzie sama kolekcja będzie oznaczona przez tag ‘ts’, a każdy jej element przez tag ‘t’.
  6. Bindujemy kolekcję Teachers, gdzie sama kolekcja będzie oznaczona przez tag ‘ts’, a każdy jej element przez teacherBuildera.

Po wywołaniu metody GenerateXml i przesłaniu w jej parametrze obiektu, z którego chcemy stworzyć XMLa dostajemy XElement, który posiada tylko zbindowane atrybuty i tagi. Umieszczam tą bibliotekę mimo, iż wiem, że można jeszcze sporo do niej dopisać. W najbliższym czasie zamierzam dodać bindowanie kolekcji bez opakowania go w nadrzędny element oraz domyślną serializację do xml’a . Jeśli macie jeszcze jakieś pomysły, co by się przydało możecie pisać lub dopisać samemu i wysłać na github :)

Link do github’a

Łatwiejsza praca z bazą danych Azure Mobile Services

Ostatnio zacząłem bawić się z Windows Azure Mobile Services, ponieważ chciałem zobaczyć czy, to rozwiązanie będzie wystarczające do aplikacji, którą teraz piszę. Nie spodobał mi się jednak sposób jaki ekipa Microsoftu sugeruje wyciąganie danych w aplikacji, czyli przechowywanie uchwytu do bazy Mobile Service jako statycznej właściwości w klasie App. Wiele przyjemniejszym rozwiązaniem jest stworzenie sobie klasy Repozytorium, która będzie pośrednikiem między aplikacją a serwisem wyciągającym dane. Najprostsze repozytorium może wyglądać tak:

public class ServiceRepository<T>
{

    public static MobileServiceClient MobileService = new MobileServiceClient(
        "https://linktoservice.azure-mobile.net/",
        "SECRETPASSWORD");

    public async Task<T> Add(T obj)
    {
        await MobileService.GetTable<T>().InsertAsync(obj);
        return obj;
    }

    public async Task Delete(T obj)
    {
        await MobileService.GetTable<T>().DeleteAsync(obj);
    }

    public async Task<T> Update(T obj)
    {
        await MobileService.GetTable<T>().UpdateAsync(obj);
        return obj;
    }

    public IMobileServiceTable<T> Get()
    {
        return MobileService.GetTable<T>();
    }
}

Ponieważ każdy element w bazie WAMS posiada swoje Id, możemy trochę rozszerzyć działanie repozytorium wprowadzając interfejs IServiceModel, po którym będą dziedziczyć wszystkie inne modele.

interface IServiceModel
{
    int Id { get; set; }
}

Dzięki temu, możemy dodać do repozytorium jeszcze jedną bardzo przydatną metodę:

public class ServiceRepository<T>
    where T : IServiceModel
{

    //...

    public async Task Get(int id)
    {
        var obj = await MobileService.GetTable()
            .Where(e => e.Id == id)
            .Take(1)
            .ToListAsync();

        if (obj != null && obj.Any())
            return obj.First();

        throw new InvalidIdException();
    }
}

Stworzenie takiej klasy daje nam dużo bardziej czytelny kod i pozwala nam zmniejszyć liczbę zmian w systemie, jeśli w przyszłości okazałoby się, że jednak nie będziemy korzystać z WAMS, a czegoś innego.

RandomData

Już jakiś czas temu przedstawiałem na grupie .NET pewną niewielką bibliotekę, którą napisałem jednej nocy. Napisanie jej wynikło z potrzeby wygenerowania listy randomowych użytkowników, na których mógłbym pokazać sposób działania LINQ. Dziś znalazłem chwilę czasu, żeby poprawić w niej kilka błędów i opisać jej działanie.

Tak więc, przede wszystkim biblioteka składa się ze zbioru atrybutów, do generowania losowych danych.  Za pomocą tych atrybutów możemy oznaczać pola we własnej klasie i za pomocą specjalnego obiektu Randomizer możemy wygenerować jeden obiekt, bądź całą kolekcję. Przykład działania znajduje się poniżej.

class User
{
 [Identity]
 public int Id { get; set; }

 [RandomFirstName()]
 public string FirstName { get; set; }

 [RandomLastName]
 public string LastName { get; set; }

 [RandomDateTime("1960-01-01", "2013-08-06")]
 public DateTime BornDate { get; set; }

 [RandomText(300)]
 public string Description { get; set; }

 [RandomValue("Poland", "Germany", "France", "USA")]
 public string Country { get; set; }

 public override string ToString()
 {
 var strBuilder = new StringBuilder();
 strBuilder.Append("Id: ").Append(Id).Append(" || ");
 strBuilder.Append("FirstName: ").Append(FirstName).Append(" || ");
 strBuilder.Append("LastName: ").Append(LastName).Append(" || ");
 strBuilder.Append("BornDate: ").Append(BornDate).Append(" || ");
 strBuilder.Append("Country: ").Append(Country);

 return strBuilder.ToString();
 }
}

Klasa, wyposażona w atrybuty z biblioteki RandomData.

var randomizer = new Randomizer<user>();
var users = randomizer.GetRandomCollection(10);

Wygenerowanie kolekcji randomowych użytkowników

Aktualnie w skład biblioteki wchodzą następujące atrybuty:

  • Identity – generuje identyfikator obiektu, można podać z jakim skokiem mają zostac generowane kolejne liczby,
  • RandomBool – generuje wartość true lub false,
  • RandomDateTime – generuje losową datę, można podać wartość minimalną i maksymalną,
  • RandomFirstName – generuje imię z angielskiego słownika imion, można określić, czy ma to być imię męskie czy żeńskie,
  • RandomLastName – generuje nazwisko z angielskiego słownika nazwisk
  • RandomNumber – generuje losową liczbę, można podac zakres,
  • RandomText – generuje napis ‘Lorem ipsum’, można podać ile liter ma być w napisie,
  • RandomValue – losuje jedną z wartości podanych do konstruktora atrybutu.

Zachęcam do pobierania biblioteki i jeśli ktoś ma pomysły na rozwój, bądź komentarze do kodu bardzo proszę o kontakt. Cały kod jest dostępny na githubie, więc możecie go pobierać i jeśli będziecie chcieli go rozwinąć zachęcam do dzielenia się tym również na githubie.

Przepełnienie stosu

Pomijając to, że zaczyna się sesja, więc liczba rzeczy do zrobienia, która nie jest związana z nauką przybrała maksymalny poziom, to już od dość dawna zaczynam być przytłoczony rzeczami do zrobienia (technologiami do nauczenia). Niestety przez to nie udaje mi się wziąć jednej technologii i nauczyć jej się dobrze. Zauważyłem, że liczba rzeczy, które pasowałoby umieć, wzrasta wykładniczo wraz z rzeczami, które już umiesz. Początkowo było fajnie, ale teraz moja lista to-do pęka w szwach, a na moim kindle już prawie brakuje miejsca na nowe książki. Czuje jakbym miał ciągle coś do zrobienia i to uczucie właśnie nie pozwala mi ruszyć nic nowego.

Wcześniej stałem na rozdrożu, uczyć się technologii dekstopowych/mobilnych (WPF, Silverlight), czy lepiej webowych (ASP.NET). Wybrałem webowe, więc odrzuciłem trochę na bok XAML’a, chociaż miałem w nim dużo większe doświadczenie niż w ASP. Po zrobieniu kilku projektów w ASP, nadszedł czas na naukę JavaScriptu, bo przecież aplikacje webowe w dzisiejszych czasach bez js’a wyglądają raczej blado. Po nauczeniu się JS’a nastąpił wielki wybuch nowych technologii z którym nie potrafię sobie poradzić do dziś. Skoro umiem JS’a, to trzeba się nauczyć jQuery, może coffescript, bo każdy tak chwali, nie zapomnijmy o node.jsunderscoreknockout, może też dart, o którym było głośno na Google IO.

Jeśli chodzi o JavaScript, to na pewno coś by się jeszcze znalazło, bo nowych bibliotek ostatnio wyrasta jak grzybów po deszczu, ale co z C#, w którym to przecież programuje od dawna. Wydawać by się mogło, że to technologia rozwijana głównie przez Microsoft i wielu nowych rzeczy nie ma. A jednak na mojej liście pojawiło się 8 zadań związanych z .NET-em.

– ASP .NET (do certyfikatu)
– WCF
– Azure
– RavenDB
– Windows Phone 8
– CLR via C# (książka)
– Reactive Extensions
– Powershell

Nawet po odrzuceniu technologii nie webowych, zostaje mi 5 zadań (powershell bardzo przydaje się przy aplikacjach webowych, z resztą nie tylko).  Większość z nich wymaga ok 2-3 tygodni, aby nauczyć się jak używać danej technologii, nie wspominając już o tym, żeby dowiedzieć się jak dokładnie działa.

Pamiętam jak dziś prezentacje Martina Mazura, na DevDay 2012, mówił on wtedy, że warto poznawać nowe języki, technologie, które rozwijają sposób rozwiązywania problemów. Sam widzę, że nauczenie się JavaScriptu zmieniło trochę moje podejście do tworzenia oprogramowania, tylko boje się, że będę musiał wybrać między nauczeniem się bardzo dobrze jednej wybranej ścieżki, a poznaniem podstaw z kilku różnych technologii. Na dzień dzisiejszy zostaje mi ponowne rozpatrzenie mojej listy i wyrzucenie kilku niepotrzebnych rzeczy.

Lazy Loading kontekstu aplikacji

W większościach aplikacji, kontekst ładujemy na starcie. Wtedy mamy najwięcej czasu na zużycie jak największych zasobów procesora przez większą ilość czasu. System ten sprawdza się w grach, zdarzają się jednak aplikacje, które nie zawsze korzystają z załadowanego kontekstu. Warto wtedy zastosować, coś co nazywa się “leniwym ładowaniem”. Oznacza to, że odpowiednie zasoby ładujemy dopiero w chwili kiedy się do nich odwołujemy po raz pierwszy. Dajmy na to, że mamy obiekt ApplicationContext, który zawiera wiele elementów, które aplikacja przy zamykaniu zapisuje w pamięci, natomiast przy uruchamiania wczytuje je z pamięci. Obiekt ten zawiera również jakiś obiekt BigObject, do którego to elementu odwołujemy się tylko w specjalnych sytuacjach, dlatego nie chcemy tego obiektu ładować przy starcie.

public class ApplicationContext
{
    public BigObject BigObject { get; private set; }

    public void LoadContext() {
        BigObject = LoadObject();
    }

    private BigObject LoadObject() {
        //loading object from memory
    }
}

Wystarczy mała zmiana kodu aby stworzyć obiekt, który ładuje się dopiero po odwołaniu się do niego. Ciekawe jest to, jak niewiele kodu trzeba napisać, żeby osiągnąć pożądany efekt.

public class ApplicationContext
{
    private BigObject _bigObject;
    public BigObject BigObject {
        get { return _bigObject ?? (_bigObject = LoadObject()); }
    }

    public void LoadContext() {
    }

    private BigObject LoadObject() {

    }
}

Często jednak wczytanie kontekstu wiąże się z odczytywaniem czegoś z pamięci, więc z operacjami, które mogą trwać sporo czasu jeśli obiekt do załadowania jest sporych rozmiarów. Dzięki temu, że w C# można tak łatwo tworzyć funkcje asynchroniczne, po małej modyfikacji (wystarczy opakować zmienne w klasę Task) możemy stworzyć obiekt, który wczytywać się będzie asynchronicznie.

public class ApplicationContext
{
    private Task<BigObject> _bigObject;
    public Task<BigObject> BigObject {
        get { return _bigObject ?? (_bigObject = LoadObject()); }
    }

    public void LoadContext() {
    }

    private Task<BigObject> LoadObject() {
        //loading object from memory
    }
}

W tym przypadku należy pamiętać, aby przed odwołaniem się do właściwości BigObject postawić słówko kluczowe await.

var bo = await appContext.BigObject;

Jednak czekać na wczytanie danych będziemy tylko za pierwszym razem, każde kolejne odwołanie się do BigObject zwróci nam jego wartość automatycznie.

TypeScript, czyli pomoc w okiełznaniu JavaScript

Jak większość programistów, która wychowała się na tworzeniu aplikacji okienkowych nie jestem wielkim fanem JavaScirpt’u. Niemniej jednak język ten zyskuje coraz większą popularność, nie tylko wśród Web Developerów. Nie można zignorować tego jak bardzo największe firmy (takie jak Microsoft) zachęcają do tworzenia aplikacji mobilnych za pomocą HTML i JavaScript, dlatego myślę, że w niedługim czasie o ile już nie są, programiści tego języka będą bardzo cenni.

In JavaScript, arrays are objects, functions are objects, regular expressions are objects, and, of course, objects are objects.

Sam JavaScript jest językiem dla mnie językiem dziwnym. Można w nim zrobić rzeczy, o jakich nie śniło się nawet zwykłym programistom języków C – podobnych. Niestety zbyt duże możliwości jakie daje ten język nakładają się na to, że o wiele ciężej wykryć błąd w programie, bo tak na prawdę kompilator nie wie czy to błąd, czy użyliśmy tego specjalnie.

Programiści języków statycznie typowanych przyzwyczajeni są, że kompilator im krzyknie kiedy będą chcieli przesłać stringa, zamiast inta. Stety/niestety w JavaScripcie nie było takich możliwości. Ostatnio jednak coraz większą popularność zyskują biblioteki pozwalające na okiełznanie trochę samego JavaScript. Jedną z tych bibliotek, jest rozwijana przez Microsoft, TypeScript.

TypeScirpt

TypeScript w żaden sposób nie zastępuje kodu JS, jest bardziej rozszerzeniem jego składni. Edytor TypeScript wyświetla na raz zarówno kod TS jak i JS, dzięki czemu wiemy, czy na pewno chodzi nam o to co piszemy. Na stronie typescriptlang.org jest dostępnadokumentacja, z której możemy dowiedzieć się jakie funkcjonalności posiada biblioteka. W niniejszym poście postaram się przedstawić tylko największe zalety tego rozszerzenia.

Sprawdzanie typów

selekcja
JavaScript nie jest językiem silnie typowanym, więc zmienna, która jest napisem, za chwilę może być liczbą, lub funkcją. Tak samo zmienne przesyłane do funkcji nie mają w żaden sposób sprawdzanych typów. Tak więc jeśli chcemy być 100% pewni, że przesłana zmienna jest odpowiedniego typu musimy sprawdzać za każdym razem typy argumentów. Na szczęście TypeScript wprowadza możliwość określenia jakiego typu argumentu oczekujemy w funkcji. Nie pozwala to jednak korzystać z przesilania funkcji, bo koniec końców i tak cały kod jest konwertowany na JS.

function add(a: number, b : number){
   return a + b;
}
var sum = add(2, 3);    //OK
sum = add(2.1, 2.3e3);  //OK
sum = add(2, "Ola");    //ERR

Jest to najprostszy przykład sprawdzania argumentów przesłanych do funkcji, Warto jednak zauważyć, że błąd, który wyskoczy przy ostatnim wywołaniu funkcji, wyskakuje jedynie w edytorze TypeScript, więc jeśli ktoś chciałby użyć tej funkcji z poziomu zwykłego JavaScript operacja byłaby w pełni dozwolona, co więcej funkcja zwróciłaby wynik: “2Ola”.

Sprawdzanie typów nie ogranicza się tylko do wartości przychodzących do funkcji, można również określić jakiego typu zmienną, funkcja zwróci. Jeśli tego nie zadeklarujemy, kompilator sam sprawdzi jaki typ zwracamy i zmienną zadeklarowaną z wartości zwróconej będzie traktować jako właśnie takiego typu.

function add(a: number, b : number) : string{
   //return a + b;             //ERR
   return (a + b).toString();  //OK
}

Ostatnią rzeczą, odnośnie sprawdzania typów, którą zamierzam opisać to sprawdzanie jaką funkcję przesyłamy jako argument. Jak było wspomniane na początku w JS nawet funkcje są obiektami, więc często funkcje przesyła się jako parametr innej funkcji. Dzięki określeniu interfejsu funkcji możemy zadeklarować, że oczekujemy funkcji, która przyjmuje liczbę i zwraca liczbę. Jest to coś na kształt delegatów w języku C#.

function doSomething (arg : string, foo : (a : number) => number){
   return arg + " : " + foo(2).toString();
}
var foo2 = function (x : number){
   return "-" + x;
}
/*
Supplied parameters do not match any signature of call target: Call signatures of types
'(x: number) => string' and '(a: number) => number' are incompatible
*/
var res = doSomething("Jan", foo2);     //ERR

Klasy

u have no class
JavaScript jest językiem, w którym klasy określamy poprzez prototyp. Każdy obiekt, posiada swój prototyp, do którego możemy dodawać funkcje, przez co zyskujemy coś na kształt klas. Dziedzicznie natomiast jest tak zawiłe, że trzeba się sporo napisać, żeby osiągnąć wymagany efekt. Na szczęście TypeScript pomoże nam również z tym. Dzięki dobrze znanej z języków C-podobnych składni można definiować klasy, prywatne bądź publiczne zmienne, oraz metody. Poniższy przykład posiada: prywatną zmienną, konstruktor, publiczną metodę oraz prywatną metodę. Podobnie jak we wcześniejszym przypadkach, prywatne zmienne oraz metody są tylko umowne w kodzie TypeScript. Więc z poziomu kodu JavaScript można zarówno się odwołać do zmiennej name jak i wywołać metodę setName.

class MyClass {
   private name : string;

   constructor (nam : string){
      this.setName(nam);
   }
   getName() {
      return this.name;
   }
   private setName(value){
      this.name = value;
   }
}
var ob = new MyClass("Ala");
document.writeln(ob.getName());  
//Alaob.setName("Ola");  //ERR
ob.name = "Ola";    //ERR

Dziedziczenie

Dziedziczenie obiektów jest banalnie proste i oszczędza pisania bardzo wielu linijek kodu. Przykład ze strony typescriptlang.org świetnie pokazuje wszystkie zalety dziedziczenia.

class Animal {
   constructor(public name: string) { }
   move(meters: number) {
      alert(this.name + " moved " + meters + "m.");
   }
}
class Snake extends Animal {
   constructor(name: string) { super(name); }
   move() {
      alert("Slithering...");
      super.move(5);
   }
}
class Horse extends Animal {
   constructor(name: string) { super(name); }
   move() {
      alert("Galloping...");
      super.move(45);
   }
}

var sam = new Snake("Sammy the Python");
var tom: Animal = new Horse("Tommy the Palomino");
sam.move();
tom.move(34);

W obu przypadkach zostaną wywołane funkcje przeciążające.

Intefejsy

Implementowanie interfejsów, chociaż podobne jest do dziedziczenia po klasach, to używane jest do trochę innych rzeczy. Dlatego twórcy TypeScript również pozwolili na tworzenie interfejsów w JavaScripcie. W interfejsach możemy deklarować zmienne bądź metody publiczne. Klasy implementujące te interfejsy muszą zagwarantować obsługę wszystkich metod oraz stworzenie zmiennych przedstawionych w interfejsie. Implementacja odbywa się za pomocą słówka implements, czyli po Javovemu.

interface SayHello {
   hello ();
}
class Animal {
   name : string;
   constructor (name : string){
      this.name = name;
   }
}
class Snake extends Animal implements SayHello{
   hello(){
      return ("ssss " + this.name + " ssss");
   }
}
class Duck extends Animal implements SayHello {
   hello (){
      return ("quack " + this.name + " quack");
   }
}

function echo (soundSource : SayHello){
   alert(soundSource.hello());
   alert(soundSource.hello());
}

var tom = new Snake ("Tom");
var james = new Duck("James");
echo(tom);
echo(james);

Dodatkowe linki
Aby móc korzystać z TypeScript w Visual Studio, trzeba najpierw pobrać plugin. Polecam również zainstalować dodatek do Visual Studio – Web Essentials 2012, który pozwoli na kompilacje kodu TS na JS z poziomu Visual Studio. Poza tym świetny edytor do nauki TypeScript można znaleźć na stronie domowej TypeScript.

Windows 8 Extensions

Już jakiś czas temu udostępniłem na github’ie projekt o nazwie Win8Extensions, w którym miałem umieszczać klasy, które mogą się przydać podczas pisania aplikacji na Windows 8. Na razie aplikacje Windwos Store, które stworzyłem można liczyć na palcach jednej ręki, natomiast z doświadczenia wiem, jakie klasy są zawsze potrzebne podczas pisania tego typu aplikacji. Stworzyłem ten projekt również po to aby zobaczyć co inni myślą o moim kodzie. Jeśli ktoś zajrzy w kod z chęcią wysłucham co powinienem poprawić… Oczywiście komentarze staram się pisać, ale ciężko mi to idzie ;)

W projekcie tym możecie znaleźć przede wszystkim różnego rodzaju konwertery, które nie są tworzone tworzeniu nowego projektu Windows Store, a które mogą się przydać. Między innymi ObjectToVisibilityConverter, który sprawdza czy obiekt jest pusty (null) i jeśli tak zwraca Visibility.Collapsed. W ten sposób możemy ukryć na ekranie ramki, które mają wyświetlić obiekt, ale tylko jeśli nie jest on pusty.

Inną ciekawą klasą, która może zainteresować programistów Windows Store Apps jest ApplicationDataSerializer, który za pomocą jednej funkcji zapisuje i odczytuje wybrany obiekt z i do podręcznej pamięci programu. Obecnie korzysta on z seriazliacji do json’a, natomiast łatwo go przerobić tak aby serializował do xml’a.

Z biegiem czasu, jeśli jeszcze będę pisał aplikacje na Windows 8 będę starał się dodawać nowe rzeczy do biblioteki, może jakieś nowe kontrolki… już nawet mam kilka pomysłów co to mogłoby być. Niczego jednak nie obiecuje, bo jest to jednak projekt robiony w wolnym czasie, więc może być różnie.

Tak jak pisałem wcześniej, jest to moja pierwsza biblioteka OpenSource, więc jeśli ktoś będzie miał jakieś opinie lub pomysły co można tam jeszcze uwzględnić, niech do mnie napisze. No i oczywiście zachęcam do korzystania z tych klas w swoich własnych projektach.

Win8Extensions na GitHub

Zainwestuj w swój sprzęt

Ostatnio zacząłem się interesować trochę tym w co warto inwestować. Właśnie przeczytałem książkę “Bogaty Ojciec, Biedny Ojciec“, w której autor przedstawia jak budować swoje aktywa, tak, aby pieniądze zaczęły na siebie zarabiać. Polecam tą książkę wszystkim, którzy myślą o tym, żeby rozkręcić swój biznes lub po prostu nie widzą siebie, jako pracownika etatowego.

Wracając do tematu, przekładając to na świat zwykłego programisty. Z doświadczenia wiem, że zarówno studenci jak i pracujący programiści większość dnia spędzają przed komputerem. Nie jest to tylko czas spędzony w pracy czy na uczelni, jeśli programowanie jest czyjąś pasją / uzależnieniem, to po powrocie do domu, fotel przed komputerem jest miejscem, gdzie spędza się najwięcej czasu. W końcu to komputer jest naszym największym aktywem, to on na nas zarabia.

W dzisiejszych czasach naprawdę nie trudno jest zarobić jakieś pieniądze na boku, nie mówię tu o nielegalnym dorabianiu na drugi etat, ale o wciąż rosnącym zapotrzebowaniu rynku na różnego rodzaju aplikacje. Najlepszym przykładem są tutaj aplikacje mobilne, których tworzenie wydaje się dosyć proste, a mogą wygenerować znaczny zysk. Jedyne co potrzeba do zarabiania na aplikacjach mobilnych to programista i komputer.

Wiele się mówi, że programiści powinni inwestować w siebie, kupno nowych książek o programowaniu jest dobrą inwestycją, tak samo poznanie nowego języka programowania. Dlatego raz na jakiś czas, jeśli mamy już wystarczająco książek a został jakiś grosz, który możemy wydać, może warto go zainwestować właśnie w komputer.

system-stats

Nie posiadam jakiegoś mega wypasionego komputera, ale uważam, że dobry sprzęt jest niezbędny jeśli chcemy stworzyć coś na prawdę dobrego. Dlatego 4 GB ramu i coś szybszego od Pentium 4, byłoby bardzo wskazane. Co jeszcze może ułatwić i przyspieszyć pracę programiście?

  • Wygodny fotel – wiele osób pisało o tym, czemu wygodny fotel jest inwestycją nie tylko w wasze zdrowie, ale również w efektywność,
  • Dodatkowy monitor – na ten luksus już nie wszystkich może stać, sam nie miałem okazji pracowania na dwóch monitorach dłużej niż przez godzinę, ale z doświadczenia wiem, że czasami przydaje się kawałek dodatkowego miejsca na ekranie,
  • Dysk SSD – taaak! W dzisiejszych czasach dyski te są nadal drogie, natomiast kupno dysku ssd pod system (120GB) kosztuje ok 350 zł, więc myślę, że warto zainwestować taką kwotę jeśli czas czekania na otwarcie Visual Studio zmaleje 3 krotnie.
  • Szybki internet – szybki internet znacznie przyspiesza wyszukiwanie informacji i z przykrością widzę jak niektóre firmy informatyczne oferują swoim pracownikom jakieś strasznie wolne łącza na których znalezienie odpowiedzi na swój problem zajmuje dłużej niż znalezienie odpowiedzi w książce.

Istnieje pewnie jeszcze sporo czynników, które przyspieszają pracę, natomiast chciałem tylko zwrócić uwagę, że warto czasami pomyśleć o rozbudowie swojego centrum dowodzenia, nawet jak rodzina czy znajomi znów narzekają, że “znowu wydałeś całą kasę na komputer!“.