wtorek, 27 marca 2012

i++ czy i--

Chciałem sprawdzić czy pętla z i++ oraz i-- są sobie równe. Dlatego zrobiłem mały test:
            //Test dla i++
            Stopwatch s1 = new Stopwatch();
            s1.Start();
            for (int i = 0; i < lim; i++)
            {
                //code
            }
            s1.Stop();
            Console.WriteLine("Time for i++: {0} ms",
                    s1.ElapsedMilliseconds);
            //Test dla i--
            Stopwatch s2 = new Stopwatch();
            s2.Start();
            for (int i = lim - 1; i >= 0; i--)
            {
                //code
            }
            s2.Stop();
            Console.WriteLine("Time for i--: {0} ms",
                    s2.ElapsedMilliseconds);
Dodałem możliwość powtarzania tego testu. Obliczenia powtarzałem z 10 razy, aby wyniki były bardziej wiarygodne.
           int lim = int.MaxValue; //2147483647

            long time1 =0, time2=0;
            List<long> gList1 = new List<long>();
            List<long> gList2 = new List<long>();

            for (int i = 0; i < 10; i++) //powtarza 10 razy
            {
                TestFor(lim, ref time1, ref  time2);
                gList1.Add(time1);
                gList2.Add(time2);
            }
            var avgPlus = gList1.Average();
            var avgMinus = gList2.Average();
            var maxPlus = gList1.Max();
            var maxMinus = gList2.Max();
            var minPlus = gList1.Min();
            var minMinus = gList2.Min();

            Console.WriteLine(new { avgPlus, maxPlus, minPlus }); 
            // wyświetla wyniki dla i++

            Console.WriteLine(new { avgMinus, maxMinus, minMinus });
            // wyświetla wyniki dla i--

Jednostki w przedstawionych wynikach są liczone w milisekundach.
1) Brak operacji w pętli.
{
avgPlus = 5084,
maxPlus = 5178,
minPlus = 4998
}
{
avgMinus = 6747,
maxMinus = 6828,
minMinus = 6677
}

Operacja i++ jest szybsza. Czasy dla operacji i++ są około 1,7 sekundy mniejsze niż dla operacji i--.

2) Prosta operacja zawarta w pętli.
            int iter = 0;
            iter++;

{
avgPlus = 6368,
maxPlus = 6494,
minPlus = 6319
}
{
avgMinus = 5472,
maxMinus = 5600,
minMinus = 5446
}
Wyniki są odwrotne do wyników z poprzedniego testu. W tym przypadku operacja i-- jest szybsza. Ciekawe jest, że wyniki dla prostej operacji w pętli są lepsze niż dla pętli bez operacji.

3) Operacja na stringu.
            "ab".Replace('a','b');

{
avgPlus = 127846,3,
maxPlus = 136981,
minPlus = 125358
}
{
avgMinus = 125099,2,
maxMinus = 131357,
minMinus = 123913
}
Badanie potwierdza wnioski z punktu 2, że operacja i-- jest szybsza od i++.

4) Skoro była inkrementacja w pętli to sprawdziłem dekrementacje.
            int iter = 0;
            iter--;

{
avgPlus = 6237,4,
maxPlus = 6260,
minPlus = 6225
}
{
avgMinus = 5337,6,
maxMinus = 5383,
minMinus = 5298
}
Badanie potwierdza wniosek z punktu 2. Operacja dekrementacji jest szybka od operacji inkrementacji.

5) W ciele pętli jest tworzenie obiektu.
{
avgPlus = 52622,
maxPlus = 54548,
minPlus = 51284
}
{
avgMinus = 51557,1,
maxMinus = 55958,
minMinus = 50173
}
Ostatnie badanie potwierdza, że operacja dekrementacji jest szybsza od operacji inkrementacji.

Jak na razie nie wiem dlaczego tak się dzieje. Gdyby ktoś wiedział dlaczego operacja dekrementacji jest szybsza, to proszę o kontakt.

poniedziałek, 26 marca 2012

Szybki kod dla stron

