poniedziałek, 30 sierpnia 2010

[Narzędziownia] TestDriven.Net

Ten post jest pierwszym z grupy, którą pozwoliłem sobie nazwać Narzędziownia. Będę w niej umieszczał krótkie posty opisujące ciekawe programy, biblioteki lub serwisy, z których korzystałem w trakcie pracy nad projektem i które mógłbym polecić innym. 

Co to za ustrojstwo?
TestDriven.Net jest pluginem do Visual Studio pozwalającym na wygodne uruchamianie testów jednostkowych. Niby nic, a bardzo ułatwia i przyśpiesza pracę. 
Wtyczka współpracuje z najpopularniejszymi narzędziami do testów jednostkowych, takich jak NUnit, MbUnit czy MSTest. Nie trzeba ich nawet osobno pobierać, instalator TestDriven.Net zadba o pobranie i zainstalowanie odpowiedniej wersji.
Testy możemy uruchamiać z poziomu menu kontekstowego w pliku z testami. I tu objawia się bardzo przydatna funkcja tej wtyczki. Jeśli klikniemy wewnątrz ciała testu zostanie uruchomiony tylko ten jeden test, co przy większej ilości napisanych testów może być sporą oszczędnością czasu. Oczywiście jeśli menu kontekstowe wywołamy z innego miejsca w pliku, zostaną wykonane wszystkie testy

Niesłychanie przydatną funkcją jest możliwość uruchomienia testów z debuggerem. Można łatwo sprawdzić co tak naprawdę wykonuje nasz nowo stworzony kod.
Bez problemu można też uruchomić interfejs graficzny frameworka testującego (w moim przypadku NUnita) czy przerwać aktualnie wykonywane testy. 
Wtyczka automatycznie buduje wymagane projekty, więc nie musimy o tym sami pamiętać. Jeszcze jeden krok to maksymalnej prostoty działania.

Podsumowanie
Mogę z całą stanowczością polecić TestDriven.Net. W znacznym stopniu przyspiesza pracę z testami jednostkowymi i nie wymaga żadnej wstępnej konfiguracji. Oczywiście jeśli ktoś posiada narzędzia w stylu Resharpera, to nie jest mu potrzebne nic więcej do uruchamiania testów. Jednak dla mnie było to znaczne ułatwienie w pracy.

niedziela, 29 sierpnia 2010

Model bazy danych i mapowania NHibernate

Po całym tygodniu szarpanego walczenia z NHibernate'm zdecydowałem się zrobić wstępny projekt bazy danych i odpowiednio go zmapować do wykorzystania w aplikacji. 


Model bazy 
Na początek zakładam nie dużą ilość informacji do przechowywania w bazie, dlatego też jej model nie może być bardzo skomplikowany. 
Graficzna reprezentacja modelu została stworzona w programie MySQL Workbench (nie wiem czy robiłem coś źle, czy też provider System.Data.SQLite nie działa jeszcze zbyt dobrze jeśli chodzi o tworzenie relacji pomiędzy tabelami, ale stworzone przeze mnie relacje nie chciały przenieść się w odpowiedni sposób do graficznego podglądu Data Setu).
Tą nieskomplikowaną strukturę tabel można streścić w prosty sposób:
  • Album - podstawowe informacje o albumie, czyli nazwa, data utworzenia, a także opcjonalnie opis oraz indeks zdjęcia będącego miniaturką
  • Photo - reprezentuje pojedyncze zdjęcie, zawiera ścieżkę bezwzględną do pliku ze zdjęciem, datę dodania oraz nieobowiązkowo opis i przyporządkowanie do jakiegoś albumu
  • Tag - tabela ze wszystkimi dostępnymi tagami
  • PhotoTag - odpowiada za przypisanie tagów do zdjęć
