ASP.NET MVC - Reflector vs DropDownList

Kolejny odcinek o Reflectorze i MVC, tym razem opowieść spod znaku "przecież to NIE MOŻE nie działać!". Oczywiście bezlitosna rzeczywistość twierdziła inaczej i jak zwykle w takich wypadkach bywa – to ona była górą. Zobaczmy cóż takiego się stało...

Jak zwykle dla uproszczenia stworzę bezsensowny projekcik specjalnie pod ten scenariusz, aby każdy mógł w prosty sposób odtworzyć cały proces. Praktyki stosowane podczas implementacji wcale nie muszą być godne naśladowania, po prostu chodzi o jak najprostszą demonstrację problemu.
Zadaniem moim było wyświetlenie rozwijanej listy elementów oraz zaznaczenie tego, którego ID zostało przekazane do akcji kontrolera. Wydaje się, że nic prostszego, zatem zróbmy to:
1) stwórzmy model, który pomoże nam w silnie typowany sposób przekazać niezbędne dane do widoku:

  1:  public class HomeIndexModel
  2:  {
  3:  	public int? SelectedUserId { get; set; }
  4:  	public ICollection<User> Users { get; set; }
  5:  
  6:  	public HomeIndexModel(int? selectedUserId, ICollection<User> users)
  7:  	{
  8:  		SelectedUserId = selectedUserId;
  9:  		Users = users;
 10:  	}
 11:  }

2) zmodyfikujmy akcję Home/Index tak, aby była w stanie przyjąć odpowiedni parametr i przekazała dane do widoku:

  1:  public class HomeController : Controller
  2:  {
  3:  	public ActionResult Index(int? id)
  4:  	{
  5:  		var users = new List<User> {new User(1, "User1"), new User(2, "User2")};
  6:  		ViewData.Model = new HomeIndexModel(id, users);
  7:  
  8:  		return View();
  9:  	}
 10:  }

3) klasa User jest właściwie oczywista, ale dla pełnej jawności oto ona:

  1:  public class User
  2:  {
  3:  	public int Id { get; set; }
  4:  	public string Name { get; set; }
  5:  
  6:  	public User(int id, string name)
  7:  	{
  8:  		Id = id;
  9:  		Name = name;
 10:  	}
 11:  }

4) wykorzystując projekt MVC Contrib tworzymy listę w bardzo wygodny sposób:

  1:  Users: <%= Html.DropDownList("users", Model.Users.ToSelectList(x => x.Id, x => x.Name, x => x.Id == Model.SelectedUserId)) %>

Dla niezorientowanych: metoda ToSelectList tworzy gotowe do wykorzystania elementy listy przy pomocy trzech wyrażeń lambda. Pierwsze służy do pobrania wartości elementu (value), drugie – wyświetlanej wartości (text), trzecie z kolei definiuje czy dany element ma być aktualnie wybrany czy też nie. Prosto i przyjemnie.

OKej, skoro mamy takie rozwiązanie, to je przetestujmy wchodząc na stronę Home/Index/2. I zonk:

Po kilku minutach zdumienia i tarcia brody (jak to inteligentnie musi wyglądać!) tknięty durnym impulsem zmieniłem przekazaną w pierwszym parametrze docelową nazwę listy z "users" na "x", i... zadziałało:

Na czas, że tak to brzydko określę, "płatny" to w zupełności wystarczyło. Jednak w czasie "wolnym" nie dawało mi to spokoju. Odpaliłem więc wieczorem Reflectora, załadowałem dllkę System.Web.Mvc i zabrałem się do "inwestygacji":

1) Wszystko zaczyna się w metodzie DropDownList, zatem do niej udamy się najsampierw:

2) Po kilku klikach i szybkich nawigacjach docieramy do sedna generacji tagu <select>, czyli prywatnej metody System.Web.Mvc.Html.SelectExtensions.SelectInternal. Od razu widać, że to jakaś skomplikowana potwora. Wiemy jednak jakie przekazujemy parametry, zatem dość łatwo możemy zidentyfikować potencjalnie interesujące źródła tego dziwnego zachowania:

Trochę ten rysunek pomazałem, ale już tłumaczę. Fragmenty 1, 2 oraz 3 wyeliminujemy: pierwsze dwa odpadają z powodu naszych parametrów, a trzeci dotyczy już plucia napisami, gdzie z pewnością wszystko jest w porządku (w końcu po małej modyfikacji strona działa jak trzeba). Zaznaczony fragment nr 4 wydaje się niezmiernie interesujący: ktoś zmienia wartość właściwości Selected dla elementów, które my tak pieczołowicie przygotowaliśmy w naszym aspx! Ma to jakiś związek ze zmienną set, która z kolei tworzona jest z source otrzymanego z obj2 uzyskanego przez wywołanie metody GetModelStateValue lub Eval. Nie jest źle, na pewno zbliżamy się do celu niczym łowczy do łani.
3) Klikamy losowo w jedną z nich, mi akurat trafiło się GetModelStateValue. Rzut oka wystarczył jednak, aby upewnić się, że to nie tu tkwi problem:

4) Przechodzimy zatem do Eval, i okazuje się że tu jest pies pogrzebany:

Dochodzimy do miejsca, gdzie pobierana jest wartość właściwości MODELU (czyli instancji naszej klasy HomeIndexModel) o nazwie odpowiadającej nazwie listy, do tego case-insensitive! W tym przypadku będzie to kolekcja użytkowników o nazwie Users typu ICollection<User>. Oznacza to ni mniej ni więcej, że zgodnie z tą logiką (z fragmentu "4!" z obrazka pod punktem 3) zaznaczone zostaną elementy spełniające warunek: item.Value == <anyUser>.ToString(). Łatwo się domyślić, że nie zostanie zaznaczone NIC, tak jak dało się zaobserwować.

Puenta: tworząc listę rozwijaną przy pomocy metody Html.DropDown i nadając jej nazwę występującą we właściwościach modelu możesz zostać zaskoczony niedziałaniem "serwerowego" zaznaczania elementów na liście. Ja rozwiązałem to zmieniając nazwę właściwości w modelu, jednak ten sam skutek odniosłaby zmiana nazwy listy.


Uff, jak teraz na to patrzę to dochodzę do wniosku że trochę przesadziłem... bo i co to kogo obchodzi?? Jeżeli dotarłeś aż do tego miejsca to gratuluję zawziętości, bo to chyba najnudniejszy post w mojej karierze:).
Bottom-line: reflector rulez, gdyż pozwala zaspokoić ciekawość dociekliwego programisty. Tutaj z pewnością prościej byłoby ściągnąć kod źródłowy MVC, ale kto by się spodziewał że zagrzebiemy się tak głęboko...

opublikowano 02 lipca 09 06:19 przez Procent | 1 komentarzy   
Zarejestrowano w kategorii: , , ,
Visual Studio 2010: Zwijanie regionów

Regiony w Visual Studio to byt bardzo przydatny. Biorąc je za pewnik – bardzo łatwo lekceważyć ich wkład w organizację i przejrzystość kodu. Szczególnie mocno docenia się je, gdy przyjdzie korzystać z IDE które ich nie oferuje. Kilka lat temu musiałem napisać projekt w Javie i, nie interesując się zbytnio milionem dodatków do Eclipse, po prostu odpaliłem środowisko i zacząłem pisać. Staram się nie nadużywać regionów, bo często są one oznaką złego designu aplikacji, ale wtedy przekonałem się że ich całkowity brak potrafi dać się we znaki.
Tym bardziej bolałem nad dość marnymi możliwościami zarządzania regionami w Visual Studio. Resharper jako tako przychodzi z pomocą, dostępne są też darmowe narzędzia stworzone w tym celu (jak chociażby Regionarate), ale i tak najczęściej wykorzystywaną funkcjonalnością związaną z regionami jest ich... zwijanie i rozwijanie! Niestety w VS 2008 i wcześniejszych w celu zwinięcia regionu trzeba było kliknąć w magiczny mikroskopijny krzyżyk bądź, mając kursor na linii regionu, wcisnąć megaprzydatną kombinację klawiszy ctrl+m, ctrl+m. Trochę trwało zanim dowiedziałem się o jej istnieniu i zdecydowanie uprościła mi życie:).

Ale do rzeczy. W nowym Visualu zwijanie regionów będzie dużo prostsze. Wystarczy bowiem najechać kursorem na brzeg marginesu znajdującego się w obrębie regionu, a cały region zostanie podświetlony. Dwukllik z kolei spowoduje zwinięcie regionu, bez celowania w durny krzyżyk:

To samo tyczy się wszystkich bloków kodu (jak np. metody), nie tylko regionów. Mała rzecz a cieszy.

opublikowano 30 czerwca 09 06:23 przez Procent | 3 komentarzy   
Zarejestrowano w kategorii:
Strongly-typed DisplayValue i DisplayMember / DataValueField i DataTextField

Ileż to razy zmuszeni jesteśmy pisać kod temu podobny:

  1:  list.ValueMember = "Id";
  2:  list.DisplayMember = "Name";

Na CodeGuru niejednokrotnie pytano o jakiś sposób na rozwiązanie tego problemu. Podawanie stringów jest ZŁE, niewygodne i bardzo podatne na błędy wszelakie. Zmiana nazwy właściwości rozwala UI, refactoring bez dodatkowych narzędzi jak Resharper potrafi napsuć sporo krwi (a i z pomocą R# wcale przyjemny nie jest)... Syf, kiła i mogiła.
Postanowiłem poeksperymentować w tym obszarze i oto co udało mi się osiągnąć. Mając klasę User:

  1:  public class User
  2:  {
  3:  	public int Id { get; set; }
  4:  	public string Name { get; set; }
  5:  }

Możemy zrobić coś takiego:

  1:  list.ValueMember<User>(u => u.Id);
  2:  list.DisplayMember<User>(u => u.Name);

Fajnie, prawda? Zobaczmy jak taka magia wygląda pod spodem.
Wykonanie tych instrukcji bez podawania nigdzie jawnie żadnego stringa możliwe jest dzięki LINQ, a dokładniej klasie Expression. O niej i wszystkim co się z nią wiąże napiszę być może kiedy indziej (a nawet jeśli nie to zachęcam do samodzielnego zapoznania się z tematem), dzisiaj natomiast ograniczę się do pokazania metod zademonstrowanych powyżej:

  1:  public static class ListControlExtensions
  2:  {
  3:  	public static void ValueMember<T>(this ListControl _this, Expression<Func<T, object>> retrieve)
  4:  	{
  5:  		_this.ValueMember = GetMemberName(retrieve);
  6:  	}
  7:  
  8:  	public static void DisplayMember<T>(this ListControl _this, Expression<Func<T, object>> retrieve)
  9:  	{
 10:  		_this.DisplayMember = GetMemberName(retrieve);
 11:  	}
 12:  
 13:  	private static string GetMemberName<T>(Expression<Func<T, object>> retrieve)
 14:  	{
 15:  		Expression body = retrieve.Body;
 16:  
 17:  		MemberExpression memberExpression;
 18:  
 19:  		// reference type -> no conversion needed to object type
 20:  		if (body is MemberExpression)
 21:  		{
 22:  			memberExpression = (MemberExpression)body;
 23:  		}
 24:  		// simple type => boxing/conversion needed to return object type
 25:  		else if (body.NodeType == ExpressionType.Convert && ((UnaryExpression)body).Operand is MemberExpression)
 26:  		{
 27:  			memberExpression = (MemberExpression)((UnaryExpression)body).Operand;
 28:  		}
 29:  		else
 30:  		{
 31:  			throw new ArgumentException(string.Format("This lambda: {0} is not supported!", retrieve.Body.ToString()));
 32:  		}
 33:  
 34:  		return BuildMemberPath(memberExpression);
 35:  	}
 36:  
 37:  	private static string BuildMemberPath(MemberExpression memberExpression)
 38:  	{
 39:  		string thisName = memberExpression.Member.Name;
 40:  
 41:  		if (memberExpression.Expression is MemberExpression)
 42:  			return BuildMemberPath((MemberExpression)memberExpression.Expression) + "." + thisName;
 43:  		return thisName;
 44:  	}
 45:  }

Jak widać kluczowym elementem jest metoda GetMemberName. Zwraca ona podane wyrażenie lambda w postaci tekstowej, w sam raz do przypisania do DisplayMember (lub, jeśli już przy tym jesteśmy, do DataTextField w kontekście aplikacji web).
Takie operacje sprawdzane w czasie kompilacji są nam udostępnione, ponieważ jako parametr tych metod przyjmujemy Expression<Func<...>> a nie samo Func<...>.  Dzięki temu cała instrukcja rozbita na części pierwsze stoi przed nami (p)otworem. Logika przedstawionych operacji jest bardzo prosta:
1) sprawdzamy, czy całe wyrażenie jest pobraniem wartości jakiejś składowej klasy –> jeśli tak, budujemy z niego tekst
2) jeśli nie, sprawdzamy, czy mamy przypadkiem do czynienia z rzutowaniem jako główną operacją wyrażenia; do mechanizmu możemy przekazać wyrażenie zwracające object (dokładniej: Func<T, object>), więc w przypadku typów prostych (jak np. int) musi zajść tzw. boxing; w tym przypadku zakładamy, że "podrzędne" do rzutowania wyrażenie jest pobraniem wartości ze składowej klasy i na nim opieramy budowanie tekstu
3) jeżeli żaden z powyższych scenariuszy nie jest spełniony, wyrzucamy wyjątek, na przykład dla wywołania

  1:  list.ValueMember<User>(u => u.Id + 666);