Natrafiłem na filmik przedstawiający sposoby przyspieszania ładowania stron internetowej.



A oto lista 14 zasad:
1) Zmniejsz liczbę żądań HTTP Requests
2) Stosuj Content Delivery Network
3) Dodaj wygaśnięcie w nagłówku ( header expires )
4) Stosuj komponenty GZip
5) Arkusze stylów wstawiaj w nagłówku
6) Wstawiaj skrypty na końcu dokumentu
7) Unikaj wyrażeń w css
8) JS i css zawarte w plikach
9) Zmniejsz liczbę odwołań do DNS
10) Zmniejsz wielkość pliku z js i css
11) Unikaj przekierowania
12) Usuń duplikacje
13) Ustaw ETags dla swojej strony
14) Ustaw cache dla AJAX

Więcej o innych sposobach przyspieszania strony można znaleźć tutaj oraz tutaj,a do sprawdzenia tych reguł można zastosować YSlow. To narzędzie polecał m.in. Scott Hanselman.

Sztuczka z kolorami

Wcześniej pisałem o Richardzie Wisemanie. Tym razem chciałbym przedstawić jego sztuczkę z kolorami :)



wtorek, 20 marca 2012

Matryca decyzji i historia Arnolda

Większość ludzi jakich znam określa swoje decyzje na podstawie tego czy dana czynność jest przyjemna dla nich czy nie. Dajmy na to, że masz do wyboru ponad 3 godziny siedzenia i oglądania telewizora, albo ćwiczenie przez 3 godziny. Jeżeli wybór decyzji byłby uzależniony od tego czy będziesz miał z tego przyjemności, to na pewno wybrałbyś siedzenie przed telewizorem. Ale zupełnie inaczej wybierają ludzie, którzy myślą w kategorii pożyteczności dla siebie i innych. Jeżeli chciałbyś schudnąć parę kilogramów to wiesz o tym, że korzystniejsze dla ciebie jest ćwiczenia niż siedzenie przed telewizorem. Najlepiej by było gdyby taka czynność był przyjemna i pożyteczna. Jednak najczęściej tak nie jest. Jeżeli chcemy osiągną dany cel, to musimy kierować się decyzjami pożyteczności. A jeżeli coś dla nas jest nieprzyjemne, to staramy się zmienić nastawienie.

matryca decyzji




Arnold Schwarzenegger jest osobą, która postępuje zgodnie ze swoim celem, niezależnie od tego czy jego decyzja była łatwa czy nie. Starał się zmienić swoje odczucia z nieprzyjemnej w przyjemną czynność. W taki sposób robił to co lubił i osiągał sukcesy. Dzięki temu jest uważany za najpopularniejszego kulturystę, ikonę amerykańskiego kina akcji oraz senatora najlepszego stanu USA. Kiedy był młody, przemierzał 12 kilometrów na siłownię. Był krytykowany za to, że inaczej ćwiczy, za dużo czasu spędza na siłowni, mógłby zająć się czymś innym, itd. Arnold był zmotywowany i robił swoje. Podczas pobytu w wojsku były organizowane zawody Junior Mr. Europe, na które Arnold chciał pójść. Opuścił koszary bez pozwolenia i wygrał mistrzostwa. Późnej wygrał 3 razy z rzędu Mr. Universe. Stał się najmłodszym zwycięzcą tych zawodów ( w wieku 20 lat). Po kulturystyce chciał zostać aktorem. Dano mu szansę w filmie Herkules w Nowym Jorku, ale film okazał się totalną klapą. Ludzie z całego świata zaczęli naśmiewać się z niego, że jest słabym aktorem oraz nie potrafi mówić po angielsku. Arnold tym razem też nie dał za wygraną i zapisał się na kurs baletu, pobierał nauki z dykcji oraz rozmawiał z innymi aktorami. Aż w końcu stał się największą gwiazdą filmów akcji. Mając popularność chciał zostać senatorem najliczniejszego stanu. Pracował ciężko, aż w końcu osiągał swój cel. Arnold jest żywym przykładem osoby kierującym się decyzjami pożyteczności oraz wychodzącym poza swoją strefę komfortu.