Większość pól jest oczywista i nie wymaga wyjaśnień. Zdecydowałem się na przechowywanie bezwzględnej ścieżki do zdjęcia i zapisanej w formacie bez dodatkowych znaków ucieczki.
Jeśli chodzi o relacje między tabelami to jeden album posiada wiele zdjęć (relacja 1:n), każde zdjęć może posiadać wiele tagów i jednocześnie każdy tak może być przyporządkowany do wielu zdjęć (relacja n:m) oraz każdy album ma jakąś miniaturkę w postaci zdjęcia (relacja 1:1, nie ujęta na diagramie). Co do ostatniej relacji mam pewne wątpliwości. Co w przypadku, gdy album nie zawiera żadnego zdjęcia (a relacja ta wymaga aby posiadał miniaturkę)? Ale ten problem odkładam na później, jeśli to faktycznie będzie problem to zmiana relacji nie powinna być kłopotliwa.


Mapowania NHibernate'a
Nie będę dokładnie opisywał każdego mapowania, pokażę całość dla tabeli Album i fragment dla pozostałych tabel (tabela PhotoTag nie wymaga jakiekolwiek mapowania, gdyż jest ona jedynie pośrednikiem w relacji n:m)
Najpierw stworzyłem klasę Album, która będzie reprezentowała w programie tablicę z bazy danych:
public class Album
{
  public virtual int AlbumId { get; set; }
  public virtual string Name { get; set; }
  public virtual string Description { get; set; }
  public virtual Photo Thumbnail { get; set; }
  public virtual DateTime Created { get; set; }
  public virtual Iesi.Collections.Generic.ISet Photos { get; set; }
}
Warto zauważyć, że do reprezentacji relacji jeden do wielu należy wykorzystać strukturę opartą na ISet<>, reprezentującą zestaw unikalnych (nie powtarzających się) obiektów. Niestety nie można skorzystać z wprowadzonej w C# 4.0 struktury ISet i w dalszym ciągu należy dołączać referencję do biblioteki Iesi.Collections (dostępnej zresztą w domyślnej instalacji NHibernate'a).
Następnie utworzyłem dokument XML mapujący klasę Album:

  
    
      
    
    
    
    
    
    
      
      
    
  

Najciekawszym fragmentem jest mapowanie relacji jeden do wielu. Pomimo początkowych wątpliwości okazało się, że taki zapis jest całkiem jasny i samowyjaśniający.
A mianowicie: tworzymy zestaw danych o nazwie Photos, pochodzący z tabeli Photo, który wykorzystuje typy generyczne i to elementy tego zestawu są odpowiedzialne za informację o relacji, poprzez posiadanie klucza o nazwie Album, a wszystkie elementy tego zestawu będą typu Photo
Po drugiej stronie relacji, w mapowaniu klasy Photo należy zawrzeć informację o tym do jakiego albumu należy zdjęcie. Załatwia to linijka:

Co również jest w miarę oczywiste. Wydaje mi się, że gdy stworzę jeszcze kilka takich mapowań, nie będę musiał więcej zaglądać do przykładów. 
Natomiast jeśli chodzi o mapowanie relacji wiele do wielu pomiędzy tabelami Photo oraz Tag wykorzystujemy worek (ang. bag), czyli strukturę zawierającą mogące się powtarzać obiekty. W klasie jest to odzwierciedlane poprzez strukturę opartą na IList. W pliku mapującym dodajemy znacznik:

  
  

Tłumaczenie tego kawałka jest następujące: struktura nieuporządkowana (bag) o nazwie Tags, działająca w oparciu o typy generyczne, wykorzystuje tablicę PhotoTag do stworzenia relacji wiele do wielu; w tej tablicy klasa Photo (której tyczy się to mapowanie) reprezentowana jest przez klucz obcy w kolumnie Photo, natomiast elementy z drugiego końca relacji odpowiadają kolumnie Tag i są klasy Tag.
Oczywiście dla klasy Tag mapowanie musi być symetryczne.


Do sprawdzenie działania tych relacji napisałem prosty data provider i kilka podstawowych testów, jednak nie podoba mi się jego postać oraz sposób zarządzania sesjami. Muszę trochę te sprawy przeorganizować. I jest znakomity temat na następnego posta.

poniedziałek, 23 sierpnia 2010

SQLite, NHibernate i testy jednostkowe