otrzymamy komunikat: 

Budowanie tekstu to prosta rekurencja wędrująca po wywołaniach kolejnych składowych i sklejająca poszczególne części. Dzięki temu wywołanie:

  1:  list.ValueMember<User>(u => u.UserAddress.AddressCity.Name);

wygeneruje tekst: "UserAddress.AddressCity.Name".

ALE HOLA HOLA! Oczywiście takie wywołanie na niewiele się zda w przedstawianym scenariuszu. Jak wiadomo, zarówno Windows Forms ze swoimi ValueMember i DisplayMember jak i ASP.NET z DataValueField i DataTextField nie wspierają wywoływania zagnieżdżonych właściwości. Dlatego też pomimo faktu, że mamy mechanizm potrafiący spisać dowolnie skomplikowany łańcuch zagnieżdżeń, i tak wykorzystać możemy jedynie jego najprostsze działanie w postaci u => u.Id czy u => u.Age. Ale w końcu lepsze to niż to co mieliśmy wcześniej.

Tak czy siak zachęcam to eksplorowania tej działki .NETa, ponieważ można natknąć się na naprawdę interesujące zastosowania eliminujące dręczące nas problemy.

opublikowano 18 czerwca 09 07:27 przez Procent | 2 komentarzy   
Zarejestrowano w kategorii: , , , ,
Zawód - programista. Rozmowa kwalifikacyjna.

Jakiś czas temu Gutek opublikował posta z poradami dotyczącymi pisania CV. Ja zapowiadałem z kolei, że przeleję kiedyś w zerojedynkową przestrzeń swoje refleksje na temat rozmów kwalifikacyjnych na stanowisko programisty. Kilka razy zmieniałem pracę, zatem siłą rzeczy kilka*X rozmów mam za sobą. Popędzony niedawno mailem przez jednego z Czytelników:) postanowiłem obietnice te wprowadzić w życie.
Przedstawione tu porady mogą komuś pomóc, ale jednocześnie nie należy ich traktować jak biblijnych wytycznych. Po prostu "mi tak się wydaje", i tyle. Mam jednocześnie nadzieję, że jak zwykle w takich sytuacjach pod postami pojawią się komentarze prezentujące doświadczenia i wskazówki innych osób, podnosząc wartość owych wypocin.


1) Naucz się mówić o sobie

Jeżeli przeszedłeś wstępną rekrutację, czyli Twoje CV nie poszło do kosza i otrzymałeś zaproszenie na rozmowę kwalifikacyjną - czas na dalsze przedstawienie siebie. Na rozmowę idziesz po to, aby potencjalny przyszły pracodawca mógł poznać kim jesteś. Zastanów się jakie masz cechy charakteru ważne pod kątem zawodu programisty. Bardzo ważne jest, abyś na pytania "co sprawia ci największą satysfakcję?", "dlaczego zostałeś programistą?", "kim chcesz być za X lat?" miał gotową sensowną odpowiedź. Czasami takie rzeczy wydają się oczywiste i banalne, ale przed rozmową sam zadaj sobie kilka takich pytań i zobacz, czy umiesz natychmiast na nie odpowiedzieć.
Bycie bezpośrednim tematem rozmowy nie powinno cię krępować czy sprawiać, że czujesz się niezręcznie - w końcu dokładnie po to tam jesteś. Nie jest to też pora na kokieteryjną skromność - chwal się swoimi zaletami, osiągnięciami i pokazuj swoje dobre strony. Przed rozmową postaraj się przez kilka minut mówić o sobie do lustra, zobacz czy przychodzi ci to z trudem. Poćwicz w razie potrzeby. Jeśli na pytanie "co jest twoim największym osiągnięciem?" rozdziawisz japę, wybałuszysz oczy i powiesz "eee... nie wiem" to zmarnujesz czas i swój, i rozmówcy. Nie chodzi o to żebyś był mega-pewny siebie czy zgrywał nie wiadomo kogo, tylko o to żebyś potrafił w sensowny sposób pokazać pracodawcy kim naprawdę jesteś.

2) Naucz się mówić o swoich projektach

Możesz być pewny, że na rozmowie padnie pytanie o twoją przeszłość, wykonane projekty i inne osiągnięcia. Sama rozmowa to nie jest dobry moment na przypominanie sobie szczegółów dotyczących danych okresów w twoim życiu. Szanuj czas rozmówcy i przygotuj się na taki temat. Zobacz co masz zawarte w CV i spróbuj sam sobie opowiedzieć o każdej informacji z nim zawartej.
Masz tam jakiś projekt? Postaraj się w minutę sklecić opowiastkę o nim, niech otrzyma od ciebie trochę emocji i stanie się częścią twojej historii. Po co go realizowałeś, z kim to robiłeś? Jakich narzędzi użyliście, co ci się w nim podobało a co nie? Na jakie problemy się natknęliście? Co dało ci tworzenie tego rozwiązania - może inne spojrzenie na jakiś framework, może nowe doświadczenie w pracy grupowej, może wreszcie przekonałeś się do takiego a nie innego stylu kodowania? Cokolwiek. Żaden projekt nie powinien być pustym wpisem w CV.

3) Naucz się mówić o swoich oczekiwaniach

Bądź świadom tego, czego oczekujesz od swojej przyszłej pracy - nie tylko finansowo. I mów o tym, jasno i klarownie. Postaraj się, aby rozmówca dokładnie zrozumiał co jest dla ciebie niezbędne do zawodowego zadowolenia. U mnie osobiście rzeczą absolutnie najważniejszą był całkowicie uregulowany czas pracy i wydaje mi się, że na każdej rozmowie bardzo wyraźnie dawałem to do zrozumienia. Nie akceptuję czegoś takiego jak nieoficjalne "nadgodziny", moim zdaniem równo o ustalonej godzinie powinno się wyłączać komputer i wychodzić z biura.
Mów o tym co jest dla ciebie najważniejsze i obserwuj reakcje - jeżeli któryś z kluczowych dla ciebie warunków prawdopodobnie nie będzie spełniony to szczerze radzę - poszukaj sobie innego miejsca.

4) Mów "prawdę i tylko prawdę"

Pisanie naciąganej nieprawdy w CV to idiotyzm. Mówienie tego na rozmowie prosto w oczy potencjalnemu pracodawcy to idiotyzm do kwadratu. Jeżeli coś umiesz - chwal się tym. Jeżeli czegoś nie umiesz - przyznaj się do tego. Pójście inną drogą jest po prostu głupie. W końcu idziesz na rozmowę żeby przekonać do siebie pracodawcę. A jeżeli uda ci się to przy pomocy kłamstewek i robienia z siebie fałśzywego megaboga - prawda i tak wyjdzie na jaw już na początku pracy. A wtedy... wstyd i zębów zgrzytanie.

5) Zadawaj pytania

Pamiętaj o tym, że "rozmowa kwalifikacyjna" to nie jednostronny wywiad. Ja zawsze traktowałem takie spotkanie jako egzamin obu stron - zarówno ja muszę być zaakceptowany przez firmę, jak i firma przeze mnie. Pytaj o wszystko, co ma dla ciebie jakąkolwiek wartość. Pisałem kiedyś o typach pracy - każdy przez tą samą nazwę może rozumieć trochę co innego. Mimo to każdy ma jakieś swoje wyobrażenie "pracy idealnej". O której zaczyna się i kończy praca? Którego dnia miesiąca pensja wpływa na konto? Czy zespół spotyka się po pracy? Osobę techniczną można pomęczyć bardziej. Jakie narzędzia poza Visual Studio są wykorzystywane? Czy odbywają się wewnętrzne szkolenia? Czy piszą testy jednostkowe, jeśli tak to czego do tego celu używają? Czy uczestniczą w konferencjach, czytają blogi, prenumerują techniczne pisma? W jaki sposób tworzą warstwę dostępu do danych, jakich frameworków wykorzystują w warstwie prezentacji?
Nawet jeśli pytanie wydaje ci się głupie, ale mimo to ciekawi cię odpowiedź na nie - ZADAJ JE. Po wyjściu z rozmowy powinieneś mieć wszystkie informacje potrzebne do postanowienia "czy chcę tam pracować". Po podpisaniu umowy za późno jest na odkrywanie przykrych niespodzianek w stylu "od dziś przez najbliższy miesiąc będziesz klepał procedury składowane".

6) Rozglądaj się

Zwracaj uwagę na miejsce, które niedługo może być twoim drugim domem. Czy pracujący tam ludzie wyglądają na zadowolonych czy tylko czekają na fajrant? W miarę możliwości zerknij do pokoju programistów - panuje tam grobowa cisza czy może gra muzyczka? Rozmawiają ze sobą czy każdy siedzi nieruchomo wpatrzony we własny ekran? Zobacz też jak wygląda praca w kontekście aktualnej pory dnia. Ja kiedyś byłem na rozmowie o godzinie 18 i widziałem, że praca idzie pełną parą. Od razu wiedziałem, że to nie miejsce dla mnie - o tej porze chcę być już od dawna w domu.

7) Bądź sobą

To jest chyba najważniejszy ze wszystkich punktów. Pracodawca musi wiedzieć, jaki naprawdę jesteś. W ten sposób będzie potrafił zaplanować twoją rolę w zespole, jeśli postanowi cię wybrać. Będzie także w stanie odrzucić twoją kandydaturę, jeżeli uzna że absolutnie się do tego konkretnego zespołu nie nadajesz, i będzie to z korzyścią również dla ciebie.
Jesteś ponurym mrukiem, który najchętniej nałoży słuchawki na uszy i zajmie się pracą, a wspólne obiadki nie są mu potrzebne - jak ja? Bądź taki na rozmowie! Przecież już w pierwszych dniach ewentualnej pracy wyjdzie szydło z worka. Nie staraj się na siłę prowadzić zabawnej konwersacji, jeżeli nie leży to w twojej naturze - będzie to wyglądało żałośnie, a i tak łatwo jest poznać czy zachowujesz się naturalnie, czy też jakieś aspekty twojego zachowania są wymuszone.
Pamiętaj, że oprócz kwalifikacji technicznych ważne jest również usposobienie i charakter. ALE - tak samo jak w kwestiach technicznych, tak i w personalnych powinno się być szczerym i uczciwym. Chcesz przecież, aby pracodawca wybrał CIEBIE. CIEBIE, a nie kukłę która po prostu wygląda jak ty, a powstała na potrzeby tej jednej rozmowy.

opublikowano 15 czerwca 09 06:34 przez Procent | 3 komentarzy   
Zarejestrowano w kategorii: ,
ASP.NET MVC i Unity

Nadejszła wiekopomna chwila – ASP.NET MVC już od jakiegoś czasu egzystuje jako oficjalny produkt, więc oto najwyższa pora na zapoznanie się z nim. Cierpliwie przeczekałem wszystkie ochy i achy, pokonałem chęć bycia "trendy";) i zabieram się za to dopiero teraz.

Na pierwszy ogień poszło wpasowanie w cały mechanizm kontenera Dependency Injection tak, aby kontrolery brały się właśnie z niego. Wklejenie gotowych kilku linijek kodu byłoby dość nudne, więc postanowiłem tym razem przedstawić swoje poszczególne kroki i myśli lęgnące się w mózgu podczas poznawania zupełnie nieznanego wcześniej kodu (co wcale, uprzedzam, nie oznacza, że będzie ciekawie!). Poniżej zatem wierne odzwierciedlenie mojej ścieżki od koncepcji do rozwiązania:

1) Najpierw należało zidentyfikować SKĄD te kontrolery się biorą. Bystre moje, niczym woda wiadomo gdzie, oczy, zauważyły, że każdy kontroler dziedziczy z klasy bazowej o niespodziewanej i zaskakującej nazwie... Controller. I to tyle czego oczekuję od Visual Studio, czas na przesiadkę do Reflectora. Po uruchomieniu tego cuda i wciśnięciu ctrl+o (czyli Open File) odszukałem dllkę zawierającą wszystkie tajemnice ASP.NET MVC, czyli:

(zawczasu dodałem ją do repozytorium projektu wiedząc, że mój wybór tym razem padnie na tą technologię)
2) Załadowawszy żądany zestaw (jakie megamądre stwierdzenia z mych rąk dziś płyną, a niech mnie!) zabrałem się za jego przeszukiwanie. Klawisz F3 otwierający panel wyszukiwania był w tym wypadku niezastąpiony. Niezwłocznie przystąpiłem do poszukiwań:

3) Jakże gładko poszło! Dwuklik na tym interesującym wierszu przeniósł mnie w panel nawigacji po bibliotekach i typach. Z ciekawości należało zanalizować pochodzenie klasy Controller, bardzo prawdopodobne było że w infrastrukturze ASP.NET MVC jest jakaś bardziej generalna klasa czy interfejs. A jakże:

Nie dość, że mamy ControllerBase, to jeszcze implementuje ona najwyższy w hierarchii interfejs IController. To musiało być to, byłem święcie przekonany że cokolwiek nie tworzyłoby instancji poszczególnych kontrolerów, zwracałoby je właśnie w postaci implementacji tego interfejsu. Kolejny dwuklik scentralizował mój świat na tym interfejsie, w którym mogłem się zagrzebać.
4) Zawartość interfejsu interesowała mnie co najwyżej średnio, co nie przeszkodziło jednak w chwilowym zboczeniu z drogi w celu dowiedzenia się, że jedyna odpowiedzialność kontrolera to "zrobienie czegoś" (w metodzie Execute()) mając do dyspozycji informacje o bieżącym żądaniu http oraz coścośtam związanego z url rewritingiem. Na szczęście Reflector posiada przycisk BACK, który pozwoli wygrzebać się z kodowego bagna i wrócić do odpowiedniego miejsca nawet jeśli bardzo damy się ponieść duchowi eksploratora:

Po powrocie do interfejsu kliknąłem prawym przyciskiem, a następnie wybrałem Analyze... zobaczymy gdzież to ów interfejs jest wykorzystywany.
5) W oknie analizatora rozwinąłem odpowiednie grupy i cóż się okazało? A-HA, mamy cię! To już nawet Gosiu by się domyślił, że IControllerFactory tworzy kontrolery:

Przeszedłem zatem w to miejsce aby kontynuować badania.
6) Po wciśnięciu ctrl+r, równoważnym z wybraniem Analyze z menu kontekstowego, ponownie znalazłem się w oknie analizatora. I jakież to ciekawe rzeczy ukazały się moim astygmatycznym ślepiom:

BINGO! Co prawda od razu pojawiła się myśl "hmm, dwa tak mocno powiązane ze sobą typy nazywające się - IControllerFactory oraz ControllerBuilder - tak, jakby robiły dokładnie to samo... ciekawe dlaczego?", ale tym razem poskromiłem ciekawość i zostawiłem inwestygację na kiedy indziej.
Czyli już wiem co trzeba wywołać, aby podmienić standardowy sposób tworzenia kontrolerów. Zostały pytania: GDZIE to zrobić, JAK się do owej metody dostać i CO jej przekazać?
7) Kolejne sekundy z Reflectorem przyniosły odpowiedzi na dwa pierwsze pytania:

W statycznym konstruktorze tworzona jest domyślna instancja Buildera, a właściwość Current właśnie ją zwraca. Nie mamy co prawda do czynienia z Singletonem, ale już znam odpowiedź na pytanie "JAK?". O tak: ControllerBuilder.Current.SetControllerFactory(...). A "GDZIE"? Najpewniej najstosowniejszym miejscem będzie kod wykonywany podczas uruchomienia aplikacji, więc domniemana lokalizacja to Application_Start() w Global.asax.cs.
8) Czas zmierzyć się z pytaniem trzecim: CO tam wrzucić? Aby na nie sensownie odpowiedzieć, należy przyjrzeć się istniejącym implementacjom IControllerFactory. A w tym przypadku - jedynej istniejącej implementacji.

Krótki rzut oka na zawartość klasy DefaultControllerFactory wystarczył do podjęcia decyzji: oto będzie właśnie matka mojej implementacji; za dużo mądrych rzeczy tam się musi dziać w tych wszystkich prywatnych składowych, aby wymyślać koło na nowo i próbować przekodować to samo w swoim, notabene wolnym, czasie. Zawęziłem zatem swoją analizę jedynie do metod zwracających IController – jako kandydatów do ewentualnego nadpisania. Idealna do tego celu okazała się metoda GetControllerInstance():

Jedyne co tak naprawdę robi oprócz sprawdzania argumentów i rzucania wyjątków to wywołanie Activator.CreateInstance(Type), czyli jest to perfekcyjnie zlokalizowany kawałek kodu do podmiany! Zauważyć warto, że oznaczona jest modyfikatorami "protected internal", których występowanie czasami BŁĘDNIE tłumaczone jest jako: "metoda widoczna jedynie dla klas zadeklarowanych w tym samym assembly i dziedziczących z jej właściciela”. Zapamiętać należy, że tak naprawdę stawiany tam jest operator OR, a nie AND! Poprawne wyjaśnienie: "metoda widoczna dla klas zadeklarowanych w tym samym assembly ORAZ dla klas dziedziczących z jej właściciela”. Tak więc możemy ją sobie spokojnie nadpisać.
9) OKej, posiadając te wszystkie informacje można zakodować co następuje:

  1:  public class UnityControllerFactory : DefaultControllerFactory
  2:  {
  3:  	private readonly IUnityContainer _container;
  4:  
  5:  	public UnityControllerFactory(IUnityContainer container)
  6:  	{
  7:  		_container = container;
  8:  	}
  9:  
 10:  	protected override IController GetControllerInstance(Type controllerType)
 11:  	{
 12:  		return (IController)_container.Resolve(controllerType);
 13:  	}
 14:  }

Tyle zabiegów sprowadziło się do właściwie jednej linijki, uzupełnionej o:

  1:  protected void Application_Start()
  2:  {
  3:  	ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(Unity.Container));
  4:  	RegisterRoutes(RouteTable.Routes);
  5:  }

, gdzie statyczna klasa Unity to mój własny helper.
I bardzo dobrze. Tym lepiej, że działa bez zarzutu!


To już koniec wycieczki, proszę wysiadać. Mam nadzieję, że przekonałem choć jedną "niewierzącą" osobę jak potrzebnym i wspaniałym narzędziem jest Reflector. Okazało się również, że o ile Google jest zdecydowanie najszybszym sposobem na znalezienie odpowiedzi, jednocześnie nie jest to najbardziej satysfakcjonująca i niosąca najwięcej wartości edukacyjnych droga.
Dopowiem jeszcze, że w rzeczywistości podróż ta trwała około kwadransa. Dopowiem też, że po tym wszystkim z ciekawości poprzeglądałem internet w poszukiwaniu lepszych rozwiązań i... zdziwiłem się jak bardzo można nakombinować, żeby skomplikować sobie życie. Znalazłem sporo alternatyw (bardzo zresztą podobnych), każda jednak jednak miała więcej linii kodu. Po co?

Najczęściej the simpler => the better.

opublikowano 10 czerwca 09 06:28 przez Procent | 7 komentarzy   
Zarejestrowano w kategorii: , , ,
LLBLGen Pro – płatny O/R Mapper. Czy warto?

A cóż to i dlaczegóż to

Niedawno Szymon napisał posta o O/R Mapperach. Korzystając z impulsu postanowiłem także popełnić co nieco w tym temacie, tym bardziej że tą konkretną notkę zaplanowałem przynajmniej 2 miesiące temu. Może ona być uzupełnieniem dla projektów wspomnianych przez Szymona, czyli NHibernate, Linq2Sql i Entity Framework.
Słowem wprowadzenia...
LLBLGen Pro to płatny O/R Mapper od firmy Solutions Design. Najważniejszym człowiekiem za nim stojącym jest Frans Bouma – na to nazwisko natykałem się w internecie jeszcze przed moim kontaktem z LLBLGen.
"Hola hola, płacić za O/R Mapper??" – wykrzyknąć ktoś może w niezmiernym zdumieniu. No i fakt, cena narzędzia (249 jełro) może być dla "samodzielnych" programistów nieco odstraszająca. Warto jednak pamiętać o tym, że fakt "darmowości" bądź "OpenSourcowości" jakiegoś produktu w wielu firmach automatycznie go dyskwalifikuje. W takich sytuacjach programistów w nich pracujących można podzielić na cztery grupy pod względem implementacji dostępu do danych:
1) ręczne pisanie procedur / zapytań... wszyscy byliśmy w tym miejscu i każdy się chyba zgodzi, że nie jest to wymarzony sposób na pracę z danymi, nawet jeśli większość kodu sobie wygenerujemy jakimś pisanym domowymi sposobami generatorem
2) wykorzystanie propozycji z Redmond, czyli Linq2Sql (który jest technologią umierającą), Entity Framework (o którym można przeczytać wiele, z czego póki co 90% to narzekania i wytykanie błędnych rozwiązań; co się pewnie trochę zmieni po wypuszczeniu kolejnej wersji) czy DataSety (o których pisać nawet nie będę, bo traktowanie ich jako technologii dostępu do bazy danych w "normalnej aplikacji" to trochę naciągane rozumowanie)
3) pisanie "własnego O/R Mappera" – tworzyłem kiedyś w pracy coś takiego i nawet zgrabnie tłumaczyło zapytania obiektowe do postaci SQL; dla mnie osobiście to zadanie się podobało, ponieważ było fajnym wyzwaniem architektoniczno-programistycznym; patrząc jednak z punktu widzenia pracodawcy (który chyba sobie z tego do końca sprawy nie zdawał), to pieniądze wydane na pensje pracowników biorących udział w tworzeniu tego projektu (bo nie robiłem wszystkiego tylko i wyłącznie sam) można było wydać na licencje chociażby takiego LLBLGen dla całego działu dev i wyszłoby się na plus: kasy by jeszcze zostało, a firma miałaby gotowy do użycia, przetestowany przez setki klientów, niewymagający ciągłych modyfikacji, supportowany na zewnątrz, dopieszczony produkt, oferujący 100x więcej funkcjonalności niż to co udało mi się wypracować
4) kupno narzędzia, za którego poprawne działanie, poprzez pobranie opłaty za licencję, odpowiedzialna jest firma zewnętrzna

Nie wiem czy się zgodzicie (podejrzewam że tak), ale wg mnie rozwiązanie 4) jest rozwiązaniem najlepszym. Zobaczmy zatem co oferuje nam najbardziej znany produkt z kategorii "płatnych ORM dla .NET". Dobrze jest wiedzieć, że coś takiego istnieje, a z moich obserwacji wynika że w Polsce stosunkowo niewiele osób o nim słyszało.


Cały poniższy tekst nie ma być tutorialem "jak zrobić sobie aplikację z LLBLGen" – od tego jest (całkiem dobra i dość wyczerpująca zresztą) dokumentacja. Nie ma być też dokładnym omówieniem założeń produktu (te z kolei znajdziemy w sekcji "Concepts" wspomnianej dokumentacji). Ma być raczej zbiorem przykładów, uwag i spostrzeżeń, które rzuciły mi sie w oczy podczas dwumiesięcznej pracy z LLBLGen na podstawowym poziomie "pobierz/dodaj/zaktualizuj/usuń". Po lekturze czytelnik powinien być w stanie ocenić czy w ogóle mógłby w przyszłości rozważyć zastosowanie takiego rozwiązania. 
Przykłady oparte będą na bardzo prostej bazie danych: użytkownik ma blogi, blog ma posty, a posty są połączone relacją wiele do wielu z tagami:

Kod C# wygenerujemy przy pomocy narzędzia pozwalającego na wizualną konfigurację tego procesu:
1) tworzymy nowy projekt LLBLGen:

2) wskazujemy źródłową bazę danych

3) wybieramy tabele do wygenerowania (LLBLGen oferuje dwa tryby generacji kodu: Adapter i Self Servicing; jedyny z którego korzystałem to Adapter, ponieważ Self Servicing jest implementacją wzorca Active Record, który to wzorzec nadaje się moim zdaniem jedynie do mikro-projektów)


4) efekt to rozpoznane kolumny, ich typy, relacje pomiędzy tabelami itd. – nic szczególnie interesującego; na tym etapie możemy zmodyfikować nazwy klas do wygenerowania (np. liczba mnoga na pojedynczą), kolumn, poukrywać niepożądane kolumny etc.:

5) na koniec wciskamy F7, podajemy katalog docelowy dla wygenerowanych projektów Visual Studio i wsio, generację mamy za sobą, możemy zacząć operować na naszej bazie danych


Zaczniemy od zniechęcania, czyli...

Wady

1) "rozdęte" klasy

Tak, to prawda. Zapomnij o POCO.

Przygotuj się na pisanie mapowań wygenerowanych klas na domenę, ponieważ to co otrzymujesz z generatora nie nadaje się na "obiekt biznesowy"... a już na pewno nie na transport w środowisku rozproszonym! Ale z drugiej strony jakiekolwiek generowanie klas na podstawie bazy danych w celu zawarcia w nich mechanizmów pozwalających na proste zarządzanie kontaktem z bazą kończy się w ten sposób, więc nie jest to żadne zaskoczenie. Przy Linq2Sql czy Entity Framework mamy to samo.

2) momentami skomplikowane zapytania

Półtorej godziny spędziłem kiedyś nad sformułowaniem za pomocą obiektów LLBLGen zapytania, które można przetłumaczyć na nasz przykład jako "pobierz mi posty z bloga o ID = 1 lub takie które nie mają tagów" (bezsens takiego zapytania w aktualnym scenariuszu pomińmy milczeniem). Teraz zajęłoby mi to chwilę, ale momentami można natrafić na banalny z pozoru problem, który zmusi nas do przewertowania dokumentacji, przeszukania forum i eksperymentowania przez bliżej nieokreśloną ilość czasu. Na szczęście nie są to częste przypadki. Dla zainteresowanych, problem ten rozwiązuje średnio opisany w dokumentacji FieldCompareSetPredicate:

3) "eksplorowalność": minus jeden