Ciacho za ciacho

2 razy w roku w kościele dominikanów jest organizowana akcja charytatywna o nazwie "ciacho za ciacho". Akcja jest bardzo prosta. Pieczesz placek w sobotę, zostawiasz w kościele, a w niedzielę po mszy idziesz na krużganki i kupujesz swoje ciacho (oczywiście możesz też inne ciasta kupić). Jeśli nie umiesz piec placków (tak jak ja) to wystarczy, że kupisz ciacho.


Nie pisałbym o tej akcji, gdyby nie możliwość zakupienia książek za bardzo niską cenę. W tym roku zaskoczyła mnie książka "Applied XML Programming for Microsoft .NET" za 15 zł oraz Building Web Solutions with ASP.NET and ADO.NET również za 15 zł. Były też inne książki z wydawnictwa MS Press za tak niską cenę. Ceny książek zaczynały się od 1zł. Na kiermasz przyszedłem po godzinie 20tej, więc te ciekawsze książki były już kupione. Były książki wydane w tym roku jak i książki mające z 50 lat. Kiedyś byłem w organizacji i znalazłem książkę z 1890 roku. Bardzo żałuje, że nie kupiłem jej.

Podsumowanie SFI 2012

Studencki Festiwal Informatyczny już się zakończył, więc krótko opisze moje wrażenia z tego festiwalu. O SFI pisałem już wcześniej. Jako stary (od 2006 roku) uczestnik festiwalu, chciałbym opowiedzieć te najciekawsze tegoroczne prelekcje.



Najbardziej podobała mi się prezentacja Bruce Lawson pod tytulem "How to destroy the web". Bruce pracuje dla Opery, w wolnych chwilach tworzy muzykę oraz ogląda koty na youtubie. Na swoim pokazie opowiadał o tworzeniu nowych niekompatybilnych standardów, różnic między przeglądarkami oraz jak zmonopolizować technologię. Najbardziej spodobała mi się jego charyzma i lekkość prezentacji.
Na drugim miejscu z najlepszych prelegentów SFI uplasował się Marcin Kosedowski. Marcin opowiadał o pracy freelancera (praktyczne kwestie oraz jego przygodzie z pracą na kontraktach). Sposób opowiadania Marcina był przyjemny i prosty.



Bardzo mi się podobała prelekcja Przemka Biecka o wizualizacji danych. Sprawozdanie Przemka z festiwalu można przeczytać z jego bloga. Baza danych RavenDB była przedstawiana przez Michała Śliwonia z firmy ABB. Prezentacje Michała można zobaczyć pod tym linkiem. Do ciekawszych prezentacji należałoby wyróżnić prezentację Marcina Jaśkiewicza z istv. Bardzo żałuję, że nie byłem na prezentacji Tadeusza Golonki.

Jeżeli chodzi o lokalizacje SFI to organizatorzy wybrali bardzo dobre miejsce. Na stronie Auditorium Maximum jest możliwość wirtualnego zwiedzania.



czwartek, 15 marca 2012

Książka "Zarządzanie projektami informatycznymi"

To jest stary wpis, ale nigdy nie miałem czasu na dokończenie oraz opublikowanie go. Ten post będzie o wskazówkach zawartych w książce "Zarządzanie projektami informatycznymi. Subiektywne spojrzenie programisty" napisanej przez Joel Spolsky. Spolsky od 2000 roku prowadzi bloga (pomysł nazwy mojego bloga pochodzi od tego Pana), był jednym z twórców Visual Basic for Applications w Excelu, jest właścicielem firmy Fog Creek oraz CEO stackoverflow.com. Książkę napisał w 2005 roku. Przedstawiając Ci te rady będę bazował na moich starych notatkach, jakie zrobiłem po przeczytaniu tej książki.



Chciałbym wymienić 12 najważniejszych rad Spolskyego odnoszących się do prowadzenia projektu informatycznego:

1) Mechanizm kontroli wersji
System kontroli wersji jest już podstawą. Tworzenie oprogramowania nie jest rozgrywką jednoosobowa, ale jest grą zespołową.

2) Kompilacja całego systemu w jednym kroku
Jeszcze pamiętam jak w pewnej firmie musiała być wyznaczona osoba, która mogła przekompilować kod i wysłać na serwer produkcyjny (testowy). Taki proces mógł zajmować nawet do 2 godzin, więc bardzo rzadko dokonywano publikacji oprogramowania.

3) Codzienna kompilacja
Proces codziennej kompilacja jest nazywany Continuous Integration. Do automatyzacji kompilacji może przydać się CC.NET




4) Baza danych dla wykrytych błędów

5) Usuwanie błędów przed napisaniem nowego kodu

6) Realizacja projektu zgodnie z wcześniejszym planem

7) Specyfikacje
Natura programisty nakazuje interpretować jednoznaczne wymagania tak, aby uprościć wymagania. Często nie jest to coś, czego chciałby klient.

8) Właściwe warunki pracy dla pracowników
W ciszy jest łatwiej skoncentrować za zadaniu. Bardzo dobrą praktyką w pracy, w pokoju składających się z kilku osób jest ustalenie cichych dni. Są to dni, w których nie jest puszczana muzyka, nie ma luźnych pogawędek o polityce oraz nie przesyła się śmiesznych linków z różnych serwisów.

9) Najlepsze narzędzia są wykorzystywane w pracy
Nie wyobrażam sobie dużej aplikacji napisanej w zwyczajnym edytorze tekstu, czy IDE bez możliwości refaktoryzacji kodu. Genialnym dodatkiem do Visual Studio jest ReSharper. Możesz pobrać testową wersję dodatku, ale uważaj. Raz spróbuje i nie będziesz chciał wrócić do starego IDE.

10) Wykorzystanie z pomocy testerów

11) Kandydaci na stanowisko muszą napisać próbny kod

12) Korytarzowe testy użyteczności
Testy korytarzowe polegają na tym, że napotkaną pierwszą osobę na korytarzu i prosi się ją o przetestowanie i wyrażenie swojej opinii na temat systemu. Każdy twórca oprogramowania uważa, że jego system jest łatwy w obsłudze i intuicyjny.

Wiele ludzi uważało wskazówki Spolskyego za nierealne do spełnienia. W dzisiejszych czasach dobre firmy postępują zgodnie z tymi radami, aby wytwarzać najlepsze oprogramowanie jakie jest możliwe. Nie opisałem wszystkich punktów, gdyż są one oczywiste. Książka Spolskyego jest świetnie napisana i bardzo praktyczna (nawet na dzisiejsze czasy). Moim zdaniem jest to bardzo dobra książka o zarządzaniu projektami dedykowana dla programisty.

piątek, 9 marca 2012

Flock się skończył

Projekt Flock był genialną przeglądarką internetową na silniku chromium dedykowany dla osób prowadzących blog lub korzystających z serwisów społecznościowych takich jak: MySpace, Facebook, YouTube, Twitter, Flickr, Blogger, Gmail, Yahoo! oraz WordPress.
W styczniu 2011 roku Flock Inc. został kupiony przez Zynga, a wsparcie dla Flock zakończyło się 25 kwietnia 2011. Portal Flock.com przestał istnieć. Twórcy zalecają przeniesienie się na Chrome lub Firefox. Starą wersję (2.6.1) można jeszcze pobrać z tego linka.

czwartek, 8 marca 2012

SFI

Studencki Festiwal Informatyczny jest 3 dniowym spotkaniem pasjonatów technologii w Krakowie. W tym roku festiwal odbywa się w dniach 8 - 10 marca 2012 w Auditorium Maximum Uniwersytetu Jagiellońskiego. Na spotkaniu można dowiedzieć się o różnych ciekawych programach, technologiach i metodach. Już nie jestem studentem, ale byłem na dzisiejszym spotkaniu. Niektóre prezentacje były ciekawe, a z innymi było ciężko. Dzisiaj jest pierwszy dzień, wieć ciężko coś więcej powiedzieć o tej edycji. Poczekamy, zobaczymy.