Oglądając screencasty z Summer Of NHibernate, zacząłem poznawanie NHibernate'a i chciałem wypróbować świeżo zdobytą wiedzę w praktyce, jednak po drodze natrafiłem na kilka trudności i problemów. Dlatego też w tym poście chciałbym napisać jak sobie to wszystko poukładałem, żeby działało tak jakbym sobie tego życzył.

SQLite
Na początek trzeba zaopatrzyć się w dotnetowego wrappera na bibliotekę SQLite (pobranie i zainstalowanie samej biblioteki uważam za krok oczywisty i nie wymagający komentarza). W moim przypadku wybór padł na System.Data.SQLite. Nazwa co prawda dziwna, ale pozwala na odróżnienie od innego providera SQLite.NET. Ma to kolosalne znaczenie przy współpracy z NHibernate (o tym później).
Warto pobrać wersję instalacyjną, dzięki niej od razu dostajemy możliwość pracy z bazami SQLite z poziomu Server Explorera w Visual Studio, co przydaje się później to tworzenia schematów bazy. Dość sporo czasu poświęciłem na znalezieniu menadżera baz danych SQLite, który umożliwiłby mi podstawową edycję baz, jednak w momencie, gdy zorientowałem się, że to samo mam dostępne w Server Explorerze straciły one na znaczeniu. Ale muszę przyznać, że trochę się rozczarowałem dostępnymi opcjami. Udało mi się znaleźć dwa programy godne jakiejkolwiek uwagi: SQLite Administrator oraz SQLite2009 Pro Enterprise Manager, jednak oba zawiodły mnie pod względem usability i strasznie ciężko mi się w nich pracowało. Na szczęście obecne rozwiązanie wystarcza mi w 100%.
Do projektu, w którym będziemy korzystać z NHibernate'a i połączenia z bazą dołączamy referencję do pliku System.Data.SQLite.dll.

NHibernate
Archiwum pobieramy stąd i rozpakowujemy :) Następnie dołączamy potrzebne biblioteki do projektu. I tu pierwszy plus ujemny NHibernate'a. Żeby wszystko się ładnie skompilowało trzeba dodać całkiem sporo bibliotek, a dokładniej: NHibernate.dll, Antlr3.Runtime.dll, Iesi.Collections.dll, NHibernate.ByteCode.Castle.dll. No ale cóż, jak mus to mus, jednak po dołączeniu jeszcze bibliotek testujących tworzy się całkiem długa lista referencji, a co gorsza biblioteki te są wymagane w runtimie dlatego muszą zostać skopiowane razem z plikiem wykonywalnym. 
Same mapowania omówię w którymś z następnych postów razem ze strukturą bazy danych. Teraz przedstawię konfigurację samego NHibernate'a odpowiedzialną za połączenie z bazą danych. Plik konfiguracyjny został zaczerpnięty z przykładowych szablonów dostępnych w domyślnej instalacji NHibernate'a:


NHibernate.Connection.DriverConnectionProvider
NHibernate.Driver.SQLite20Driver
Data Source="D:\Code\DSP\SoH\test.db";Version=3;New=True
NHibernate.Dialect.SQLiteDialect
true=1;false=0
NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle
true
 


Jednak ten szablon zakłada, że wykorzystywany jest inny provider SQLite niż ten, z którego ja korzystałem. Domyślnie do connection.driver_class przypisana jest wartość NHibernate.Driver.SQLite, co wydawało mi się wartością jak najbardziej rozsądną. Jednak gdy korzystamy z System.Data.SQLite ma to być NHibernate.Driver.SQLite20Driver. Koniec kropka i nie ma zmiłuj. 
Na razie większość swojej wiedzy czerpię ze screencastów Summer Of NHibernate i jestem z nich bardzo zadowolony. Jednak lojalnie muszę ostrzec, że już kilka razy zdarzyło mi się, że podana składnia nie chciała zadziałać. Ma to związek z tym, że są one oparte o starszą wersję NHibernate'a, nie ma to jednak większego wpływu na pozytywne wrażenia.
Opierając się właśnie na powyższych screencastach poprawne działanie testuję poprzez serię testów jednostkowych. W czasie nauki pojawia się jednak konieczność testowania operacji dodawania, usuwania oraz aktualizowania rekordów bazy. Aby zapewnić, że każdy test będzie pracował na takiej samej bazie danych (zawierającej te same, zdefiniowane przez nas rekordy) należy przed każdym testem przywracać jej strukturę. W tym miejscu pojawia się miejsce dla:

NDbUnit
Bibliotekę można pobrać stąd (strona zawiera dobry tutorial, na którym zresztą się oparłem). Ma  ona na celu utrzymanie jednolitego i z góry znanego stanu bazy danych przed każdym testem jednostkowym. Współpracuje z wieloma typami baz danych (oczywiście uwzględnia SQLite) oraz z całkiem pokaźną grupą narzędzi do testów jednostkowych (również wykorzystywany przeze mnie NUnit).
Do projektu dodajemy referencję do dwóch plików: obowiązkowego NDbUnit.Core.dll oraz charakterystycznego dla wykorzystywanej bazy danych, w moim przypadku NDbUnit.SqlLite.dll. 
Następnie należy przygotować DataSet zawierający opis struktury bazy danych, którą chcielibyśmy przywracać przed każdym testem. Można to zrobić w prosty sposób z poziomu Visual Studio. Dodajemy do projektu nowy plik typu DataSet (z grupy Data) i nadajemy mu nazwę na przykład Database.xsd. Następnie z Server Explorera przeciągamy do niego te tabele, które mają być aktualizowane w bazie i zapisujemy (można usunąć pliki stworzone automatycznie przez VS).
Teraz należy stworzyć plik zawierający dane testowe. Jeśli już mamy dane w bazie danych najłatwiej posłużyć się metodami udostępnionymi przez NDbUnit. Wystarczy raz wykonać kawałek kodu podobny do poniższego:
string _connectionString = @"data source=D:\Code\DSP\SoH\test.db";
var mySqlDatabase = 
new NDbUnit.Core.SqlLite.SqlLiteUnitTest(_connectionString);
mySqlDatabase.ReadXmlSchema(@"..\..\TestData\Database.xsd");
System.Data.DataSet ds = mySqlDatabase.GetDataSetFromDb();
ds.WriteXml(@"..\..\TestData\TestData.xml");
Mając już te dwa pliki można przygotować sobie strukturę testów jednostkowych. Przed całym Test Fixture (zestaw testów, nie wiem jak to przetłumaczyć na polski) wczytujemy zarówno schemat bazy jak i same dane, dzięki temu mamy bazę danych w stanie wyjściowym:
private INDbUnitTest sqlDatabase;
string connectionString = @"data source=D:\Code\DSP\SoH\test.db";

[TestFixtureSetUp]
public void TestFixtureSetup()
{
 sqlDatabase = new NDbUnit.Core.SqlLite.SqlLiteUnitTest(connectionString);
 sqlDatabase.ReadXmlSchema(@"..\..\TestData\Database.xsd");
 sqlDatabase.ReadXml(@"..\..\TestData\TestData.xml");
}
Następnie przed każdym testem przywracamy pożądany stan bazy:
[SetUp]
public void SetUp()
{
  sqlDatabase.PerformDbOperation(DbOperationFlag.CleanInsertIdentity);
}
I na koniec wszystkich testów pamiętamy, aby przywrócić dane (mogą nam się przydać poza testami).
[TestFixtureTearDown]
public void TestFixtureTearDown()
{
  sqlDatabase.PerformDbOperation(DbOperationFlag.CleanInsertIdentity);
}
Dzięki takiemu podejściu wszystko jest zautomatyzowane i nie musimy się przejmować przywracaniem domyślnego stanu w ciele każdego testu, w którym mamy zamiar modyfikować zawartość bazy.
Wydaje mi się, że takie postępowanie można zastosować jedynie do testowych baz danych. Nie uważam, że byłoby pożądane pracowanie w taki sposób z bazami produkcyjnymi. W końcu tam dane mogą się zmieniać cały czas i nigdy nie będziemy na bieżąco. 