Korzystając z LLBLGen musimy przyzwyczaić się do ciągłego odwoływania się do typów wyliczalnych (enumów), klas statycznych, zgadywania "co też robi z tym obiektem przeciążany operator?" itd. Można się do tego dość szybko przyzwyczaić, jednak na początku odnosi się wrażenie, że można było całość ładniej... zaprojektować. Oto przykładowy kod pobierający bloga o zadanym ID wraz z przypisanymi do niego postami:

Na czerwono zaznaczyłem klasy i właściwości, o których istnieniu musimy wiedzieć, zanim uda się nam coś osiągnąć. Jest tego sporo i nie odkrywa się tego zbyt intuicyjne, niestety na początku bez otwartej nieustannie dokumentacji ciężko jest zrobić co_kol_wiek. Wystarczyłoby podczas generacji utworzyć jeden centralny punkt dla każdego Entity zbierający właściwości/klasy umożliwiające wykonanie wszystkich operacji, dobrze to opisać, i świat byłby lepszy.


Czas przyjrzeć się produktowi z drugiej strony:

Zalety / uwagi

1) Wzrost wydajności programisty od pierwszych chwil

To co widzieliśmy na początku artykułu – zaznaczenie checkboxów przy odpowiednich tabelach – jest wszystkim, co musi umieć programista aby rozpocząć pracę. Tak naprawdę może rozpocząć ją więc natychmiast. Dodanie LLBLGen do projektu nie wiąże się z dużym kosztem "edukacyjnym". Jest to po prostu warstwa tłumacząca zapytania do obiektów na SQL, i tyle. Nie trzeba przejmować się nauką polityki cache stosowanego w LLBLGen, ponieważ takiego cache po prostu nie ma. Nie trzeba zastanawiać się nad mapowaniem kolumn na właściwości – robi się to samo. Oczywiście przez takie podejście możemy stracić możliwość uszycia sobie warstwy DAL idealnie dopasowanej do naszej aplikacji, ale wielokrotnie nie jest to niezbędne (poza tym do LLBLGen można się oczywiście w wielu miejscach "podpiąć" własnym pluginem i dostosować jego działanie do własnych wysublimowanych potrzeb, ale tego nie robiłem). Na podaną w wadach konieczność orientowania się w wewnętrznych klasach lekiem są przykłady, przykłady i jeszcze raz przykłady. Wystarczy że jedna osoba w zespole poświęci pół dnia na dokładne zapoznanie się z tymi mechanizmami i już od dnia następnego będzie w stanie pomóc reszcie stworzyć większość zapytań.
Przykłady pojawiające się w tym poście, jak i te zawarte w dokumentacji, aż kłują w oczy możliwością utworzenia jakiegoś helpera redukującego liczbę linii kodu.

2) Pobieranie wybranych kolumn

Wielokrotnie podczas rozmów o OR Mapperach jako argument przeciwko nim słyszałem takie coś: "po co mi ściągać cały wiersz z tabeli, jeśli potrzebuję tylko jedną czy dwie kolumny? a nie będę przecież na każdy osobny taki przypadek tworzył kolejnej klasy, kolejnego mapowania". No i co racja to racja, dlatego poniżej przykład pobrania wszystkich postów, jednak pobrane obiekty zawierać będą jedynie ID i tytuł:

3) Dokumentacja, support

Płatny produkt powinien mieć godną dokumentację i wsparcie producenta. Tak jest w tym przypadku, w dołączonych plikach można znaleźć naprawdę ogrom informacji. Dodatkowo na forum również znajduje się masa rozwiązanych problemów. No i oczywiście jeżeli nie znajdziesz odpowiedzi na dręczące cię pytanie, masz pełne prawo oczekiwać, że ktoś z zespołu odpowie ci tak szybko jak to możliwe.

4) CommandLine – błyskawiczne odzwierciedlanie w kodzie zmian z bazy

Narzędzie CliGenerator.exe pozwala na automatyzację całego procesu generacji kodu. Dlatego też dobrą praktyką byłoby przechowywanie w repozytorium samego pliku projektu LLBLGen, a generacja kodu następowałaby na maszynie programisty bądź na build serverze.

5) Wsparcie dla LINQ

W najnowszej wersji softu wprowadzono możliwość pisania zapytań LINQ i przekazywania ich do infrastruktury LLBLGen. W dokumentacji wygląda to przyjemnie, ale nie korzystałem z tego udogodnienia. Wcześniej alternatywą (wcale nie taką złą) dla LINQ było przekazywanie obiektów klasy RelationPredicateBucket z zawartymi kryteriami wyszukiwania.

6) Wsparcie dla wieeeelu baz danych

Nie powinno to specjalnie dziwić, ale LLBLGen oferuje wsparcie dla wielu silników baz danych. Niechaj poniższy screen pokaże co i jak:

Czy warto?

Celem tego posta nie była reklama czy dokładna prezentacja LLBLGen – tak naprawdę liznęliśmy tylko wierzchołek góry lodowej (ależ dwuznaczne!!). Chciałem tylko pokazać, że poza światem open source istnieją takie PRODUKTY, i wcale nie muszą one pochodzić z firmy Microsoft.

A odpowiedź na pytanie "czy warto?" jest bardzo prosta:
Jeżeli możesz korzystać z rozwiązań darmowych (NHibernate, Active Record z Castle Project, SubSonic...) – go for it, Luke!
Jeżeli nie możesz korzystać z rozwiązań darmowych bądź zależy ci na zrzuceniu części odpowiedzialności za powodzenie twojego projektu na kogoś innego, oczekując supportu z prawdziwego zdarzenia i "pochylania się" nad każdym twoim problemem – LLBLGen Pro jest rozwiązaniem na dzień dzisiejszy po prostu najlepszym. A jeśli twoja firma zapiera się, że jest kryzys i nie stać jej na nowe inwestycje, postaraj się przemówić im do rozsądku. Przerzucenie się na coś takiego jest naprawdę rozwiązaniem win-win, gdzie oni są szczęśliwi (zarabiają na licencjach) a korzysta również twoja firma (pieniądze wydane na licencje z pewnością zwrócą się bardzo szybko, bo tak errorogenne:) i nieprzyjemne pisanie kodu dotykającego bazy danych zostaje z prac nad projektami całkowicie usunięte). Ściągnij trial i zobacz sam. Ściągnij specjalnie przygotowane materiały i pokaż managerowi. Po prostu: zrób wszystko, aby nie tracić życia na ręczne pisanie banalnego, powtarzalnego SQLa!

Powodzenia.

opublikowano 08 czerwca 09 06:45 przez Procent | 16 komentarzy   
Zarejestrowano w kategorii: , ,
Instalacja(SQL Server 2008 + Visual Studio 2008) = Irytacja

Wymyśliłem sobie, że rozpoczynając właśnie nowy projekt wykorzystam Sql Server Compact Edition, przynajmniej na samym początku. Ściągnąłem, zainstalowałem (okazało się w trakcie że już to miałem – zainstalowało się kiedyś razem z VS, ale to nieważne), dodałem lokalną bazę do projektu za pomocą Visual Studio, kliknąłem dwa razy – pięknie, śmiga.
Kolejny pomysł – a czemu by nie pobawić się tą bazą ze znienawidzonego Management Studio (którego notabene już nie nienawidzę; dzięki wirtualnemu środowisku i odseparowaniu wszystkich projektów od siebie da się z nim jednak żyć)? No to odpalam, wybieram "Compact Edition", dogrzebuję się do pliku i... ZONCZYSKO! Komunikat, że "chcę otworzyć zbyt starą wersję pliku" okazał się debilny, ponieważ to SSMS (2005) było za stare na Compact 3.5.
ALE, skoro już sobie postanowiłem że za pomocą SSMS się do tej bazy dobiorę, to nie wypada w połowie drogi rezygnować. Raz/dwa do napędu płytka z SQL Server 2008 i jedziemy. Next –> next –> next, po drodze jakiś reset, weryfikacje, cuda na kiju... prawie godzina zmarnowana. Ale trudno, próbujemy dalej.
W końcu instalator pozwolił mi na wybranie jakichś opcji, z których interesowało mnie jedynie nowe Management Studio. OK –> Next –> cośtamcośtam, kolejna weryfikacja i... FIGA! Oto owej weryfikacji wynik:

Ale WTF? Przecież mam VS 2008, mam Service Packa (z którym zresztą wcześniej zainstalował mi się Compact)... ale na wszelki wypadek uruchamiam instalację SP1 jeszcze raz. Może coś przeoczyłem?…
Po kolejnych minutach ZMARNOWANYCH na czekanie aż instalator ServicePacka powie mi, że produkt jest już zaktualizowany i ponownym uruchomieniu instalatora SqlServer 2008 z podobnym rezultatem rency mi opadli, a żuchwa zbielała.
Ale co robić, po takiej ilości czasu bezecnie wywalonego na śmietnik informatycznej historii nie wypada się po prostu poddać. Cóż się okazało...?
Dla siebie i dla potomności: instalator Sql Server 2008 sprawdza, czy WSZYSTKIE wersje Visual Studio 2008 mają zaaplikowany SP1. WSZYSTKIE, włączając w to Visual C# Express Edition, który mi się zaplątał na wirtualce, a którego nie używam, więc i nie aktualizuję. Ehh...
I teraz się zastanawiam – to moja wina i głupota, czy jednak twórcy instalatora mogli się pokusić o więcej mówiący komunikat? A może któryś z nich siedzi za oknem na swojej miotle i obserwuje, i czeka na pierwszy siwy włos na mojej skroni?
P.S. "Poprawna" instalacja trwa już od dobrych 40 minut... na razie jest ok. 80%... mam nadzieję, że przy 99% nie wyskoczy okno "sorry, your minesweeper high score is too low".

opublikowano 03 czerwca 09 06:29 przez Procent | 5 komentarzy   
Zarejestrowano w kategorii: , ,
Reklamowo-porządkowe sko_dev_jarzenie

Reklamy środków czystości są niepowtarzalnie wręcz obleśne. Czy nikt tym wstrząśniętym stanem swojego kibla czy zlewu ”gospodyniom” nie uświadomił, że zbierać brud i syf powinno się częściej niż raz na rok? I piękny blask powstały po przejechaniu czystą szmatą po megabrudnej powierzchni niekoniecznie musi być wynikiem wylania na tąże szmatę litra reklamowanego właśnie detergentu.

To tak jakby z C# usunąć interfejs IDisposable oraz konstrukcję using (coby o zbieraniu brudów nie było tak łatwo pamiętać). A “rekwizyty reklamowe” powinny dziedziczyć z klasy:

  1:  public abstract class KitchenItem
  2:  {
  3:  	private readonly Timer _timer;
  4:  
  5:  	protected KitchenItem()
  6:  	{
  7:  		GC.KeepAlive(this); // no unwanted cleaning!
  8:  
  9:  		_timer = new Timer { AutoReset = true };
 10:  		_timer.Interval = TimeSpan.FromDays(365).TotalMilliseconds; // wait till I am rrrrrealy dirty
 11:  		_timer.Elapsed += (s, e) => YearlyCleaning();
 12:  		_timer.Start();
 13:  	}
 14:  
 15:  	protected abstract void YearlyCleaning();
 16:  
 17:  	public void Dispose()
 18:  	{
 19:  		throw new UnintendedCleaningException("Wait until I am really dirty, you ***!");
 20:  	}
 21:  }
opublikowano 02 czerwca 09 06:33 przez Procent | 3 komentarzy   
Zarejestrowano w kategorii:
Visual Studio 2010: GenerateFromUsage

Poprzednie edycje Visual Studio potrafiły uprzykrzyć życie, jeżeli ktoś próbował stosować Test Driven Development, czyli: najpierw napisz kod korzystający z klasy, a dopiero potem samą klasę; najpierw zaimplementuj wywołanie metody, a dopiero potem samą metodę. Bez dodatków takich jak Resharper podobne scenariusze były niczym innym jak wielkim pain in the... neck.
Teraz to się zmieni i nawet użytkownicy gołego VS będą mogli cieszyć się generacją kodu na podstawie kontekstu jego wykorzystania. Oto typowy przykład:

1) Definiujemy stworzenie nowej instancji nieistniejącej klasy (wraz z parametrem konstruktora) oraz wywołanie jej metody

2) Generujemy klasę

3) Generujemy konstruktor

4) Generujemy metodę

5) Dopieszczamy wygenerowany kod

Uwagi... Feature taki jest z pewnością niesamowicie przydatny, jednak przydałaby się większa kontrola nad generowanym kodem. Co jeśli chcę klasę publiczną – czy muszę ręcznie dodawać modyfiaktor widoczności (zmiana template w folderze program files/visual studio/costamcostam/templates/class.zip nic nie dala)? Albo metodę nie-internal? Nie znalazłem nigdzie ustawień pozwalających zmienić domyślne zachowanie, co nie oznacza jednak że nie zostaną takie dodane (ani też że już nie są gdzieś ukryte).

opublikowano 30 maja 09 01:45 przez Procent | 6 komentarzy   
Zarejestrowano w kategorii:
Relacja z CodeCamp Warszawa 2009

W sobotę, 23 maja, w siedzibie Microsoft Polska odbyło się techniczne spotkanie CodeCamp Warszawa 2009. Wstęp, pizza i wiedza za darmo. Oto me wrażenia jako biernego uczestnika i obserwatora:

Tomasz Kopacz "Programowanie równoległe i rozproszone"

Rozpoczęcie dnia wystąpieniem Tomasza Kopacza wróżyć może tylko dobrze. Mający apetyt na zwykłe dla tego prelegenta wycieczki w najgłębsze otchłanie szerokich wód technologii nie mogli być zawiedzeni. Tym razem mieliśmy okazję posłuchać o programistycznym zmuszaniu komputera do wykonywania wielu czynności jednocześnie – i dlaczego jest to takie trudne. "Why bother?"... Na samym początku ujrzeliśmy slajd z wykresem obrazującym procentowy wzrost obecności procesorów wielordzeniowych w zwykłych PCtach. W ciągu ostatnich 4 lat wartość ta wzrosła z 30% do prawie 100%! Od równoległości w programowaniu nie ma po prostu ucieczki. Ten jeden czynnik – ignorowanie mocy obliczeniowych więcej niż jednego rdzenia - może być powodem porażki naszej aplikacji na rynku.
Po krótkim wstępie obrazującym nam stan aktualny posłuchaliśmy trochę o teorii programowania równoległego. Poznaliśmy największe wyzwania czekające na programistów, przyczyny powstania i cele wielu rdzeni oraz jak je można wykorzystać już teraz. Kilka demonstracji kodu pisanego w dniu dzisiejszym w celu osiągnięcia "równoległej nirwany" mogło wydać się wszystkim aż nazbyt dobrze znane z własnych doświadczeń. Nawet najprostsze operacje takie jak asynchroniczne pobranie danych dla strony ASP.NET czy rozdzielenie banalnego algorytmu pomiędzy kilka wątków tak bardzo redukują czytelność kodu i pierwotny zamiar programisty, że ciężko jest się w tym wszystkim połapać. Jeśli dodamy do tego spory narzut wydajnościowy związany z używaniem mechanizmów takich jak Semafor, Mutex, EventWaitHandle czy lock okaże się, że smutne z nas, programistów, misie i że zdecydowanie jest to obszar dający pole do popisu twórcom nowych rozwiązań i koncepcji.
A jeśli takie mechanizmy wrzucić bezpośrednio do klas .NET? Zarządzać wątkami, zasobami, mocą komputera bez ciągłego kontaktu z systemem operacyjnym? Uzyskalibyśmy dwie rzeczy: po pierwsze lepszą wydajność, po drugie szansę na zaimplementowanie tego w prosty do wykorzystania sposób. I tak to właśnie wkrótce będzie wyglądać. W Visual Studio 2010 pojawi się wiele udogodnień dla pracy z wielowątkowym kodem i jego debuggowaniem. Sam .NET Framework z kolei udostępni nową przestrzeń nazw (System.Threading.Tasks) zawierającą całkiem nowe podejście do pisania takich projektów. Zamiast Thread będziemy używać Task, zadania zrównoleglimy wywołaniem jednej metody AsParallel() z PLINQ, opóźnioną inicjalizację zmiennych zapewni nam klasa Lazy<T>, a dostępu do zmiennej oczekującej na wykonanie operacji w tle ustrzeże wywołanie Task<int>.Factory.StartNew(). Cóż... będzie fajnie:).
Po dość szczegółowym i popartym demonstracjami omówieniu powyższych koncepcji skończyła się ciekawa część sesji. Z programowania równoległego na jednej maszynie przeszliśmy do tematów rozpraszania systemów na wiele maszyn oraz do tak ostatnio popularnej chmury. Niestety te ostatnie kilkanaście minut uważam za zbyt rozbite pomiędzy wiele różnych tematów. Zamiast po kilka minut poświęcić na CCR (Concurrency and Coordination Runtime), DSS (Decentralized Software Services), HPC Server i Windows Azure (które to tematy same w sobie są z pewnością bardzo zajmujące), można było jeszcze trochę poopowiadać o tym co nas, programistów ze zwykłej gliny, kręciło najbardziej, czyli nowy .NET.

Moja ocena: 7/9 (za fachowe i napawające optymizmem przedstawienie kierunku rozwoju .NET; nie więcej jednak, bo zbyt dużo materiału "na doczepkę")

Piotr Czekała i Krzysztof Bartkowski "Media w Silverlight - dostarczanie niezapomnianych wrażeń"

Po krótkiej przerwie na scenę wkroczyło dwóch prelegentów z firmy Insys. Z Silverlightem nie miałem póki co zbyt wiele do czynienia i z zainteresowaniem słuchałem tego, co mieli nam do przekazania. A mieli do przekazania sporo – i to na bardzo satysfakcjonującym poziomie szczegółowości. Sesję podzielono na trzy części.
Pierwsza z nich to wstęp. Przedstawienie siebie, firmy oraz tego czym się zajmują na co dzień. Historyjki o LechTV, zmaganiach z kolejnymi wersjami SL i próbami przekonania klienta i użytkowników że "naprawdę warto doinstalować ten plugin" były dość interesujące i momentami zabawne, ale jak na mój gust – za długo "reklamowano" firmę Insys. Choć z drugiej strony – nie było to bardzo irytujące i w sumie odrobina autopromocji nikomu zbytnio przeszkadzać nie powinna:).
Główną część sesji stanowiły opowieści o prezentowaniu audio i wideo za pomocą Silverlight. Dowiedzieliśmy się co to jest Progressive Download – i dlaczego w miarę możliwości należy stosować bardziej zaawansowane rozwiązania. Przeszliśmy do Streamingu i posłuchaliśmy o jego wyższości nad progresywnym ściąganiem. Oba tematy okraszono demonstracjami na żywo, więc mogliśmy momentalnie przekonać się na własne oczy co autor ma na myśli. Demonstracje przygotowano starannie, więc nic się nie wysypało i uniknięto tak często spotykanego efektu "dziwne, przed kwadransem działało...". Następnie dużo czasu poświęcono na zaprezentowanie Smooth Streaming, możliwościami bijącego na głowę dwie wcześniej przedstawione technologie. Odtwarzanie wideo bez ciągłego oczekiwania na buforowanie, skakanie po całym filmie bez zacięcia, nieprzerwane odtwarzanie i adaptowanie jakości wideo do aktualnego stanu łącza == absolutny komfort użytkownika. Zobaczyliśmy również jak za pomocą Expression Encoder przygotować media gotowe do wykorzystania przez Silverlight. Ogólnie ta część niosła za sobą spore walory edukacyjne i pomimo kilku nużących elementów i momentami usypiającego głosu prelegenta – podobało mi się.
Następnie nadszedł czas na feature, który u po wyjściu SL2 u wielu osób mógł powodować opad szczęki i był tzw. WOW-factorem tej technologii. Chodzi oczywiście o DeepZoom. Jako wiodący motyw służący za demo dla omawianych funkcjonalności potraktowano witrynę Sunrise Festival, gdzie można bawić się w przybliżanie mozaiki złożonej z ponad 1000 zdjęć. Dodatkowo zaimplementowano filtrowanie prezentowanych obrazów wzbogacone o animacje każdego foto z osobna. Całość robiła wrażenie, tym bardziej że wydajność rozwiązania autentycznie nie pozostawia nic do życzenia. Przy okazji prelegent podzielił się wiedzą zdobytą podczas implementacji tego projektu – widać, że technologia nie ma przed nim tajemnic. Omówiono dokładnie strukturę plików, jakiej wymaga DeepZoom i zaprezentowano narzędzie Deep Zoom Composer służące do jej generowania. Jednocześnie wskazano wady i niedociągnięcia tej aplikacji, jak również powiedziano kilka słów o autorskim programie zastępującym DZC z ominięciem jego wpadek. Imponować mogła również trójwymiarowa panorama pola golfowego stworzona przy użyciu Photosynth oraz demonstracje oprogramowania kontroli nad wyświetlanym obrazem za pomocą udostępnianego przez SL API.
Z sesji wychodziło się z wrażeniem, że Silverlight nie ma przed prelegentami tajemnic i ze spokojem można zaufać przekazanym przez nich informacjom. Wystąpienie z kategorii "przez pasjonatów dla pasjonatów".

Moja ocena: 7/9 (za dogłębne przedstawienie tematu)

Bartłomiej Legiędź "Wyjątki kontrolowane w C#"

O idei checked exceptions, ich wadach, zaletach i możliwych implementacjach opowiedział nam kolega z Zine’a, będący jednocześnie zwycięzcą łódzkiego Speaker Idola. Wystąpienie sprawiało wrażenie bardzo przemyślanego, doskonale zorganizowanego i poprowadzonego z wprawą godną starego scenicznego wyjadacza. Temat był dla mnie dość ciekawy, ponieważ swego czasu sam zastanawiałem się nad omawianą kwestią. Przemyślenia te zakończyłem usypaniem kopczyka wdzięczności w mej programistycznej duszy na cześć Andersa Hejlsberga, twórcy C#, za wspaniałą decyzję nieimplementowania tego mechanizmu w moim ulubionym języku.
Z zainteresowaniem wysłuchałem historii wyjątków kontrolowanych: od CLU, przez C++ aż do Javy. Zaprezentowane przykłady implementacji zostały profesjonalnie omówione, a ich wady bezlitośnie wytknięte. Zgadzam się z prelegentem, że implementacja z Javy byłaby całkowicie do zaakceptowania, gdyby istniała możliwość zrezygnowania z sygnalizowania BŁĘDU podczas KOMPILACJI programu w razie niestosowania się do tych zaleceń. W obecnej postaci kończyć się to musi brzydkimi obejściami obowiązku deklarowania rzucanych wyjątków poprzez nagminne ciche łapanie klasy bazowej bądź deklarowanie "throws Exception". Takie zycie...
Bartek doszedł do wniosku, że taki mechanizm jest jednak przydatny i postanowił zrobić coś z aktualnym stanem rzeczy. Efektem tego postanowienia jest plugin do Resharpera o nazwie Exceptional. Jego zadanie jest dość proste - wynajduje on w naszym kodzie niełapane wyjątki i proponuje dwa rozwiązania: złap wyjątek bądź udokumentuj możliwość jego wystąpienia. W ten sposób otrzymujemy nienachalną informację o potencjalnym przeoczeniu czegoś ważnego oraz możliwość automatycznego tego naprawienia kilkoma kliknięciami wywołującymi odpowiednią akcję z listy sugestii R#. Dla mnie bomba, a następujące po części teoretycznej demo skłoniło mnie do ściągnięcia i instalacji tego narzędzia. Wymaga ono jeszcze oczywiście dopracowania, ale nawet w obecnej postaci jest naprawdę godne polecenia.
Lubię słuchać kogoś wysławiającego moje własne przekonania w uporządkowany sposób, więc słuchało mi się bardzo przyjemnie:). Skupiono się na jednym, bardzo ściśle określonym i w miarę istotnym problemie, następnie dokładnie go przeanalizowano, zbadano istniejące rozwiązania, wytknięto ich wady, zaproponowano własną propozycję a na koniec ją zrealizowano. Brawo! Dla mnie najlepsza sesja na całej imprezie.

Moja ocena: 8/9 (za bardzo przemyślaną agendę, świetną treść, doskonałą propozycję rozwiązania problemu i w końcu – jej realizację)

Michał Żyliński "Ile cukru w cukrze - IronPython i jego zastosowania"

O wprowadzeniu języków dynamicznych do .NET Framework słyszy się od dawna, a sztandarowymi przykładami w tym temacie są IronRuby i IronPython. Z czym to się jednak je, jak się w tym pisze i do czego można to wykorzystać? Na te pytania miał nam odpowiedzieć pracownik polskiego oddziału Microsoftu, Michał Żyliński.
Przyznać muszę, że mój kontakt z językami dynamicznymi był do tej pory raczej symboliczny. Ot, parę przeczytanych artykułów, obejrzanych prezentacji, kilka godzin luźnych eksperymentów. Minimalny poziom wiedzy wystarczył jednak do bezproblemowego zrozumienia wstępu, podczas którego posłuchaliśmy trochę o historii i strukturze Pythona oraz zobaczyliśmy przykładowy kod. Co ciekawe, prelegent w celu podkreślenia faktu, że mówi o Pythonie, a nie jego konkretnej implementacji dla .NET, korzystał ze środowiska PythonWin a nie VS.
Jako możliwe zastosowania Pythona zaproponowano nam ORMapping, Aspect-Oriented Programming (chociaż nie wiem jaką rolę miałby tam spełniać) czy prosty serwer www. Ciekawie wyglądało demko otwierające Worda i wypisujące jakiś tekst do nowoutworzonego dokumentu – zajmowało jedynie 5 linii! To właśnie zwięzłość i skondensowanie instrukcji przy jednoczesnym zachowaniu czytelności kodu jest jedną z największych zalet Pythona.
Po przejściu do właściwej części prezentacji, czyli włączenia Pythona do świata .NET, zaprezentowano nam różnice pomiędzy jego standardowym środowiskiem a implementacją rodem z Microsoft. Mostem łączącym świat statyczny z dynamicznym jest DLR (Dynamic Language Runtime), o którym usłyszeliśmy kilka słów i poznaliśmy zasady jego działania z bardzo wysokiego lotu ptaka.
Później nastąpiła próba odpowiedzi na najważniejsze chyba pytanie: po co nam Python w .NET? Przy tej okazji obejrzeliśmy kilka dem kończących wystąpienie. Były to między innymi kombinacje wykorzystania IronPython w środowisku WinForms, w ASP.NET, w Silverlight... Niestety, im dłużej na to patrzyłem, tym mniej byłem do całej idei zaprzęgania dynamicznych języków do takich celów przekonany. W takich scenariuszach kodu wcale nie będzie strasznie mniej, a włączanie dodatkowego języka programowania do projektu tylko dlatego że jest "fancy" i wszyscy o tym mówią wydaje mi się nie do końca odpowiedzialną decyzją. Tak naprawdę jedyne sensowne (w kontekście aplikacji .NET) zastosowanie, jakie wyniosłem z sesji, to udostępnienie użytkownikom aplikacji możliwości pisania skryptów modyfikujących jej zachowanie – i jeśli kiedykolwiek pojawi się u mnie taka potrzeba, wówczas z pewnością zwrócę swe oczęta w odpowiednią stronę (ostatnio pisał też o tym Bartek Szafko).

Moja ocena: 6/9 (tak naprawdę nie jestem wiele mądrzejszy po sesji niż przed nią – i nadal nie do końca wiem, gdzie w codziennym programowaniu w .NET jest miejsce na IronPythona)

Andrzej Piotrowski "Designer + Programista = Produkt, Problem + Pomysł = Aplikacja"

Na koniec wystąpił przed nami zwycięzca (a właściwie jedyny uczestnik) warszawskiego Speaker Idola. Temat mówiący niewiele i... do dziś nie wiem o co tak naprawdę chodziło. Od początku widać było, że prelegenta zżera trema – ale to jest całkowicie zrozumiałe i nikt nie może mieć o to pretensji. Próby nawiązywania kontaktu z publicznością poprzez organizowanie minikonkursów z nagrodami – jak najbardziej godne pochwały. I na tym niestety owe pochwały muszę zakończyć.
Nie potrafię nawet teraz poukładać sobie w głowie z czym po kolei mieliśmy do czynienia. Najpierw zobaczyliśmy na slajdzie definicje "strategii 4P oraz 4C". Chwilę potem nastąpiła wzmianka o Strategii Błękitnego Oceanu. W międzyczasie w połowie omawiania slajdu przechodziliśmy bez słowa wyjaśnienia do kolejnego tematu, co powodowało u mnie w głowie niemały zamęt. O co chodzi?? Podczas obserwacji prelegenta przypominały mi się momentami czasy liceum, gdy na lekcji polskiego trzeba było recytować jakiś durny wiersz i chcąc zrobić to najszybciej jak to możliwe – plątałem się i myliłem. Musiałem wtedy wyglądać właśnie tak. Rozumiem, że można nie urodzić się z naturalnym talentem do prezentowania czegokolwiek, ale w takim razie po co się zgłaszać na taką imprezę bez uprzedniego zdobycia jakiegokolwiek doświadczenia, chociażby na lokalnej grupie .NET? A jeśli takie doświadczenie jest to... może po prostu trzeba lepiej się przygotować?
Po kilku pierwszych slajdach zostałem absolutnie zaskoczony tym co zdarzyło się dalej. Otóż zaprezentowano nam założenia projektu z konkursu Imagine Cup, z roku 2007, w którym prezenter brał udział. A po prezentacji założeń... kilkuminutowy filmik pokazujący jego działanie? Dwa razy?? WTF?
Ale to nie koniec, bo... za chwilę zostaliśmy uraczeni dokładnie tym samym, tylko że z IC 2008. Potem puszczono nam jakąś "wizjonerską reklamę". Potem kolejny filmik, nie pamiętam juz o czym. A następnie... a jakże, filmik o projekcie z IC 2009!!
Na koniec kilka słów o tym, że "wizja jest ważniejsza od możliwości jej realizacji" (tekst może dobry na Imagine Cup, ale nie tutaj), że trzeba zmieniać świat i że bez dobrego designu nie mamy szans. Po drodze poplątano design w sensie "interfejs użytkownika" z designem w sensie "architektura rozwiązania". I... to tyle.
Może opis ten wygląda złośliwie, jednak nie takie jest moje zamierzenie. Przez cały czas bowiem zastanawiałem się "o co chodzi?", i nadal nie mam pojęcia. Proponuję po prostu przed następnym wystąpieniem pokazać je uprzednio komuś dobrej woli i skonfrontować jego odczucia z zamierzonym przekazem. Przed prezentacją byłem bardzo ciekaw co ujrzę, bo czytając od czasu do czasu bloga autora można odnieść wrażenie, że jest megamastawymiataczem (szczególnie utkwiła mi w pamięci bardzo protekcjonalna i nie na miejscu chęć "wypunktowania" Artura Paluszyńskiego w relacji z C2C). I cóż... było trochę inaczej.
I na koniec jeszcze jedna uwaga do samych slajdów: pakowanie 10 kolorów na jednym ekranie oraz trzykrotna zmiana motywu prezentacji nie wypada korzystnie.

Moja ocena: <brak> (bo naprawdę nie wiem co miałbym wystawić – mimo chęci i starań prelegenta był to po prostu niezrozumiały chaotyczny bełkot; albo jestem głupi i tylko ja tak to odebrałem)

Podsumowanie

Jak na takie "niszowe" weekendowe spotkanie, bez "KONFERENCYJNEGO" nadęcia i pompy – zdecydowanie udane wykonanie. Podziękowania tym, którym się chce.

Ocena ogólna konferencji: 8/9

opublikowano 27 maja 09 07:02 przez Procent | 8 komentarzy   
Zarejestrowano w kategorii: , ,
Jedna z największych wad Virtual PC wyeliminowana

Niedawno moje życie stało się lepsze. Nie jestem może w raju, ale przybliżyłem się o jeden kroczek. A wszystko za sprawą małego hotfixa. Ale od początku:
Kilka miesięcy temu pisałem o megairytującej cesze Virtual PC, która uniemożliwiała pracę w rozdzielczościach wyższych niż 1600x1200. Co prawda w poście podałem pewien łorkaraund, lecz w moim przypadku nie do końca się on sprawdzał. VS w mojej konfiguracji współpracował z połączeniem przez Remote Desktop mniej niż idealnie (pojawiały się pewne problemy z kolorystyką w edytorze), zatem pozostało mi rozciąganie wirtualki w okienku do 1600x1200 – a na monitorze zostawało miejsce akurat na Winampa:). Pewnego ranka coś mnie tknęło i dałem nura w internet w poszukiwaniu informacji o następcy VPC 2007 – czy także będzie miał ta wadę? Dzięki chęci zaspokojenia swojej niepohamowanej ciekawości znalazłem coś, co spowodowało prawdziwego banana na mojej twarzy. Mianowicie w lutym roku bieżącego wypuszczono hotfixa do VPC, który pozwala na pracę w wyższych rozdzielczościach! Nareszcie full screen na 24" pojawił się w zasięgu mej chciwej ręki, jea, i to bez uciekania się do płatnego VMWare. Instalka do ściągnięcia oczywiście ze stron Microsoftu: http://support.microsoft.com/?id=958162.

Kilka uwag:
1) działa jak złoto:)
2) maszyny wirtualne z zachowanym stanem wymagają restartu – czyli zachowany stan zostaje utracony; radzę dlatego zastanowić się przed instalacją czy któraś z wirtualek nie znajduje się w stanie bardzo nam bliskim
3) pomimo komunikatu:

"Restart Requirement
You do not have to restart the computer after you apply this hotfix.
"

pierwszym okienkiem, które pojawiło się po zaaplikowaniu hotfixa, był monit o restart komputera:). Świnie.

Użytkownikom VPC gorąco polecam. Jeszcze niechaj tylko w kolejnej wersji pojawi się możliwość korzystania przez wirtualkę z wielu rdzeni (pomarzyć można...) i produkt będzie w stanie zmierzyć się z płatną konkurencją.

opublikowano 26 maja 09 07:18 przez Procent | 1 komentarzy   
Zarejestrowano w kategorii: , ,
Visual Studio 2010: Zoom

Bardzo przydatną konsekwencją przeprojektowania wyglądu Visuala 2010 z wykorzystaniem WPF jest ZOOOOM. Nie trzeba będzie już zwiększać czcionki na potrzeby prezentacji czy przyzwyczajać do niewygodnej konfiguracji ekranu.
Przed:

Po (ctrl + wheel):

Jedyne co mi trochę przeszkadza to brak listy z możliwością wyboru powiększenia (np od 10 do 1000%) z domyślnie wybranym 100%. Aktualnie jedynym znalezionym przeze mnie sposobem na powrócenie do standardowego powiększenia (oprócz ręcznego manipulowania kółkiem myszki) jest zamknięcie i otwarcie zakładki.
I jak już przy zakładkach jesteśmy: powiększenie działa per zakładka, a nie globalnie. I tak powinno być.

I tyle, o tej akurat nowości ciężej cokolwiek więcej napisać:).

opublikowano 24 maja 09 04:14 przez Procent | 4 komentarzy   
Zarejestrowano w kategorii:
Visual Studio 2010: NavigateTo

20 maja pojawiła się publiczna wersja Beta1 naszego ulubionego IDE. Zainstalowałem i klikam, szperam, poznaję. Wrażeniami i ciekawostkami będę się raz po raz dzielił.

Pierwszy feature, o którym słyszałem już dość dawno, jednak byłem niezmiernie ciekaw jak zostanie to zaimplementowane, to tzw. "Navigate To". Ma na celu wyeliminować nawigację w kodzie za pomocą Solution Explorera – która to cecha w głównej mierze spowodowała moje rozkochanie w Resharperze (dokładnie chodzi o punkt 2) w tym artykule).
Zobaczmy zatem co stanie się po wciśnięciu magicznego skrótu ctrl + , (control i przecinek)...

(na obrazku solution, z którego będę dziś korzystał)
Można zauważyć, że VS wyszukuje nie tylko elementy zaczynające się od wpisanej frazy (AnotherClass), ale także zawierającą ją w środku (AndYetAnother). Spostrzeżenie kolejne: wyszukiwane są nie tylko klasy, ale również metody (w tym przypadku konstruktor) oraz zwykłe pliki wchodzące w skład rozwiązania!
Dalej.

Niezmiernie ucieszyłem się, gdy po wpisaniu NTM zobaczyłem to co powyżej. Oznacza to, że podobnie jak w R#, możemy wyszukiwać za pomocą samych wielkich liter – wówczas podczas dopasowywania wzorca małe litery w nazwach elementów są pomijane. Bardzo, bardzo fajnie!
Dalej.

Podczas korzystania z R# kilkukrotnie zabrakło mi możliwości zapamiętania wykorzystanego schematu bądź odwołania się do wcześniej wpisanych szlaczków. Jak widać powyżej – w VS będziemy mieli listę z ostatnimi frazami.
Dalej.

Wpisywane filtry możemy zagnieżdżać – jak widać na rysunku, najpierw zostały dopasowane elementy spełniające kryterium "pr", a następnie z nich wybrano te zawierające "al". Miło.

To tyle ciekawostek dotyczących NavigateTo, które udało mi się wychwycić podczas dłuższych oględzin. Czy ktoś zauważył w tym okienku coś więcej?
Wrażenie: bardzo się cieszę, że do VS włączono taką funkcjonalność. Teraz nawet programiści mówiący NIE zewnętrznym ulepszaczom nie będą zmuszenia do marnowania cennego czasu wślepiając się w Solution Explorer. Obawa: zbieranie wszystkiego w jednym oknie może okazać się mało praktyczne, miło byłoby mieć opcję wyszukiwania różnych typów elementów za pomocą różnych skrótów klawiszowych.

Do następnego razu – z pewnością podobnych odcinków będzie dużo więcej.

opublikowano 21 maja 09 08:23 przez Procent | 3 komentarzy   
Zarejestrowano w kategorii:
Relacja z polskich finałów Imagine Cup 2009: Projektowanie Oprogramowania

A było to tak...

Tak jak pisałem kilka dni temu, w ubiegłą środę odbył się polski finał konkursu Imagine Cup 2009 w kategorii Projektowanie Oprogramowania. Tegoroczny temat przewodni: “Wyobraź sobie świat, w którym technologia pomaga rozwiązać najtrudniejsze problemy ludzkości”. Darząc tą inicjatywę ogromną sympatią spodziewałem się powrotu wspomnień sprzed kilku lat, widowiskowych prezentacji, studencko-pasjonackiego klimatu i generalnie dobrej zabawy. Od razu napiszę, że moje wysokie oczekiwania zostały w pełni zaspokojone.
Już na samym początku zostałem zaskoczony atmosferą i wystrojem Instytutu Wzornictwa Przemysłowego, gdzie odbywała się oficjalna część wydarzenia. Obawiałem się, że wraz z “wyprowadzką” z budynku Microsoftu konkurs utraci część swojego uroku. Na szczęście okazało się, że organizatorzy zadbali o odpowiednie przygotowanie sali i dało się czuć tą specyficzną, niepowtarzalną atmosferę przez cały czas.
Zdziwiła mnie także liczba obecnych osób. Sala wypełniona była po brzegi, co niestety dało się odczuć podczas nieszczęsnej przerwy na kawę, kiedy to tłum rzucił się na jeden mały stolik i żeby się do niego dopchać, trzeba było prawie całą przerwę spędzić w kolejce. Rok temu podobno było tak samo, może za rok ktoś zmieni ów stan rzeczy?
Po krótkim powitaniu, przedstawieniu agendy i zaprezentowaniu nazw pięciu najlepszych drużyn zaczęło się. Na scenę po kolei wychodzili śmiałkowie, aby zebranej widowni przedstawić efekt swojej wielomiesięcznej pracy i walczyć o reprezentację Polski w Egipcie.

Prezentacje

Na sali było dość ciemno, więc niestety nie bardzo miałem możliwość notować swoje spostrzeżenia. Poniżej moje wrażenia z przedstawionych prezentacji tak, jak je wyryłem w pamięci. Zabawiłem się w jurora i powystawiałem oceny… co prawda moim zdaniem każdemu zespołowi należy się 9 za sam fakt wzięcia udziału w konkursie i dotarcia do finału, ale ten aspekt pominąłem. Żałuję też, że pierwszy dzień IC wraz z sesją plakatową nie jest w jakiś sposób otwarty dla publiczności – swoje zdanie trzeba było wyrobić jedynie podczas 20 minut prezentacji i kwadransa odpowiedzi na pytania jury. Ale mam nadzieję że mi się udało, więc po kolei.

1) FteamS (Politechnika Łódzka)

Chłopaki z Łodzi jako jeden z głównych problemów ludzkości obrali niedostępność edukacji dla dużej części mieszkańców naszej planety – głównie chodziło o wybiedzone afrykańskie dzieciaczki.  Ich system miał zmienić ten stan rzeczy poprzez wykorzystanie telefonów komórkowych do rozprowadzania edukacyjnych treści. Stworzony przez nich format MMSa w zupełności wystarczał do przesyłania mądrych tekstów, quizów, obrazów itd. Na początku zdziwiłem się “komórki, w Afryce?”, szybko okazało się jednak, że ten pomysł nie został wzięty z nieba. Jak się dowiedzieliśmy, ponad 70% mieszkańców Afryki korzysta z telefonów komórkowych, a dzięki aplikacji napisanej w Javie do nauki nie jest wymagany super sprzęt.
Największe jednak wrażenie robiła inna część systemu – interaktywna tablica. Założenie jest takie: nauczyciel traktuje ścianę jako kawałek tablicy, jednak zamiast mazaków wykorzystuje kontroler konsoli Wii oraz długopis z diodą wysyłającą sygnały w podczerwieni. Dzięki temu komputer może dokładnie sczytać ruchy ręki nauczyciela, odwzorować je jako zbiór krzywych, i przesłać przez sieć do innej aplikacji. Na tym końcu dane są ponownie formatowane w obraz i wyświetlane za pomocą rzutnika na ścianę w domu ucznia. Oczywiście komunikacja może przebiegać w obie strony. Dema zaprezentowane w postaci filmików puszczonych podczas prezentacji potrafiły zaimponować. Sam pomysł nie jest może nowy (zresztą Bartek Pampuch, jeden z jurorów w konkursie, już od kilkunastu miesięcy wykorzystuje ten myk w swoich prezentacjach), ale za porządne wykonanie na potrzeby Imagine Cup należy się szacunek.

Po chwili zastanowienia pojawiło się u mnie jednak trochę wątpliwości. O ile sama tablica może z pewnością służyć do wielu zastosowań, o tyle całe “core” rozwiązania, czyli przesyłanie informacji edukacyjnych różnymi drogami (MMS, www, zwykła aplikacja desktopowa) wydaje się… trochę na wyrost. Jeżeli dzidzia w Afryce może odebrać MMSa z jakąś treścią, może równie dobrze odebrać maila. I nie potrzeba do tego specjalnej aplikacji, której obsługi musi uczyć się zarówno nauczyciel jak i uczeń. To samo tyczy się strony agregującej różne testy i materiały… na rynku istnieje już wiele systemów e-learningowych z przetestowanymi wdrożeniami, wykwalifikowanymi użytkownikami, pełną dokumentacją i dostarczających pełen wachlarz możliwości wymaganych od takiej platformy.

Do samego prowadzenia natomiast nie mam żadnych zastrzeżeń. Pójście na pierwszy ogień oznaczało faktyczne otwarcie imprezy, i ryzyko znudzenia widowni było większe niż w przypadku kolejnych prezentacji. Moim zdaniem jednak udało się bardzo dobrze – podczas tego wystąpienia powiedziałem do siebie “naprawdę będzie tu fajnie” i bez chwili znudzenia obserwowałem poczynania łodzian.

Moja ocena: 7/9 (za dość ciekawy pomysł i bardzo dobrą realizację – a w szczególności za tablicę; minus za odkrywanie koła na nowo w dziedzinie dość mocno już zagospodarowanej)

2) Demoscene Spirit (Uniwersytet im. Adama Mickiewicza w Poznaniu, Akademia Sztuk Pięknych w Poznaniu oraz Uniwersytet Medyczny w Poznaniu)

Drudzy w kolejności wystąpili zwycięzcy z zeszłego roku. Tym razem za problem do rozwiązania postawili sobie dyskomfort ciężarnej kobiety, która wielokrotnie podczas noszenia dodatkowego bagażu musi wybierać się do lekarskiego gabinetu na badanie KTG. A jak się okaże, że nie wszystko przebiega zgodnie z oczekiwaniami, to badanie takie wykonuje się nawet co 2 godziny (sic!). Dość ciekawe informacje jak na konkurs informatyczny i kolejny powód do odetchnięcia z ulgą, że Bozia postanowiła przy moim bycie postawić literkę M.
No dobra, ale co dalej? Otóż drużyna stworzyła uproszczony prototyp urządzenia, potrafiącego wykonać takie badanie bez wielkiej szpitalnej aparatury. Przy pomocy komputera. W DOMU pacjentki. Wyniki takiego badania zostają udostępniane lekarzowi, który juz wie co z nimi należy uczynić. Bardzo podobało mi się wielokrotne podkreślanie przez zespół faktu, że nie pretendują do tytułu pogromców drogich aparatów KTG, a jedynie chcą zwiększyć komfort pani w stanie błogosławionym poprzez zredukowanie liczby wizyt u lekarza – i tyle.
Pierwsze co rzucało się w oczy to nieprawdopodobnie wręcz urzekający interfejs użytkownika. Specjalnie do jego realizacji zaprzęgnięta studentka ASP próbowała wczuć się w rolę ewentualnej użytkowniczki programu i tak zaprojektowała wygląd aplikacji, że samo patrzenie i klikanie jest w stanie uspokoić szalejącą burzę hormonów czy zmniejszyć apetyt na śledzia z dżemem. Wielokrotnie podczas prezentacji wyrwało mi się “woow”, co nie zdarza mi się często.
Jeżeli do ciekawie wybranego problemu, fachowo zaprezentowanego przez studentkę medycyny, dodamy jego oryginalne rozwiązanie, opakowane w piękny interfejs i zaprezentowane na luzie w stuprocentowo profesjonalny sposób przez zapadający w pamięć zespół (zwracam uwagę na różnorodność uczelni i specjalizacji członków zespołu!) – otrzymamy prezentację-wzór. Jak dla mnie bomba.

Wspomnieć jeszcze muszę, że na omawianej problematyce oczywiście się nie znam, jednak obecna na widowni koleżanka z branży “dziecio-wyczarowującej” miała zastrzeżenia do przedstawianych faktów merytorycznych. Że 24 tydzień ciąży to coś tam, a 26 to coś tam innego, i że nie wszystko co usłyszeliśmy jest zgodne z prawdą… Ale newermajnd, jak ktoś się nie zna to i tak na to uwagi nie zwracał:).

Sędziom spodobał się również pomysł na ewentualną dystrybucję w aptekach. Fakt, ciekawe i oryginalne.

Moja ocena: 9/9 (właściwie za wszystkie elementy, na które zwracałem uwagę… tylko po co było do tego wszystkiego mieszać afrykańskie matki niemające możliwości kontaktu z lekarzem?)

3) NosoiFighters (Wojskowa Akademia Techniczna)

Ta prezentacja zaczęła się w dość nietypowy sposób. Wyobraźcie sobie: wychodzi koleś w jasnym garniturze i głosem Wołoszańskiego pomieszanego z narratorem Strefy W11 mówi: “wczoraj na sesji plakatowej jeden z biznesmenów był zarażony świńską grypą… zobaczmy ilu z nas przeżyje”. Taki klimat kilku pierwszych minut powodował nieustanny rechot w mych trzewiach, za co wielki plus.
Aplikacja miała służyć modelowaniu i symulacji rozprzestrzeniania się chorób zakaźnych. Biedne brudne dziecko w Meksyku ma jakąś chorobę i śmiga po mieście, gdzie natyka się na nie biznesmen z tej lepszej strony świata. Wsiada w samolot, wysiada na docelowym lotnisku i…

No właśnie, i co? Niestety, niewiele wyniosłem i zrozumiałem z całego wystąpienia. Pokazano nam jakieś kulki, wrzucono na stronę plik XML który był niby definicją jakiejś choroby, poklikano po obrazkach i tyle. Szkoda, bo zaczynało się fajnie. Jestem przekonany, że taki a nie inny rozwój prezentacji był spowodowany problemami technicznymi (naprawdę padła baza na studentlive udostępniona specjalnie w tym celu??) – sam bym pewnie zrezygnował z jakiejkolwiek walki, gdyby podczas wystąpienia wszystko przestało mi działać. No ale trudno, chodzi syf po ludziach. Po 20 minutach prezentacji wrażenie miałem negatywne: nuda, rezygnacja, nieporadność i szmery z sali zwiastujące porażkę i oczekiwanie na koniec.

Na szczęście w tym przypadku sędziowie, z genialnym Tadeuszem Golonką na czele, wypadli wyśmienicie. Podczas sesji Q&A dowiedziałem się o co tak naprawdę chodziło w aplikacji, skąd są czerpane dane i jak je można wykorzystać. Okazało się również, że WATowcy poza konkursem również zajmują się tą tematyką, co pozwoliło uwiarygodnić ich starania i wzbudziło respekt.

Moja ocena: 5/9 (tak mało, bo prezentacja kiepska; tak dużo, bo sesja z jurorami niezwykle obfita w nowe informacje)

4) RHEA (Politechnika Białostocka)

Białostoccy chłopccy i dziewczęta z Podlasięta tak jak niejedni poprzednicy bardzo ubolewali nad losem afrykańskich dzieci. Ciekawostka: w niektórych rejonach Czarnego Lądu bobasom nie nadaje się imion, dopóki nie przetrwają pierwszych X lat życia. A ile takich dzieci umrze podczas prezentacji? Nie pamiętam, ale mogliśmy się tego dowiedzieć. Cóż… nie ma to jak mocne wejście.
Stworzona aplikacja miała odmienić ten stan rzeczy poprzez udostępnienie globalnego systemu gromadzącego informacje o prawidłowym rozwoju dzieci w różnych regionach świata (tzw. siatki centylowe). Z jej pomocą troskliwy rodzic mógłby dodać swoją cegiełkę do światowej bazy danych oraz sprawdzić czy jego pociecha rośnie tak jak powinna. Cel szczytny, a wykonanie?
Jak dla mnie tylko dwie aplikacje konkursowe były wybitne pod względem UI. O pierwszej już pisałem, a ta druga to właśnie aktualnie opisywana. Bardzo miły dla oka, przyjazny interfejs prezentował najwyższy poziom. Zaglądając jednak pod spód ładnych okienek i stronek zauważyłem jedynie system gromadzący dane i… niewiele więcej. Wprowadź dane, zobacz uśmiechniętą bądź smutną buźkę pod wykresem i raduj się bądź leć do doktora. Owszem, wykorzystanie map i nanoszenie na nie informacji dotyczących aktualnej “sytuacji zdrowotnej” na świecie robiło wrażenie, jednak zdecydowanie zbyt mało czasu przeznaczono na opowiedzenie o najważniejszej i najbardziej skomplikowanej, moim zdaniem, części systemu. Chodzi mianowicie o opartą na statystycznych algorytmach predykcję rozwoju dziecka bądź grup dzieci w danym regionie. O tak interesującym feature jedynie wspomniano. Shaaade, bo widać było zainteresowanie jury tą kwestią (szkoda jednak, że bardziej nie pociągnęli drużyny za języki), a i wśród publiczności dało się zauważyć pewne ożywienie, gdy poruszono ten temat.

Napisałem “ożywienie” więc można by wnioskować, że cała reszta wystąpienia była nudna. Otóż… nie, nie było tak. To chyba najrzetelniej przygotowana prezentacja spośród całej piątki. Każdy krok był zaplanowany, widać było że wszystko szło zgodnie z planem. Bardzo dobrą angielszczyzną (co niestety nie jest jeszcze standardem) przeprowadzono nas przez założenia i rozwiązania zastosowane w systemie. Panujący na scenie porządek zawdzięczać można chyba rozsądnie rozplanowanym rolom w zespole – dwie osoby prezentujące i dwie obsługujące komputery i demonstrujące możliwości aplikacji.

Aha, jeszcze jedno: to był jedyny program, którego nazwę zapamiętałem. “Infant Analyzer”… czyż nie brzmi jak wzięte prosto z generatora nazw klas - http://www.classnamer.com/?:)
Moja ocena: 7/9 (za bardzo fajną prezentację, ładne UI i ciekawy pomysł przewidywania rozwoju dziecka, o którym niestety powiedziano zbyt mało)

5) kAMUflage (Uniwersytet im. Adama Mickiewicza w Poznaniu oraz Politechnika Poznańska)

Ostatnia paczka dzielnych informatyków miała trudne zadanie, ponieważ poziom poprzednich wystąpień był niezwykle wysoki. Aby im dorównać, trzeba było przedstawić rozwiązanie naprawdę ciekawego pomysłu. I tutaj pierwszy zgrzyt… czy to, że granie na instrumentach muzycznych jest mocno utrudnione dla ludzi niewidomych, można uznać za jeden z “największych problemów ludzkości”? Nie to żebym bronił komukolwiek grać albo żałował niewidomym czegokolwiek tudzież umniejszał ich nieszczęście, ale moim zdaniem praca nie była na temat. To tyle zrzędzenia.

Po przymknięciu oka na ten fakt nie sposób było nie docenić pomysłu oraz wykonanej przez zespół dobrej roboty. Stworzyli oni kilka aplikacji, które:
1) za pomocą PocketPC umieszczonego w specjalnym, skonstruowanym na potrzeby konkursu, “chwytaku” potrafią zrobić zdjęcie kartce z nutami, odpowiednio rozpoznać obraz i wygenerować cyfrową reprezentację zapisu nutowego (WOW!) – z interfejsem stworzonym z myślą o docelowych użytkownikach

2) przy użyciu stworzonego formatu plików umożliwiają przetłumaczenie rozpoznanych nut na alfabet Braille'a i ich wydruk na specjalnej drukarce

3) wspierają dzielenie się utworami w takiej postaci za pomocą biblioteki on-line

Prezentacja okraszona była filmikami ukazującymi Braille’ową drukarkę i (udane) próby wykorzystania wydrukowanych nut przez niewidomego muzyka. Jestem pewny, że takim ludziom może ona umilić życie. Jednak mimo wszystko… skala rozwiązywanego problemu ma się nijak do postawionego wyzwania.

Moja ocena: 4/9 (tak mało – bo moim zdaniem nie na temat; tak dużo mimo to, bo poza tym bez zastrzeżeń)

"A gdybym był jurorem…"

Może kiedyś się przekonamy co by wówczas było ;). A póki co kilka uwag:
Po pierwsze, przez te wszystkie lata ani razu nie zdarzyło mi się jeszcze zrozumieć werdyktu składu sędziowskiego Imagine Cup. Staram się być obiektywny, teoretycznie znam kryteria, jakimi sędziowie się kierują, ale… niestety nie potrafię pojąć skąd taka a nie inna kolejność na liście finalistów. Trochę światła rzucone na tą materię z pewnością podniosłoby poziom satysfakcji z uczestnictwa w Imagine Cup - zarówno zawodników, jak i widzów. Może jakaś anonimowa ankieta wypełniana przez każdego sędziego, dostępna dla wszystkich? Może suma punktów, jaką dany zespół uzyskał w danym kryterium? Może więcej słów wyjaśnienia podczas ogłaszania wyników…? Nie wiem jak najlepiej można to rozwiązać, moim zdaniem jednak aktualny stan rzeczy pozostawia trochę do życzenia. Nie są to w końcu wybory Miss Przedszkolaków i stuprocentowa czarna zasłona nie jest chyba aż tak niezbędna.

Po drugie, część pytań zadawanych przez sędziów do zespołów była najzwyczajniej w świecie… głupia i niepotrzebna. Z tego co się orientuję to nie ma obowiązku zgłaszania swoich uwag na siłę. Po co więc się odzywać, jeśli nie ma się nic mądrego do powiedzenia? Lans, chęć zabłyśnięcia? Nie wiem… ale momentami dość mocno takie coś rzucało się w oczy.

I ostatnia uwaga: w konkursie na tym poziomie i o takim znaczeniu nie powinno być miejsca na jakąkolwiek prywatę. Stąd też jedno z pytań zadane zespołowi Demoscene Spirit brzmiące: “a po pierwsze to czy Pani Agata się obroniła?” uważam za megaporażkę i wymazuję to z pamięci.

Na koniec moja kolejność: 1) Demoscene Spirit; 2) RHEA; 3) FteamS; 4) NosoiFighters; 5) kAMUflage.

Impreza

Jak co roku dzień pełen wrażeń został uwieńczony imprezą. Tym razem mieliśmy okazję pobawić się w kręgielni Hulakula, gdzie zorganizowano nam wyżerkę, wypitkę, turniej w kręgle, możliwość gry w bilard i rzutki. Rozpisywać się nie będę (tym bardziej że znaczna część wieczoru miga gdzieś w błogiej mgle zapomnienia;) ) – było po prostu tak jak być powinno.

Podsumowanie

W kilku końcowych słowach należą się wyrazy najwyższego uznania dla głównych organizatorów konkursu, czyli Piotra Kramka oraz reszty zespołu: Karola, Kasi, Eugeniusza i Jana (do objerzenia na stronach Microsoftu). Moim zdaniem całe wydarzenie rozwija się bardzo energicznie i w pełni zasłużenie polska ekipa otrzymała okazję zorganizowania przyszłorocznego światowego finału IC. Tak trzymać, radość serce rozpiera gdy patrzy się na tak dynamiczną ewolucję czegoś tak potrzebnego i szczytnego! O tym, że ich wysiłki nie idą na marne, świadczyć może rosnący z roku na rok poziom dostarczanych projektów. Ba, "projekty" to jest już nawet właściwe słowo! To, z czym mamy do czynienia, to w większości gotowe do wdrożenia PRODUKTY! Ristekpa.

Na uwagę zasługiwała również obecność gościa specjalnego z USA – Joe Wilsona piastującego wysokie stanowisko Director of Academic Initiatives for Microsoft. Po obejrzeniu wszystkich wystąpień mieliśmy okazję wysłuchać jego oficjalnego stanowiska odnośnie trwających finałów. Nastawiałem się na standardową gadkę w stylu "polscy studenci są na wysokim poziomie, jesteście wszyscy fajni i tak mi tu dobrze", ale na szczęście Joe wyszedł poza takie wyświechtane slogany. Tych kilkunastu minut w jego wykonaniu słuchało się bardzo przyjemnie, potrafił dać sensowny feedback każdej z drużyn i w dość pompatycznym, ale jednocześnie trzymającym realny poziom stylu zachęcić do dalszej pracy. Jak dla mnie jego słowa powinny być mottem i doskonałym podsumowaniem konkursu: "Take your ideas further – it does not stop here!".

Innym elementem powalającym na kolana było wspomniane już prowadzenie sesji Q&A przez Tadeusza Golonkę. Jego rola nie była dla nikogo zaskoczeniem, ponieważ takie zadanie otrzymuje co roku. Poza Imagine Cup miałem okazję dwukrotnie zetknąć się z Tadeuszem na prowadzonych przez niego szkoleniach, więc jego osoba nie jest dla mnie nowością. A jednak… w tym roku wielki kunszt mediatora pomiędzy zespołami i jury zdołał mi ponownie niesamowicie zaimponować. Błyskawiczne i trafne puenty, błyskotliwe podsumowania, sklejanie dialogów w jedną mającą ręce i nogi całość – mistrzostwo. Na szczęście nie ma chyba przesłanek aby sądzić, że w kolejnych edycjach może się to zmienić.

Na sam koniec dwie uwagi krytyczne, ale nie mogą one zaważyć na ogólnym odbiorze konkursu, więc będę się streszczał:
1) wspomniana wcześniej przerwa na kawę (i obiad pewnie też – nie mieliśmy na tyle cierpliwości żeby się przekonać i poszliśmy do knajpy) to totalna porażka; jeżeli kolejne edycje mają się także odbywać w IWP to niechaj ktoś coś z tym zrobi – albo ulepszy, albo zupełnie z tego zrezygnuje
2) moim zdaniem ogłaszanie wyników podczas imprezy wieczornej miało o wiele fajniejszy klimat niż wyczytanie zwycięzców przed zakończeniem "oficjalnej" części; jednak powody takiego a nie innego planu są mi już znane, przyjmuję je do wiadomości i w pełni akceptuję… co nie oznacza że z braku innych "be" i "fuj" nie mogłem o tym tutaj wspomnieć:)

I to tyle. Zwycięzcom gratuluję, organizatorom dziękuję i, mam nadzieję, spotkamy się ponownie za rok.
Do niezdecydowanych studentów zwracam się jednocześnie z apelem: nie marnujcie tej wielkiej szansy i bierzcie udział w kolejnej edycji! Do roboty!

opublikowano 20 maja 09 06:22 przez Procent | 6 komentarzy   
Zarejestrowano w kategorii: ,
Już niebawem: Polskie finały Imagine Cup 2009!

Kiedy? Środa, 13 maja 2009. Gdzie? Instytut Wzornictwa Przemysłowego. Wreszcie: co? Kolejne polskie finały konkursu Imagine Cup w kategorii Projektowanie Oprogramowania!
Idea tego konkursu jest doprawdy wspaniała. Mamy “temat przewodni” i piszemy aplikację związaną z zaproponowanym problemem. Może to być komunikacja międzyludzka, zdrowie czy edukacja. W tym roku uczestnicy musieli zmierzyć się z “najtrudniejszymi problemami ludzkości” (może ktoś wpadnie na aplikację do maszyn drukujących karty do głosowania wstawiającą puste linie w miejsce kandydatów z PiS?;) ).

Korzyści płynących z uczestnictwa jest wieeele. Sam dwukrotnie miałem okazję zmierzyć się z innymi drużynami na tym etapie, wymienię więc kilka zalet startu:
1) znajomości; konkurs gwarantuje wytężoną pracę, zarwane noce, niemało stresu i górę satysfakcji, co z kolei pozwala na utworzenie zgranego, dobrze-się-rozumiejącego zespołu; wspólne wypicie morza tigera i nieprzespanie kilku kolejnych nocy może zaowocować długoletnimi znajomościami, jakiś próżno szukać gdzieś indziej
2) “technologiczna przygoda”; aplikacje tworzone na potrzeby konkursu nie są standardowymi projektami, muszą charakteryzować się innowacyjnym pomysłem i ciekawą realizacją… udział w konkursie może być jedyną okazją na stworzenie czegoś, czego nikt wcześniej nie tworzył, a jeśli dodamy do tego typowe zdarzenia towarzyszące programowaniu przez Xdziesiąt godzin non-stop (każdy programista powinien tego spróbować) to w rezultacie otrzymamy prawdziwą technologiczną “wyprawę w nieznane” – i to jest COŚ!
3) doświadczenie; praca w zespole uczy pokory, uczy zaufania, uczy dyscypliny i chęci dzielenia się wiedzą, a w takich okolicznościach przyrody mamy to wszystko podane w bardzo intensywnym stężeniu, którego lekceważyć nie sposób
4) poznanie technologii; stworzenie oryginalnego projektu wymaga zagłębienia się w tajniki narzędzi w stopniu niespotykanym podczas “normalnego studiowania”, ponieważ otrzymuje się okazję (a czasami warunki to wymuszają nie pytając o zdanie) do naginania standardowych praktyk i szukania nowych zastosowań dla znanych rozwiązań
5) kontakty; wyjazd na finał oznacza szansę na poznanie młodych ludzi z całego kraju, którzy dzielą wspólną pasję i bez złych emocji stają do rywalizacji, aby następnie po wyczerpującej pracy spędzić wspólny wieczór w organizowanej przez Microsoft imprezie… która, jak wynika z moich doświadczeń, jest bardzo przyjemnym, bujającym, bogatym, relaksującym i (nie)zapomnianym sposobem na zakończenie całej przygody ;)
6) możliwość wygrania cennych nagród; co tu dużo gadać – Windows, Visual Studio czy szpanerski telefon to fajna sprawa, jednak nie bez powodu wymieniłem je na ostatnim miejscu – bo nie po to się startuje w IC

Tak oto przedstawia się Imagine Cup moimi zapuchniętymi oczami bez powiek, i w ten właśnie sposób cztery lata temu zaczęła się moja cała - jeśli można to tak określić - “kariera”. Jeżeli jesteś studentem i nie brałeś nigdy udziału w tej zabawie, gorąco zachęcam! Ba, powiem więcej – dzięki Imagine Cup możesz nawet stać się gwiazdą ;).

Ale czemu ja tak nagle o tym wszystkim…? Otóż piszę o IC, ponieważ nie mogę się już doczekać zasiąścia na widowni i podziwiania przedstawianych rozwiązań. A w tym roku będę miał taką okazję. Spodziewam się spektaklu technologicznej pasji przedstawionej w profesjonalny, potrafiący zainspirować sposób. Tym bardziej że tym razem w finale walczyć będą aż dwie białostockie drużyny, powodzenia!

opublikowano 11 maja 09 06:28 przez Procent | 2 komentarzy   
Zarejestrowano w kategorii:
Więcej wypowiedzi Następna strona »