A to co najlepsze jest w SFI to darmowe i słodziutkie krówki :)

środa, 7 marca 2012

Jak przyspieszyć kodowanie cz.3 ( AroLibraries )

Od ponad 2 lat rozwijam projekt (AroLibraries) w którym zapisuje wszystkie metody rozszerzalne ( extension methods ).


AroLibraries to biblioteka zawierająca rozwiązania, które są pomocne przy wytworzeniu oprogramowania. Jednym z podstawowych rozwiązań to wykorzystanie rozszerzonych metod. Takie rozwiązanie pozwala na: - ukrycie części implementacji - czytelniejszą składnię - wielokrotne wykorzystanie tego samego kodu
Zamiast za każdym razem pisząc:
    Bitmap image = new Bitmap("picture.bmp");
    Stream memoryStream = new MemoryStream();
    image.Save(memoryStream, ImageFormat.Bmp);
    byte[] bytes = new byte[memoryStream.Length];
    memoryStream.Position = 0;
    memoryStream.Read(bytes, 0, (int)memoryStream.Length);
    
    memoryStream.Close();
    var binary = new Binary(bytes);
   return binary;

Możemy zapisać w formie:
    Bitmap image = new Bitmap("picture.bmp");
    image.ToBinary();
Kod z wykorzystaniem extension methods jest zdecydowanie czytelniejszy. Poniżej przedstawiam parę ciekawszych rozwiązań za pomocą AroLibraries:
9.8F . IsBetween(9, 10); 
//określa czy liczba 9.8 jest w przedziale 9 i 10

DateTime.Now.IsWeekend(); 
// sprawdza czy dzisiaj jest weekend

DateTime.Now.ToSecondsFromEpoch(); 
// data w formacie Epoch

DateTime.Now.EqualsToHour(new DateTime(1986, 03, 29, 12, 0, 0));  
//sprawdza czy teraz jest ta sama godzina

"4AAB7F67-A898-442a-884A-364411D584EC".IsValidGuid();
 //sprawdza czy string jest w formacie GUDI

"mymail@zzzzzzz.com". IsValidEmailAddress(); 
//sprawdza czy string jest w formacie e-maila

string words = "Some words about Library";
words.Reverse(); 
// odwraca string  ("yrarbiL tuoba sdrow emoS")

words.GetRightSideOfString(13); 
// zwraca prawą stronę stinga "about Library"

words.CountWords(); 
//liczy wyrazy

words.ReplaceOnce("a",""); 
//zamienia tylko pierwsze wystąpienie w tekście

words.ToMd5(); 
//zwraca skrót MD5 z tekstu


new Exception("0", new Exception("1", new Exception("2", new Exception("3"))))
. GetMostInner(); 
//zwraca najbardziej wewnętrzny wyjątek  (Exception nr "3")

var numbers = 1.IterateTo(10);
//iteruje od 1 do 9 

numbers.IndexOf(6); 
//zwraca index liczby 6
numbers.Repeat(2, true); 
//{1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9}

numbers.Repeat(2, false); 
// {1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9}

numbers.Shuffle();
 //miesza elementy

numbers.Swap(1,2); 
//zamienia miejscami element nr 1 z elementem nr 2

numbers.ToString(";");
 // zwraca string elementów oddzielonymi średnikiem ( "1; 2; 3; 4; 5; 6; 7; 8; 9")


9.In(numbers); 
//sprawdza czy liczba 9 jest w danej kolekcji

9.ToMonthName("Styczeń");
 //zwraca nazwę miesiąca

'a'.IsVowel(); 
//sprawdza czy jest samogłoską

var persons = new[]
{
new Person {
           FirstName = "Arek", 
           LastName = "XYZ",
           Age = 26},
};
persons.ToDataTable();    
// zmienia kolekcje w tabelę

