| Krzysztof's profileKrzysztof DrelczukPhotosBlogLists | Help |
|
|
November 17 Stronicowanie danych po stronie serwera za pomocą CTE (Common Table Expression)Zawsze kiedy chcemy stworzyć wydajną aplikację webową to musimy poradzić sobie ze stronicowaniem danych po stronie serwera bazodanowego. SQL Server 2005 ma bardzo fajną funkcję, którą to ułatwia a mianowicie row_number(). Jednak ja osobiście nigdy nielubiłem tworzyć tego typu zapytań. Jednak po połączeniu tej metody z Common Table Expression zapytanie wygląda bardzo przyzwoicie – jest czytelne i bardzo ładwo je modyfikować dla różnych zbiorów danych. Przykładowa procedure została przedstawiona poniżej. create procedure Sys_User_GetAllUsers and @PageNum * @PageSize end; Jeśli chcemy ponownie użyć poniży kod to wystarczy wkopiować między zielone komentarze nowe zapytanie i już! Szybko, łatwo i przyjemnie. PS. Dokładniejsze informacje o CTE na stronie: http://msdn.microsoft.com/en-us/library/ms190766.aspx . November 08 Kolejne liczby całkowite po raz kolejnyGdzieś w jednym z poprzednich postów prezentowałem jak wyświetlać kolejne liczby całkowite. O ile rozwiązanie Oracl’owe było całkiem ładne to MS Sql’owe było oparte na widoku sys.objects. Niezbyt fajne rozwiązanie o czym się niedawno przekonałem – ograniczona ilość wierszy oraz mogą pojawić się różnice między środowiskiem deweloperskim o produkcyjnym. Potrzeba matką wynalazków więc dziś powstało takie o to cudeńko:
Działa pięknie i nie ma żadnych ograniczeń. Jeśli jako typ @desiredCount damy bigint to możemy tak aż do 9,223,372,036,854,775,807. Na pewno wystarczy. Co więcej zapytanie nie dotyka żadnej tabeli, więc jest to bardzo szybkie rozwiązanie. Jedna, by wszystkimi rządzić, jedna, by wszystkie odnaleźć, Jedna, by wszystkie zgromadzić i w ciemności związaćTytuł tego wpisu idealnie opisuje instrukcję, którą chcę w nim opisać. Ale od początku. Jestem wielkim miłośnikiem procedur składowanych (ktoś by pomyślał, że Tolkiena...) ale jednocześnie jestem trochę leniwy. Strasznie dużo czasy zajmuje pisanie jednej procedury do wstawiania nowych wierszy, jednej dla aktualizowania ich, jednej dla kasowania i co najmniej kilku do wyciągania danych. Jest niby LINQ... ale Ci co coś wiedzą to wiedzą, że w stosunku do SQL'a to tak jakby go nie było. Tak więc jeszcze trochę będzie trzeba nam poczekać na to aby tworzyć warstwę abstrakcji dostępu do danych z poziomu kodu... Zresztą moim zdaniem i tak powinna być ona po stronie serwera. Tam jest jej miejsce - zapewnia to dużą elastyczność, bezpieczeństwo a często większą szybkość i łatwość optymalizacji. Dodatkowo są do tego świetne narzędzia jak widoki i procedury składowane (dodam tylko, że procedury po stronie bazy wcale nie równają się logice po stronie bazy - okazuje się, że wiele osób nie rozumie tej, wcale nie subtelnej, różnicy). Wracając do tematu, nie raz miałem styczność z bazami, które zawierały po kilka tysięcy takich procedur. Co więcej sam widzę jak w moich projektach ich ilość rośnie, można powiedzieć, w oka mgnieniu. Można jednak trochę ich ilość zmniejszyć - przynajmniej w stosunku do procedur operujących na jednej tabeli. Usuwanie można załatwić jedną procedurą (ale to proste, więc nie będę o tym pisał... chociaż może kiedyś), ale co z resztą. Pobieranie danych trzeba zostawić tak jak jest, jednak wstawianie oraz edycję można scalić w jedno. Nadaje się do tego nowe polecenie SQLServer'a 2008 merge - trochę jak francuskie przekleństwo. Generalnie chodzi o to aby jednym poleceniem wszystkim rządzić, wszystkie odnaleźć, zgromadzić i... w ciemności związać bo składnia jest bardzo mało czytelna - przynajmniej na początku. A wygląda to tak. Najpierw tabelka testowa: create table MergeTest ID int identity primary key,
a później magiczna procedurka: create procedure CreateOrUpdateMergeTest Zwięzła, prawda? A jak to działa? Wywołajmy ją z następującymi parametrami trzy razy: exec CreateOrUpdateMergeTest -1 ,'AAAA','BBBB'
ID Value1 Value2 A teraz wywołajmy ją w następujący sposób exec CreateOrUpdateMergeTest 2 ,'AAAA','BBBB'
ID Value1 Value2 Drugi rekord uległ zmianie.Dzieje się tak dlatego, że utworzona procedura sprawdza czy podane ID istnieje, i jeśli tak to aktualizuje rekord, a w przeciwnym razie wstawia nowy. Jej odpowiednikiem w SQL Server 2005 byłaby instrukcja warunkowa: if exists (select ID from MergeTest where ID = @id) i jeśli warunek jest prawdziwy to aktualizuje rekord za pomocą instrukcji update, a w przeciwnym razie wstawia nowy za pomocą instrukcji insert. Problem jednak z taką sekwencją instrukcji jest to, iż jest to sekwencja instrukcji... Najpierw przeszukujemy tablicę w poszukiwaniu rekordu spełniającego warunek (pierwsza blokada), później w zależności od wyniku aktualizuje lub wstawia rekord (druga blokada). Dodatkowo jeśli mamy bardzo oblegany serwer to albo powinniśmy opakować if'a w blok transakcyjny albo zaimplementować pessimistic concurency - jakby nie było i tu i tu trochę roboty. A tak wszystko to czynimy za pomocą jednej instrukcji i w dodatku jeszcze znacznie wydajnej. Gwoli wyjaśnienia, wypadałoby opisać co dokładnie dzieje się w naszej instrukcji merge. -- wskazujemy tabele docelową
November 03 Koncepcja komputera by EricssonCiekawą rzecz zaprezentował Ericsson. Kompter w kształcie walca - zamiast monitora projektor, zamiast klawiatury laserowy czytnik. Wygląda nieźle. Mały, zgrabny i mobilny... chociaż ciężko wyobrazić używanie go w pociągu albo na plaży :)
November 01 FillFactor czyli kwestia typu indeksu raz jeszcze (przy okazji trochę o optymalizacji indeksów)W ostatnim poście rozważaliśmy jaki rodzaj indeksu głównego będzie najlepszy dla naszej bazy danych. Jest jednak bardzo istotna kwestia, której w nim nie poruszyłem. Mianowicie współczynnik FillFactor. A więc co to takiego jest? FillFactor definiuje jak bardzo wypełniania jest strona danych w drzewie indeksu (strona danych to podstawowa jednostka alokacji danych w serwerze SQL). Definiuje się go podczas tworzenia indeksu lub za pomocą DBCC BREINDEX() – co generalnie jest tym samym co DROP INDEX oraz CREATE INDEX. Jeśli ustalimy jego wartość na 75 to powiemy tym samym serwerowi aby zapełniał strony danych tylko w 75%. Jego domyślna wartość to 0 i jest ona praktycznie równoznaczna z… 100% (jakby ciut niekonsekwentnie). To znaczy, że serwer zapełnia strony danych w całości – z jednym małym wyjątkiem pozostawia „trochę” miejsca przy korzeniu drzewa. Po co więc zostawiać miejsce w stronach danych? Odpowiedź brzmi następująco. Gdy strona danych jest pełna, a serwer musi wstawić tam jakieś dane, to wtedy z powodu braku miejsca wykonuje operacje zwaną podziałem strony (page split). Dzieli naszą pełną stronę, więc na dwie (mniej więcej tak samo wypełnione) i dopisuje dane. Gdy strona ponownie się zapełni powtarza operację. Jak łatwo się domyślić są to operacje bardzo kosztowne (alokacja nowej strony, przeniesienie danych, reorganizacja stron w b-drzewie). Idealnie byłoby więc zminimalizować ilość podziałów stron. Więc ustawmy FillFactor na powiedzmy 10%. No niestety to też nie jest dobre rozwiązanie. Nasze dane wtedy będą wymagały 10 razy więcej przestrzeni dyskowej co z kolei zmniejszy wydajność przy odczycie danych. Można powiedź – kiepska sprawa. Co byśmy nie zrobili to zawsze będzie sytuacja, dla której decyzja będzie błędna. Już mniej więcej widać jak oscylować tym parametrem w celu optymalizacji bazy. Kiedy mamy tabelę na której nie wiele się zmienia, a są częste odczyty (na przykład okresowo tworzone tabele zasilające modele analityczne lub hurtownie danych) wtedy powinniśmy ustawić FillFactor na 100%. Jeśli natomiast mamy tabelę często uaktualnianą a klucz nie jest monotonicznie rosnący to wtedy warto ustalić niższą wartość (jednak i tak powyżej 50%). I tutaj właśnie jest nawiązanie do wcześniejszego wpisu. Mieliśmy tam bardzo duży spadek wydajności z powodu zastosowania klucza głównego typu GUID. Problem zniknął kiedy uzależniliśmy go od daty – tak naprawdę stworzyliśmy klucz monotonicznie rosnący i wyeliminowaliśmy podziały stron. Jak widać, taki podział, jest operacją bardzo kosztowną. Kiedy mieliśmy jako główny klucz kombinację INT i IDENTITY wtedy nie nastąpił ani jeden podział strony i mieliśmy bardzo duża wydajność. Ale co w sytuacji kiedy nie możemy zrezygnować z czystego GUID’a. Czy jesteśmy skazani na tak niską wydajność przy często uaktualnianych tabelach? Rozwiązaniem jest właśnie FillFactor. Mając na uwadze „czystą losowość” GUID’ów możemy pokusić się na ustawienie go na 75% lub nawet na 50% jeśli tabela jest bardzo często uaktualniania. Oczywiście współczynnik ten odnosi się do wszystkich indeksów a więc także niegrupujących (non clustered). Tak więc jeśli zakładamy taki indeks na kolumnie przechowującej daty transakcji to możemy ustawić go na 100% - jeśli nie znamy sposobu aby cofnąć się w czasie to wtedy możemy być pewni, iż podział strony nie nastąpi. Podobna sytuacja ma miejsce w przypadku indeksowania np. numerów dokumentów. Natomiast kiedy zakładamy indeks np. na kwocie sprzedaży to wtedy pozostawienie takiego domyślnego wskaźnika FillFactor jest już niestosowne. October 31 GUID czy INT czyli trochę o kluczach głównychKlucz główny w tabeli jest jednym z głównych obiektów jakim musimy zarządzać w naszej bazie. Ma on kluczowe znacznie w wydajności dostępu do danych jak i przy późniejszej optymalizacji zapytań. Niestety większość osób poświęca mu nie wiele uwagi podczas projektowania bazy. Przyjrzyjmy się trochę bliżej najbardziej powszechnym praktykom tworzenia kluczy głównych. Klucze naturalne i surogaty To dwie pierwsze kategorie, z których musimy wybrać projektując bazę danych. Klucze naturalne to klucze występujące w domenie struktur danych oraz unikatowo identyfikują opisywany obiekt. Przykładami takich kluczy są: PESEL w odniesieniu do osoby (pomijamy możliwość kolizji – jest ona bardzo mało prawdopodobna), REGON w odniesieniu do instytucji, numer dokumentu w przypadku faktur, ISBN w przypadku książek i tak dalej. Jedną z zalet takich kluczy jest pozostanie w zgodzie z model relacyjnym Codd’a (będąc bardzo ścisłym surogaty nie do końca naruszają ten model, jednak znacznie się od niego oddalają) – choć wiem, że dla większość nie jest to wystarczający argument za ich stosowaniem. Z doświadczenia wiem, iż bardzo często narusza się podstawowe reguły tworzenia relacyjnych baz danych w imię „prostoty”. Na krótką metę może i jest to jakieś rozwiązanie ale w dłuższej perspektywie zawsze się mści i powoduje więcej kłopotów niż korzyści.
Surogaty natomiast to klucze główne utworzone jako unikatowy identyfikator danego rekordu. Może być nim liczba całkowita zwiększająca swą wartość o jeden za każdym razem kiedy dopisujemy rekord, może być nim GUID jak i każda inna unikatowa wartość (kombinacja znaków, wynik jednokierunkowej funkcji skrótu) jednak te dwie pierwsze są najbardziej popularne. Jest to krok w stronę modeli obiektowych gdzie każdy obiekt ma swój unikatowy numer identyfikacyjny (ID) oraz ich struktura jest spójna w obrębie całej bazy. Jest to bardzo duża zaleta ułatwiająca zarządzanie danymi z poziomu aplikacji. Dodatkowo klucze takie są mniejsze - z reguły poniżej 128 bitów, gdy klucze naturalne często przekraczają tą wartość – jeden znak UNICODE (UTF-16) 16 bitów. Choć ilościowo więcej „za” przedstawiłem na korzyść kluczy naturalnych to jednak częściej używane przeze mnie jak i przez innych architektów są surogaty – główny powód to spójność kluczy głównych i mniejsza szansa na popełnienie błędu. No i jest jeszcze powód egoistyczny czyli lenistwo. Taki sposób reprezentacji kluczy głównych jest po prostu bardzo wygodny! Więc wybór jest prosty. Problem pojawia się jednak przy wyborze typu takiego klucza. 90% projektantów baz danych używa typu integer i ustawia pole identity na true. I już, choć możliwości jest znacznie więcej… Integer czy GUID Ostatnio to jedna z najmodniejszych dyskusji wśród projektantów baz danych. Powoli dorównuje ona popularności dyskusji czy używać procedur składowanych czy też trzymać zapytania po stronie klienta – i podobnie jak ta obrosła mnóstwem mitów. Zanim przejdziemy do testów to najpierw rozważmy za i przeciw obu podejściom – może na tym etapie już będzie można odrzucić jedną z metod. Zalety GUID’a:
Wady GUID’ów:
Jak widać główne wady GUID’ów to ich wpływ na wydajność. Najprościej będzie jak przetestujemy to na prawdziwych danych. Testy wydajności Testy przeprowadziłem na dwóch poniższych tabelach: create table TestGUID create table TestINT
Do każdej z nich wstawiłem 1 mln wierszy („commitując” transakcję po każdym wierszu). Czas wstawienia dla obydwu tabel jest następujący:
Jak widać różnica jest spora. A co z pobieraniem danych. Wyciągnijmy wszystko co wstawiliśmy i zmierzmy czas.
Okazuje się, że różnica jest symboliczna (w granicach błędu pomiaru). Identycznie sytuacja ma się przy wyszukiwaniu i złączeniach (jednym z kluczowych argumentów przeciwko GUID’om jest właśnie złączenie – jak się okazuje jest to mit). Tak więc jeśli nie musimy wstawiać miliona wierszy na raz to kwestie związane z wydajnością możemy pominąć. Przyspieszenie wstawiania Rzućmy okiem na kilka GUID’ów: 1F46C338-E0AA-4B4A-8A61-30B838EEEDFF Widzicie wzorzec? Nie?! To dobrze. Bo go nie ma (przynajmniej na pierwszy rzut oka tak się wydaje; pomijając 13 znak gdzie zawsze jest 4: oznacza on iż GUID został utworzony przez generator Microsoft). Ilość kombinacji wartości jaką może przechować GUID jest ogromna – zdecydowanie za duża w większości przypadków. Może by zmniejszyć losowość – teoretycznie powinno to wpłynąć pozytywnie na wydajność. Jednych z podejść jest GUID sekwencyjny (w SQLServer 2008). Jednak jest pewien kłopot z generowaniem go po stronie klienta (a przypominam, że możliwość samodzielnego tworzenia pełnych obiektów po stronie klienta wskazałem jako zaletę GUID’a – nie dobrze by było się teraz z tego wycofać). Więc może jakieś hybrydowe rozwiązanie. Okazuje się, że jest. Zostało ono zaprezentowane przez Jimmiego Nilssona. Utwórzmy za jego namową własnego GUID’a w następujący sposób: declare @customGuid uniqueidentifier set @customGuid = CAST(CAST(NEWID() as binary(10)) + CAST(GETDATE() as binary(6)) as uniqueidentifier) Choć na pierwszy rzut oka wygląda to całkiem dziwnie to tak naprawdę podmieniamy jedyie 6 ostatnich batów i uzależniamy je od daty. W tej chwili gdy wygenerujemy 5 GUID’ów to wyglądać one będą następująco. E9EB5E81-ED04-486A-BB46-9CB300E83827 Gdy zrobimy to ponownie po kilku minutach to rezultat będzie taki: 46A3367D-E0B7-49D3-8A7D-9CB300E94E5E Nieznacznie zmieniły się ostania część. Reszta dalej jest w pełni losowa. Ta wolno zmieniająca się część (6 ostatnich bajtów) powtórzy się ponownie za około 77 lat. Więc przez tak długi okres możemy być pewni, że nienstąpi kolizja (oczywiście w scenariuszach wielu środowisk i replikacji baz pomiędzy nimi należy się zastanowić czy to wystarcza – moim zdaniem nie). Dalczego podmieniamy ostanie 6 bajtów? Okazuję się, że MS SQL tworzy b-drzewo dla GUID’ów zaczynając „od końca”. Zabaczmy jaki wpływa miało to na wydajność:
Różnica już jest prawie symboliczna. Podsumowanie Jak widać jeśli bierzemy pod uwagę wydajność to obydwa rozwiązania są dobre (jeśli chodzi o aspekt wydajność na poziomie bazy). Myślę jednak, iż zalety jakie wypisałem przy opisywaniu surogatów zbudowanych na GUID’ach bezsprzecznie ukażą ich jako zwycięzców testu. Jest jeszcze jeden aspekt o którym nie napisałem. INT + IDENTITY jest najbardziej popularną kombinacją, ale nie jest zgodna z ANSI. IDENTITY jest natywną opcja MSSQL Server. Jeśli kiedykolwiek będzie potrzeba migrowania naszej bazy na inny system, co wbrew pozorom nie zdarza się tak rzadko, to będziemy mieli bardzo dużo dodatkowej pracy. September 15 Wizja świata przyszłości by Microsoft w 2019Wygląda bardzo przyjemnie. Jak nas nie zmiecie w 2012 to jest nawet szansa, że dożyje... nie mogę sie doczekac :)
Ciekawa domena Ciekawą domenę ma wyspa Anguilla... Okazuje się, że to wyspa nie byle jaka bo karaibska http://pl.wikipedia.org/wiki/Anguilla. Ale do rzeczy domena jest ładna bo .ai . Ładnie komponuje sie ze stroną dotykającej technologii sztucznej inteligencji. Szczegóły: http://whois.ai/. Konkurs Prac Magisterskich z dziedziny Informatyki EkonomicznejCałkiem niedawno okazało się, że moja praca magisterska pod tytułem "Wyszukiwanie wzorców kupna-sprzedaży w finansowych szeregach czasowych za pomocą teorii falek i gazów neuronowych" zajęła drugie miejsce w XIII edycji ogólnopolskiego konkursu na najlepszą pracą z dziedziny Informatyki Ekonomicznej. Konkurs był zorganizowany przez Naukowe Towarzystwo Informatyki Ekonomicznej przy wsparciu Accenture. Szczegóły: Informacja bardzo motywująca do dalszej pracy. September 11 Pobranie parametrów z dynamicznego SQL Dynamiczny SQL jest fajny ale problem pojawia się wtedy kiedy chcemy coś z niego wyciągnąć na zewnątrz do naszego scope'a. W takim przyapdku trzeba zabawić się z procedurą sp_executesql. DECLARE @UserName varchar(50) Trigger for each row w T-SQL Ostatnio w pracy tworząc moduł logujący dla bazy danych zderzyłem się z brakiem wyzwalacza "for each row" - używając nomenklatury Oracl'owej. Okazuje się, że jest na to rozwiązanie.... niezbyt ładne i mało wydajne... no ale da się. Należy utworzyć... uwaga... kursora... brrr. No niestety. declare
updateCursor cursor for
select ModifiedBy,
Id from inserted fast_forward Powyższy kod pochodzi z wyzwalacza ON UPDATE. Nic pięknego ale działa! September 07 Generyczny singleton w .NET W swojej pracy, jako architekt, często korzystam ze wzorca Singleton (jeden z moich ulubionych wzorców - tak przy okazji - tak więc z pewnością go trochę nadużywam:) ). Trochę męczące jest w każdej klasie umieszczanie klasycznego fragmentu charakteryzującego ten wzorzec. Dlatego napisałem sobie generyczną klasę bazową Singleton. Wygląda ona mniej więcej tak: public class Singleton<K> where K : class, new() { #region thread safe singleton pattern private static K _instance = null; static readonly object singletonLock = new object(); public static K Instance { get { lock (singletonLock) { if (_instance == null) { _instance = new K(); } return _instance; } } } #endregion } W tej chwili wystarczy zadeklorowac klasę: public sealed class SingletonConcrete : Singleton<SingletonConcrete> { } I juz... Od tej pory użycie SingletonConcrete.Instance zawsze pozwoli uzyskać dostęp do tej samej instancji. Bardzo miła rzecz. Dzięki niej mogę jeszcze bardziej nadużywać ten wzorzec ;) . Jak znaleźć klucz główny dowolnej tabeli Przed takim problemem stanąłem przy implementowaniu generycznego rozwiązania dla śledzenia zmian w bazie. Google pomógł znaleźć poniższy skrypcik: declare @TableName varchar(128) set @TableName = 'Nazwa tabeli' select c.COLUMN_NAME from INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk , INFORMATION_SCHEMA.KEY_COLUMN_USAGE c where pk.TABLE_NAME = @TableName and CONSTRAINT_TYPE = 'PRIMARY KEY' and c.TABLE_NAME = pk.TABLE_NAME and c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME July 07 Kolejne liczby w SQLJak wyświetlić kolejne liczby w SQL? Okazuje się, że nie tak trudno. Wystarczy: SELECT ROWNUM NR FROM DUAL CONNECT BY ROWNUM < 100 Proste, prawda? W T-SQL ciut dłuże ale też nie powalająco skomplikowanie: select X.nr from( select ROW_NUMBER() OVER ( ORDER BY object_id ) nr from sys.objects ) X No a jednak są programiści, którzy wolą inaczej. Dziś spotkałem się z czymś takim: select 1 as nr i tak dalej do stu…. Aż ciężko uwierzyć, że ktoś nie dostrzegł nieefektywności i że przeszło to code-review. Ciekawe, co by było gdyby było trzeba wyświetlić milion kolejnych wartości?:) O ilości MCPD: Designing and Developing Windows Applications Using the Microsoft .NET Framework 3.5Kompletnie przypadkiem trafiłem na statystyki MCP. Ile osób ma jaki certyfikat. Jeśli chodzi o certyfikat z tematu wpisu to na świecie posiada go 318 osób. Nie wiele (w sumie jest ponad 2,5 mln certyfikowanych specjalistów). Ale ciekawie robi się w przypadku Polski. Otóż ten certyfikat po za mną ma JEDNA osoba. To się nazywa dołączyć do elit (parafrazując hasło MS)! Gwoli ścisłości statystyki są na dzień 10 czerwca 2009 (tak więc o miesiąc przestarzałe). Pewnie to troszeczkę z powodu tego że to stosunkowy młody egzamin (istnieje dopiero od początku tego roku)…. Ale co tam! Drugi to drugi :) Dołączam jeszcze linki z numerkami: Kilka słów o egzaminachJakiś czas z powodu braku czasu zaniedbywałem trochę kronikarską funkcję blogu. A trochę się wydarzyło. Mam na myśli kolejne certyfikaty, jakie udało mi się uzyskać ze ścieżki developerskiej MS. A było ich aż trzy. TS 70-505: Microsoft .NET Framework 3.5, Windows Forms Application DevelopmentKilka słów o tym egzaminie. Moim zdaniem nie był prostszy od egzaminu podstawowego (70-536) bo to chyba nie możliwe, ale chyba był on porównywalny. Generalnie miałem wrażenie, iż był on zrobiony w pośpiechu. Niektóre pytania jak i odpowiedzi wyglądały na bardzo nieprzemyślane. Z ciekawostek to pojawił się LINQ i lambda. Co prawda nie było tego dużo (łącznie 4 pytania), ale chyba wystarczająco, aby sprawiło, że poczuło się powiew świeżości. Podsumowując jednym zdaniem egzamin prosty, łatwy do zaliczenia nawet z niewielką wiedzą ze względu na bardzo nieprzemyślane odpowiedzi, które same się eliminują pozostawiając jedną poprawną. PRO 70-563: Designing and Developing Windows Applications Using the Microsoft .NET Framework 3.5To mój pierwszy egzamin PRO jak zdawałem. I tutaj pełne zaskoczenie. Egzamin był całkiem inny niż pozostałe. Składał się z 50 pytań i aż 90% to „case’y”. O ile egzamin podstawowy zdałem w około 15-20 minut a MCTS’y w około 30 minut tak ten zajął mi aż 1h 15m. Pytania były rozbudowane i wymagające zastanowienia. Było też wiele pytań odnośnie architektury, aplikacji wielowarstwowych oraz smart client’ow. Tak, więc duże odejście od tego, co było w poprzednich egzaminach na tej ścieżce. Przy tym egzaminie większy nacisk był nałożony na wykorzystanie technologii bardziej niż na wiedzy o niej. Udało mi się go zaliczyć, ale to chyba jeden z tych egzaminów, do których jedyny sposób, aby się przygotować to mieć kilkuletnie doświadczenie w tworzeniu oprogramowania. Czasami niż sama wiedza ważniejsze przy nim będzie wyczucie jak coś powinno wyglądać – a tego z żadnych podręczników niestety nie da się nauczyć. Egzamin oceniam pozytywnie (choć moim zdaniem za dużo pytań z Deployment’u bo aż około 10 – a z takimi problemami programista raczej mało ma doczynienia), choć był trudny to w przeciwieństwie od poprzedniego na ścieżce wyglądał na przemyślany i dopracowany. Natomiast, jeśli chodzi o poziom trudności to może nie bardzo trudny, ale na pewno nie łatwy (drogą eliminacji: trudny J). MCTS 60-503: Microsoft .NET Framework 3.5 - Windows Communication FoundationO tym egzaminie napiszę najmniej. Z pewnym względów nie powinienem się o nim wypowiadać. Powiem tylko, że z mojego punktu widzenia jest bardzo trudny i szczegółowy (jednak dobrze skonstruowany). Trzeba mieć naprawdę sporą praktykę w tej technologii aby sobie z nim poradzić. July 06 Krótka historia o if’ach i switch’ach z niewielkim podtekstemTo było normalne spotkanie statusowe, jakich wiele. Nic na początku nie zapowiadało zdarzenia, które miało wywrócić mój programistyczny świat do góry nogami. Od początku było wiadomo, że będzie ono intrygujące gdyż miało poruszać zagrożenia, które nie dawno pojawiły się w projekcie. A szczególnie sposób ich rozwiązania. No, ale po kolei. Po wejściu do salki zebrań zajęliśmy swoje miejsca i jak za każdym razem zdaliśmy raport z naszych poczynań. Co zrobiliśmy i jakie chwilowe problemy napotkaliśmy. Nic fascynującego. Ale z nudnego zebranie zaraz zmieniło, w co najmniej tak dramatyczne jak „Teksańska masakra piła mechaniczną” (co prawda nie widziałem tego filmu ale tytuł brzmi wystarczająco dramatycznie aby w ciemno użyć go w porównaniu). Kolega z zespołu zasugerował Lead Developerowi, że nie podobają mu się powtarzające się po sobie struktury IF. Rozmawiałem z nim już o tym już wcześniej. Z kolegą oczywiście! Z leadem się nie rozmawia – dylematy prostego programisty nigdy nie powinny być powodem dyskusji z lead’em. Każda rzecz, którą ja uznam za problem w rzeczywistości jest banalna a lead w tym czasie może tworzyć rozwiązania, o jakich mi się nawet nie śniło ani żadnego filozofowi. Wracając do naszej rozmowy oboje doszliśmy do wniosku, że na pewno da się zrobić to lepiej. Jednak nic konstruktywnego - taka zwykła rozmowa dwóch programistów w kuchni przy herbacie. Ale kiedy odezwał się Lead to aż me serce podskoczyło z radości. Odpowiedzią było: - "Mi też. Nie możemy tego tak zostawić". Poczułem się wspaniale. Jest jednak ktoś na tym świecie, kto uważa, że działający kod to jedno a piękny kod to drugie. Jest ktoś, kto widzi tę różnicę! Wspaniale być w takim zespole. Potem były pytania do członków zespołu o to jakby to najefektywniej rozwiązać. Kiedy przyszła moja kolej to odpowiedziałem, że jeszcze się nad tym nie zastanawiałem - nie była to do końca prawda, bo jak wspomniałem ten temat pojawił się wcześniej. Jednak w związku z tym, że nie przeprowadziłem żadnych testów to pomyślałem, że lepiej będzie usłyszeć opinie innych i potem skonfrontować to z moimi przemyśleniami. Trochę zachowawcze, wiem. No, ale jak się okazało słusznie. Wracając do meritum, jak pisałem wcześniej strasznie ucieszyłem się, że ktoś dostrzega brzydkie fragmenty kodu. I to nie byle kto. Mój Lead. Wspaniale. Po raz pierwszy, i jak się okazało chyba ostatni (w tej pracy), poczułem, że w końcu mam coś do powiedzenia komuś i ktoś w końcu mnie w tej firmie wysłucha. W końcu może stworze coś działającego i ładnego. I nawet będzie na to budżet! A to jest bardzo rzadkie - bo musicie wiedzieć, że w firmie, w jakiej pracuje nie ma budżetu generalnie na nic. Oczywiście teraz przesadzam po przecież jest budżet na Taski. Ale to tyle. Nie ma na testy, tworzenie dokumentacji, ustalenie konwencji nazewniczej, porządną analizę itp. W mojej pracy obowiązuje metodyka Mega Extreme Agile Programming. Wszystkie funkcje (analityka, testera, kodera i audytora kodu) pełni programista. Ponad to czas! U nas koduje się szybko, bo czas to pieniądz. Generalnie jak możesz coś zrobić dobrze w 8 godzin albo nie za dobrze, lub wręcz źle, w 2 godziny to dylemat nie istnieje. Zrób to w godzinę! – na pewno możesz coś pominąć. Może będzie działać trochę gorzej - ale będzie działać! A to jest najważniejsze. Oczywiście później to się mści i większość projektów nie kończy się ani w terminie ani w budżecie, ale to, że to właśnie to może być przyczyną jeszcze nikt nie doszedł. Ale nie wińmy decydentów. Korelacja naprawdę jest cięższa do zauważenia niż by to się wydawało. Jaki człowiek o zdrowych zmysłach stwierdził by, że winą przekroczenia budżetu może być brak testów jednostkowych! Przecież napisanie testu trwa jakiś czas – a jak trwa to kosztuje. Więc zwiększa koszty. Proste! A jeśli w literaturze tematu znajdzie coś innego to… no cóż. Propaganda! Ot, co. Ale po raz kolejny odbiegłem od głównego tematu. Przypomnijmy, że problem był ciąg konstrukcji IF. Kiedy ja już w swoje wyobraźni widziałem jak tworzę wspaniałą rozszerzalną strukturę - czytelną i łatwą w utrzymaniu mój Lead wypowiedział zdanie, które zmieniło moje życie. A przynajmniej etap w życiu, w którym właśnie się znajdowałem. Rzekł on: - ZAMIEŃCIE JE NA SWITCH'A. Wiem, że pewnie nikt mi nie uwierzy, że to wydarzyło się naprawdę. Ale niestety się wydarzyło. Naprawdę! Wróciłem do biurka i zrobiłem jedyną rzecz, jaka mi pozostała. Ściągnęłam na pulpit wzór wypowiedzenia umowy o pracę – wiedziałem, że od tej chwili już nic nie będzie jak dawniej. I jak chłopak porzucający swoją kochankę wielce zabawną jednak głupiutką z łezką w oku zacząłem wypełniać puste pola wpisując po kolei dane swoje i pracodawcy. W następnym poście napiszę o "problemie ifowym" i o tym jak to rozwiązaliśmy - czego oczywiście nikt nie docenił. Bo przecież to żadna sztuka zamienić kilkadziesiąt linii if'ów dziesięcio-linijkową metodą rozszerzoną, która załatwia wszystkie przypadki - nawet te, które jeszcze nie zostały rozpoznane. Phi. Zamień if'y na switch'a! To jest coś, czego świat komercyjnego oprogramowania jeszcze nie widział! June 13 Microsoft Robotics StudioMicrosoft Robotics Studio jest platformą software'ową opartą na Windows mającą umożliwić tworzenie oprogramowania dla robotów, zarówno prawdziwych jak i symulowanych. Program jest kompatybilny z rozwiązaniami sprzętowymi takimi jak np. Lego Mindstorms NXT. Robotics Studio zawiera trójwymiarowe narzędzie do symulowania robotów, środowisko uruchomieniowe zorientowane na usługi, które pozwala na komunikację z różnymi rodzajami sprzętu a także język programowania pozwalający początkującym programistom tworzyć aplikacje przeciągając ikonki. W nowej wersji pojawiło się wsparcie dla Windows Embedded CE 6.0 i Windows Mobile. Silnik symulatora fizyki w środowisku 3D bazuje na silniku PhysX firmy NVIDIA. Tak więc wirtualna rzeczywistość prawie jak naturalna. Teraz za pomocą tego oprogramowania możemy sami realizować fantazje science-fiction nie wychodząc z domu ani nawet nie wydając ani grosza (całe środowisko w wersji Express jest darmowe). Jeśli chcemy poczuć się jak pracownik NASA i eksplorować nowe planety to nic prostszego: Zdjęcie pochodzi z Microsoft Robotics Simulation. Wymodelowany robocik na wymodelowanej planecie. Jeśli uważamy że inżynierowie z NASA nie popisali się z oprogramowaniem Pathfindera to nic prostszego. Możemy stworzyć własnego a teren jego lądowania można ściągnąć z sieci. Jeśli natomiast nie interesują nas wojaże kosmiczne to może by tak zaprojektować (oprogramować) samochód aby nie potrzebował kierowcy. Miasteczko mamy już gotowe. Wystarczy robocik. Jak zapewniają twórcy nawet nie trzeba umieć programować. MSRS posiada graficzny interfejs który pozwala oprogramować robota tworząc coś na wzór schematu blokowego zachowań. Na reklamówkach widnieją dzieci. Choć to akurat stwierdzenie wydaje mi się mocno przesadzone. Programuje od ładnych “kilku” lat i nie nazwał bym tego banalnym – moim zdaniem umiejętność programowania jest konieczna. Nie mówiąc już o tym że “pod spodem” leżą serwisy – a więc niezbyt banalne do oprogramowania w pełni asynchroniczne SOA. Wyzwanie dla każdego (strasznie mądre te dzieciaki z reklamówek muszą być… ciężkie czasy nastały). Jednak najciekawsze jest to, że kiedy już uda nam się to środowisko ujarzmić to wtedy można wyjść ze świata wirtualnego do rzeczywistości i zainstalować każdy z naszych programików na prawdziwym robocie. Chociażby na takim jak ten:
Choć z założenia zabawka, to jednak bardzo zaawansowana. Standardowy NTX posiada:
Dodatkowo można dokupić czujnik wilgoci, temperatury, pH, czytnik kolorów czy też czytnik RFID – oraz wiele, wiele innych bardziej wyszukanych. Co by nie powiedzieć zabawa przednia i bardzo rozwijająca choć co prawda mój pierwszy kontakt z robotyką z MSRS zakończył się porażką. Robocik próbując przemierzyć szybciutko pewien dystans zaczął z chwili na chwilę chybotać się coraz bardziej aż w końcu się wywrócił. Kto by pomyślał że to takie skomplikowane – szczególnie kiedy każde kółko pracuje niezależnie od innych. No ale cóż. To był mały krok dla robocika ale wielki krok dla… mnie chyba :). Myślę, że to dopiero początek ciekawej przygody. Wpis o marnowaniu czasuPrzypadkiem trafiłem na ciekawy wykład Luis von Ahn o “Human computation”. Nie wdając się w szczegóły (choć zachęcam do obejrzenia – tematyka ciekawa a wykład poprowadzony bardzo humorystycznie) chciałbym napisać o jednej rzeczy, która mnie w nim uderzyła. Mianowicie o tym jak wiele czasu ludzie marnują “na głupoty” przy komputerach. Otóż wg statystyk MS w 2003 roku ludzie spędzili na graniu w sapera 9 bilionów godzin (bardzo pasjonująca gra… ;). Trzeba wziąć pod uwagę, że są to zarejestrowane godziny – a wiec na pewno dużo mniej niż w rzeczywistości. Aby uzmysłowić sobie jak wiele to jest to wybudowanie Empire State Building zajęło 7 milionów godzin… czyli 6.8 godziny gry w sapera (średnio). Ale to tylko jakiś budynek. Weźmy coś dużego! Kanał Panamski budowany 20 milionów godzin… a więc mniej niż jeden dzień gry w sapera! Jak sobie pomyśle co ludzkość by osiągnęła nie tracąc czasu na takie rzeczy to aż mnie ciarki przechodzą. Nie wiem jak Wy czytelnicy ale ja siadam od razu to twórczej pracy… zaraz po tym jak zagram w sapera. TYLKO raz oczywiście! :) June 06 Rodem z filmów science-fictionMS opracował technologie rodem z filmów science-fiction. Projekt Natal bo onim tu mowa.Zapraszam do filmiku na YouTube: We wspaniałych czasach przyszło nam żyć. Można jeszcze zajrzeć na http://www.xbox.com/en-US/live/projectnatal/. |
|||||||||||||||||||||||||
|
|