Troszkę się napracowałem, żeby wszystko działało tak jak trzeba, parę razy mocno się zirytowałem, ale za każdym razem okazywało się, że to tylko i wyłącznie wina mojego niedbalstwa lub przeoczenia istotnych faktów. Tak to bywa, jak się nie pisało niczego większego przez ponad pół roku. Ale mam nadzieję, że powoli będę się rozkręcał.

czwartek, 19 sierpnia 2010

Mercurial FTW

Zabawę z Mercurialem rozpocząłem standardowo: ściągnąłem i zainstalowałem co uznałem za konieczne (samego MercurialaPython'aTortoiseHG oraz VisualHG). Potem przyszedł czas na podstawy obsługi, w tym celu przeczytałem (i cześć z tego wypróbowałem samodzielnie) wstęp do Mercuriala. I zachwyciłem się ideami, które leżą u podstaw wszystkich DVSC. 
Lokalne repozytorium daje wspaniałe możliwości. Można pracować samemu (w odłączeniu od reszty zespołu, bez dostępu do centralnego repozytorium) przez dłuższy czas i ciągle czerpać korzyści z kontroli wersji. Commity wykonuje się lokalnie, można je przeglądać, cofać się do poprzednich wersji, przywracać najnowsze i dopiero gdy wszystko wygląda OK, wysłać na serwer. A wszystko to z niesłychaną wręcz prostotą i szybkością, której nie zaznałem podczas pracy z SVNem. 
Instalacja Mercuriala daje możliwość postawienia lokalnego serwera za pomocą jednego polecenia:
hg serve
Dzięki niemu można w bardzo przejrzysty i wygodny sposób przeglądać lokalne repozytorium.
Na pochwałę zasługuje niesamowicie sprawna i transparentna współpraca wszystkich narzędzi: Mercuriala obsługiwanego z linii komend, TortoiseHG oraz VisualHG. Można korzystać naprzemiennie ze wszystkich tych narzędzi w zależności od preferencji i nie powoduje to żadnych konfliktów. TortoiseHG ładnie integruje się z eksploratorem i pozwala na wygodne przejrzenie wszystkich zmian przed wykonaniem commitów. 
Podoba mi się także zastosowany sposób rozwiązywanie konfliktów: najpierw należy pobrać zmienione repozytorium z serwera, wtedy istnieje możliwość podejrzenia zmian na spokojnie w swoim lokalnym repozytorium. Następnie należy rozwiązać konflikty, na przykład za pomocą KDiff3, wykonać nowy commit, który połączy obie wersje i wysłać go na serwer. 
Istnieje jeszcze cała masa możliwości, których nie wypróbowałem i kolejna mnogość opcji, o których nawet nie wiem, ale to co na razie  poznałem pozwala mi mieć nadzieję, że współpraca z Mercurialem ułoży mi się znakomicie. Już widzę dla niego całą masę zastosowań w nadchodzącym semestrze na uczelni, szczególnie przy pisaniu wieloosbowych sprawozdań.

Praca z Mercurialem
Po instalacji proponuję zacząć od ustawienia nazwy użytkownika. Bez tego nie można  nawet wykonywać commitów do lokalnego repozytorium, chociaż ponoć domyślnie ma być możliwość pracy jako default@localhost. W tym celu odnajdujemy plik mercurial.ini w katalogu domowym (w przypadku Win7 mam na myśli C:\Users\<nazwa_uzytkownika>) i dodajemy do niego coś takiego:
[ui]
username = Imię Nazwisko <login@example.com>
Nie będę się tu rozpisywał na temat komend wykonujących konkretne czynności, chcę tylko wspomnieć o kolejności działań podstawowych operacji:
  • pracy z lokalnym repozytorium
    1. stworzenie repozytorium przez hg init
    2. dodanie plików objętych kontrolą wersji przez hg add
    3. praca z plikami
    4. jeśli wszystko jest w porządku to hg commit -m "komentarz"
    5. jeśli nie jest to hg revert
    6. powrót do punktu 3.
  • aktualizacji plików na serwerze
    1. pobranie aktualnej wersji z serwera przez hg pull
    2. wykonanie połączenia z naszą wersją dzięki hg merge
    3. sprawdzenie czy wszystko działa jak należy
    4. wykonanie lokalnego commitu połączonej wersji
    5. przesłanie plików na serwer przez hg push
    Dodawanie plików nieobjętych kontrolą
    Gdy stworzyłem lokalne repozytorium mojego projektu, jeszcze przed przesłaniem na serwer zaobserwowałem niechciane zjawisko. Kontrolą wersji zostały objęte wszystkie pliki w podkatalogach projektu, w tym także katalogi bin i obj. Nie widzę najmniejszego sensu by były  one na bieżąco sprawdzane i kontrolowane.
    Aby temu zapobiec wystarczy stworzyć plik .hgignore (jest on tworzony przez TortoiseHG przy zakładaniu repozytorium) i w nim umieścić wpis:
    syntax: glob 
    
    bin/** 
    obj/**
    
    Dzięki temu, oba katalogi wraz ze wszystkim co zawierają zostaną pominięte przy dodawaniu nowych plików.
    Zastanawiam się ciągle czy nie wykluczyć spod kontroli wersji wszystkich plików *.csproj oraz *.sln, gdyż zmieniają one swoją zawartość, gdy zamykam VS lub dodaję coś do projektów. Tworzy to troszkę zamieszania, jednak na razie wydaje mi się, że mogą one być przydatne w przypadku wielkiej katastrofy.

    wtorek, 17 sierpnia 2010

    First things first!

    Do pracy nad projektem powracam z ponad tygodniowym opóźnieniem spowodowanym mniej lub bardziej losowymi czynnikami, jednak nie wpływa to na mój zapał do pracy :) 
    Początkowo planowałem, że siądę przed VS i zacznę po prostu pisać, a nowe technologie będę poznawał na bieżąco w miarę potrzeb. Po zastanowieniu dochodzę jednak do wniosku, że skoro ten projekt ma mnie jak najwięcej nauczyć to należy do niego podejść mądrze rozsądnie. 
    Nie chcę by spotkała mnie później sytuacja, w której muszę przerabiać projekt w znacznym stopniu tylko dlatego, że wcześniej nie zapoznałem się podstawami. Zdaję sobie sprawę z tego, że refactoring to całkowicie naturalna czynność, jednak obawiam się, iż mógłbym się zbytnio zagmatwać. Zwłaszcza, że będę starał się ogarnąć tyle nowych dla mnie technologii. 
    Dlatego też, kilka najbliższych dni (nieprzekraczalny termin to koniec tego tygodnia) poświęcę na poznanie podstaw i wstępne zapoznanie się z działaniem w akcji nowych narzędzi. 
    Zaczynam od najtrudniejszego moim zdaniem NHibernate'a. Zachęcony tym postem zacząłem oglądać screencasty Summer of NHibernate i wprowadzać pokazane przykłady w życie. Wrażenia wkrótce.
    Potem przyjdzie czas na WPF'a, jednak nie chodzi mi o samo tworzenie interfejsu, które wygląda bardzo przyjemnie szczególnie, gdy używa się Expression Blenda. Bardziej interesuje mnie MVVM. Chciałbym się dowiedzieć czym różni się od MVC i poznać dobre praktyki pisania aplikacji o niego opartych. 
    Na koniec szybkie spojrzenie na nUnit i SQLite. Chciałbym sobie to jakoś ładnie poukładać, żeby praca była wygodna i szybka. Na przykład czy lepiej automatycznie uruchamiać testy po każdej kompilacji czy może tylko od czasu do czasu; albo jakiego wrappera do SQLite użyć. 
    Wszystko w takiej ilości by nie spowodować zbyt dużych opóźnień i jednocześnie powiedzieć mojemu sumieniu, że prace nad tym projektem nie są jedynie dziełem chaosu. Wrażeniami z procesu nauki podzielę się w kolejnych postach. 

    wtorek, 3 sierpnia 2010

    Narzędzia

        Oto lista narzędzi, z których mam zamiar korzystać podczas pracy nad projektem wraz z krótkim uzasadnieniem wyboru (być może zostanie zmodyfikowana w trakcie postępowania prac):


    • Visual Studio 2010 - wybór chyba oczywisty jeśli chcę w wygodny sposób korzystać z możliwości nowego C# oraz WPFa
    • Expression Blend 4 - słyszałem o Blendzie dużo pochlebnych opinii; co prawda moje umiejętności jako grafika są zerowe, więc nie wykorzystam jego możliwości, ale może ułatwi mi tworzenie interfejsu
    • CodeRush Express - plugin do Visual Studio zwiększający produktywność programisty, w wersji darmowej i mocno okrojonej, jednak dający całkiem przyzwoite możliwości, przynajmniej dla mnie
    • nUnit - środowisko do testów jednostkowych, chyba najwięcej o nim słyszałem, a nie było mi dane nigdy wcześniej z niego skorzystać
    • SQLite - relacyjna baza danych danych przechowywana w pliku lokalnym; pracowałem już z SQL Server Compact dlatego przyszedł czas na coś nowego; do tego na pewno przyda się program do edycji i podglądu baz, ale jeszcze nie zdecydowałem się na żaden konkretny
    • NHibernate - nie mam żadnych doświadczeń w kwestii ORM, dlatego tę bibliotekę wybieram trochę intuicyjnie; mam nadzieję, że ta część projektu da mi największą ilość nowej wiedzy
    • AForge - biblioteka do operacji wszelkich operacji związanych z przetwarzaniem obrazu, sztuczną inteligencją, sieciami neuronowymi i innymi ciekawymi tematami; trochę się z nią już bawiłem i przypadła mi do gustu
    • TortoiseHG oraz VisualHG- odpowiednik TortoiseSVN dla Mercuriala wraz wtyczką do Visual Studio; wcześniej pracowałem wykorzystując SVNa w NetBeansie i jestem tym mocno rozczarowany, mam nadzieję, że ta para się lepiej spisze; hosting kodu na BitBucket
    • WPF NotifyIcon - biblioteka obudowująca klasę NotifyIcon dając możliwości tworzenia bardzo zgrabnych funkcji dla ikonki w trayu; to na wypadek gdybym chciał wyposażyć Chupacabre w taką funkcjonalność
    To z grubsza tyle. Jeśli zajdzie jakaś potrzeba w trakcie prac to lista zostanie uzupełniona.
        Teraz przychodzi czas na odpoczynek. Po powrocie z gór, czyli od poniedziałku (9 sierpnia) zabieram się za kodowanie. Do tego czasu działalność bloga zawieszona :D

    poniedziałek, 2 sierpnia 2010

    Wymagane funkcjonalności programu i wstępny plan pracy

        Dla przypomnienia Chupacabra ma być programem wzorowanym na Picasie od Google'a, czyli aplikacji do katalogowania zdjęć, ich podstawowej edycji, tagowania i synchronizowania z albumem w chmurze. Oczywiście nie mam zamiaru podejmować się napisania aplikacji tak potężnej i doskonale dopracowanej jak Picasa. Planuję zaimplementować tylko podstawowe funkcjonalności, które pozwolą mi na wykorzystanie wszystkich technologii i narzędzi, o których wspominałem w poprzednim poście.
        Oto lista funkcji jakie chciałbym dodać do programu:
    • proste przeglądanie zdjęć - możliwość przejścia przez strukturę katalogów na dysku, wyświetlenie wszystkich zdjęć z folderu w postaci miniaturek oraz oczywiście podgląd pojedynczego zdjęcia z możliwością powiększania oraz obracania
    • tworzenie i zarządzanie albumami - użytkownik może stworzyć albumy zarówno wskazując cały katalog ze zdjęciami, jak i dodawać pojedyncze zdjęcia (być może metodą drag&drop); przy czym jedno zdjęcie może należeć do wielu albumów
    • tagowanie i opisywanie zdjęć - do każdego zdjęcia lub albumu użytkownik może dodać tagi lub opisy; oczywiście wiąże się z tym możliwość wyszukiwania zdjęć
    • podstawowa edycja zdjęć - grupa kilku najbardziej podstawowych operacji na zdjęciach (przycinanie, wyostrzanie, konwersja do zdjęć czarno-białych); celem nie jest napisanie wszystkich tych funkcji samodzielnie, dlatego skorzystam z jakiejś gotowej biblioteki graficznej
    • funkcje społecznościowe - możliwość pobierania i wysyłania zdjęć na np: Facebooka; jest to dosyć mglista wizja, ale jest to opcja, gdyby pozostałe funkcjonalności poszły mi zbyt szybko
        Być może powinienem rozbić to na mniejsze i krótsze do napisania etapy, dla których mógłbym ocenić czas potrzebny na ich realizację, jednak wydaje mi się, że jest jeszcze na to za wcześnie. Nie wiem jak dużo czasu zajmie mi opanowanie tworzenia interfejsu z wykorzystaniem WPFa, ani jak pójdzie mi nauka NHibernate'a. 
        Szczegóły techniczne i narzędzia, które mam zamiar wykorzystać do poszczególnych funkcjonalności opiszę w następnej notce. A później pozostanie już tylko zagłębić się w wir kodowania :)

    niedziela, 1 sierpnia 2010

    Nie próbuj! Rób albo nie rób. Prób nie ma.

    Tym cytatem klasyka rozpoczynam działanie mojego bloga. Zakładam go, gdyż chcę wziąć udział w konkursie "Daj się poznać", ogłoszonym na blogu Macieja Aniserowicza.
    Główną motywacją dla mnie jest możliwość spróbowania Programowania przez eksplorację. Od momentu skończenia sesji chciałem rozruszać się programistycznie po dość monotonnym matlabowym semestrze na uczelni, ale oczywiście jak to zwykle bywa, brakowało chęci i motywacji. Ten konkurs to idealna okazja, żeby coś wreszcie w tym temacie zmienić.

    O co chodzi?
    Założyłem sobie, aby w projekcie wykorzystać jak najwięcej z poniższej puli:
    • Visual Studio 2010 i C# 4.0
    • WPF i Expression Blend 4
    • ORM (zdecydowałem się na NHibernate)
    • testy jednostkowe i TDD (wykorzystam nUnit)
    Są to dla mnie nowości, dlatego na początku prac na pewno sporo czasu poświęcę na ich poznanie.
    Dodatkowo regulamin konkursu wymaga założenia publicznie dostępnego repozytorium kodu. Zdecydowałem się na korzystanie z Mercuriala (wcześniej korzystałem tylko z SVNa, a git wydał mi się troszkę za skomplikowany na początek przygody z DVCS). Jako hosting kodu wybrałem BitBucket.

    Dobra. Ale o chodzi?
    Program, który będę chciał napisać nie będzie ani oryginalny, ani też innowacyjny; nie posiadam umiejętności stwarzania przełomowych idei. Wydaje mi się jednak, że w tym projekcie uda mi się zawrzeć wszystkie zaplanowane założenia.
    Więc co to będzie?
    Być może kiedyś będzie to program podobny do Picasy, czyli program do katalogowania, opisywania, przeglądania i edytowania zdjęć; być może kiedyś będzie rozszerzony o elementy społecznościowe. Dokładniejszy opis tego co chciałbym zaimplementować pojawi się w którymś z najbliższych postów.
    Spodziewam się, że interfejs programu będzie odpychający, a obrzydliwy kod będzie się śnił prawdziwym programistom po nocach, dlatego też znalazłem dla niego wdzięczną nazwę: Chupacabra. Jak już napiszę jakiś kod to będzie on dostępny pod adresem http://bitbucket.org/cieplok/chupacabra, co jakiś czas planuję umieszczanie także skompilowanych wersji.

    Mam nadzieję, że uda mi się pociągnąć ten projekt co najmniej przez te 10 wymaganych tygodni.
    Zapraszam do czytania i komentowania. Ponieważ jest to mój pierwszy blog to wszelkie uwagi są bardzo mile widziane.