persons.OrderBy(x => x.Age); 
//sortuje po danym polu


Bitmap image = new Bitmap("picture.bmp");
image.ToBinary();  
//konwersja do typu Binary

image.SaveJpeg("pic.jpg"); 
//zapisuje do formatu jpeg

image.Fill(Color.Black);
 //zwraca obrazek cały pomalowany na czarno

image.IsPixelInImage(-1, 100); 
// sprawdza czy można pobrać pixel o podanych współrzędnych  

image.GetPixels(); 
// zwraca wszystkie kolory na obrazku

image.ToByte(); 
//konwersja do byte[]

image.ToByte().OpenBytesAsFile(".bmp"); 
// otwiera plik w zewnętrznym edytorze


TextBox tb= new TextBox();
tb.WriteLine("Text"); 
//pisze po textboxie

DirectoryInfo di= new DirectoryInfo("c:");
di.GetDirectorySize(); 
//zwraca wielkość katalogu

Stream stream= GetStream();
stream.SaveToFile("Text.txt"); 
//zapisuje stream do pliku

Stream textStream= new MemoryStream();
stream.CopyStreamTo(textStream); 
//kopiuje do nowego źródła
           

XmlNode node = GetXmlNode();
node.ToXElement(); 
//zwraca XElement

Projekt jeszcze nie jest w pełni stworzony. W przyszłości będę chciał stworzyć do niego testy jednostkowe. Liczne extension methods można znaleźć pod tym linkiem, a kod źródłowy projektu można pobrać z portalu codeplex.

Zombie Font

Natrafiłem na bardzo śmieszną, a zarazem przerażającą czcionkę na portalu zombiefont.com, na którym można wygenerować tekst za pomocą zombies. Wygenerowałem moje imię i nazwisko i pomyślałem sobie, żeby wygenerować ewolucje mojego podpisu.



Poniżej przedstawiam cały alfabet (niestety bez polskich znaków).




Podobne możliwości udziela portal e-zombie.com, który również może generować połamane zombies.



wtorek, 6 marca 2012

StaticHolder

W projektach bardzo często jest potrzebny obiekt, który w programie może zapamiętać stan paru obiektów. Wymyśliłem klasę przetrzymującą dany stan obiektu. Jest to statyczna klasa z jednym polem, który przetrzymuje stan.
    public static class StaticHolder
    {
        public static Object Hold { get; set; }
    }

    public static class StaticHolder<T1>
    {
        public static T1 Hold { get; set; }
    }

    public static class StaticHolder<T1, T2>
    {
        public static T1 Hold { get; set; } 
    }

    public static class StaticHolder<T1, T2, T3>
    {
        public static T1 Hold { get; set; }
    }
Do podstawowej klasy zostały stworzone generyczne typy. Zastosowanie StaticHolder przedstawione jest w tym kodzie:
StaticHolder.Hold = 1; 
//zapisane do obiektu 1

StaticHolder.Hold = "Text 1"; 
//zamiast 1 jest "Text 1"


StaticHolder<int>.Hold = 2; 
StaticHolder<string>.Hold = "Text 2"; 
//jest rozróżnienie między int a string


StaticHolder<int, int>.Hold = 3;
StaticHolder<string, int>.Hold = "Text 3";


bool equals = 
StaticHolder<int, string>.Hold
.Equals(StaticHolder<int, int>.Hold);
//false, StaticHolder<int, string> != StaticHolder<int, int>
// drugi typ generyczny wprowadza dodatkowe rozróżnienie

equals = 
StaticHolder<string, int>.Hold
.Equals(StaticHolder<string, int>.Hold);


// rozróżnienie dla poniższych StaticHolder
StaticHolder<int, int>.Hold = 4;
StaticHolder<int, string>.Hold = 5;
StaticHolder<int, decimal>.Hold = 6;
StaticHolder<int, EncodingInfo>.Hold = 7;
StaticHolder<int, List<int>>.Hold = 8;
StaticHolder<int, List<string>>.Hold = 9;

Nie wiem czy taki tok myślenia już ktoś nazwał i opisał. Możliwe, że jest on nazwany pod inną nazwą. Ja na ten mechanizm nazywam "StaticHolder Pattern". Z poniższego źródła można pobrać kod:

poniedziałek, 5 marca 2012

Metoda wypełniająca dla testów

Problem jaki napotykam w trakcie testowania aplikacji jest ciągłe wypełnianie tych samych pól, tymi samymi danymi. Aby zautomatyzować dany proces wystarczy dodać metodę wypełniającą.
Do metody wypełniającej dane (np. w formularzu) dodaje się atrybut Conditional("DEBUG"). Jeżeli flaga DEBUG nie jest ustawiona to metoda jest omijana w produkcyjnej binarce. Do tej metody dodatkowo dodaje warunek czy debugger jest podłączony. Debugger możne być podłączony w trybie Debug oraz Release. Dobrę praktyką jest dodanie informacji do okna Output z jakiej metody zostało dokonane wypełnienie, pisanie nazw tych metod z prefiksem "DEBUG_" oraz ustawienie dostępności na private.
Poniższy kod przedstawia ten mechanizm:
[Conditional("DEBUG")]
private void DEBUG_YourFillingMethod() //hack: Debug
{ 
    if (Debugger.IsAttached)
    { 
        Debugger.Log(0, this.ToString(), System.Reflection.MethodBase.GetCurrentMethod().Name);
        //todo: your filling code
    } 
} 


Dla aplikacji ASP.NET można zastosować HttpContext.Current.IsDebuggingEnabled.

Mario + Portal = Mari0


Kto nie pamięta gry Mario. Sympatyczny hydraulik z wąsikiem :) Jeszcze mi się łezka kręci jak wspominam kiedy na komunie dostałem pegasusa z tą grą. Najlepsza gra wszech czasów.
Gra Portal powstała w 2007 i została uznana z innowacyjną z powodu tworzenia portali na płaskich powierzchniach, które pozwalają na swobodne podróżowanie. Portal jest grą logiczną z perspektywy first person shooter.



Z połączenia tych dwóch gier powstał Mari0.



Oprócz portali bardzo mi się podoba, że w przyszłości będzie możliwość zagrania z drugą osobą przez internet.


Powodzenia przy uwalnianiu księżniczki!!! :)

Wzorzec stanu dla stron

W tym poście chciałbym przedstawić moją implementację State Pattern dla stron internetowych w ASP.NET. Zakładam, że każda strona ma dokładnie jeden stan. Wzorcem chciałbym rozwiązać podany scenariusz: Uruchamiamy stronę startową (Page 1). Z tej strony chcemy przejść do strony Page 3. Przejście jest uzależnione od spełnienia warunku (Condition). Jeżeli warunek nie jest spełniony to przechodzimy do strony Page 2, a w przeciwnym przypadku przechodzimy do strony Page 3. Również ze strony Page 2 można przejść do Page 3. Schemat działania stron przedstawiony jest poniżej:

Graficzna implementacja wzorca stanu dla stron jest zawarta w poniższym schemacie:
Klasa PageContext zawiera różne stany oraz parametry z danej strony. Klasa abstrakcyjna PageState deklaruje metodę Handle(), która jest definiowana przez konkretny stan. Klasa bazowa zawiera nazwę pliku ze stroną (np. Page1.aspx) w polu PageName. W każdej ze stron (Page*.aspx) zdefiniowane jest zdarzenie odpowiadające za zmianę stanu (przejście do innej strony). Dla strony Page1.aspx definicja wygląda następująco:
        protected void GoToNextPage(object sender, EventArgs ea)
        {
            var thisContext = new PageContext(new PageState1()) 
                                { IsChecked =  Condition1.Checked};
            thisContext.Request();
            this.Response.Redirect(thisContext.State.PageName);
        }
Klasa PageContext ma zdefiniowaną metodę Request(), która dla danego stanu wywołuje metodę Handle(). Cały przykład można pobrać z tego pliku: