Category Archives: Inżynieria oprogramowania

Hoisting w JavaScript

Na początek zagadka: jakie komunikaty wyświetli poniższy kod?

Odpowiedź brzmi, oczywiście: undefined!

wat

W przeciwieństwie do jezyków takich jak C czy C#, nie każdy blok kodu definiuje zakres zmiennej, a jedynie funkcja. Nie ma przy tym znaczenia, w którym miejscu funkcji zmienną zadeklarujemy – będzie ona dostępna w całej funkcji, także przed deklaracją. Dlatego alert(x) nie zobaczy zmiennej globalnej, tylko lokalną. I zobaczy undefined dlatego, że co prawda zmienna jest już zdefiniowana, ale przypisanie do niej wartości ma miejsce później.

Powyższy kod będzie więc równoważny z takim:

A zatem – można powiezieć, że deklaracje zmiennych są jakby “wyciągane” (ang hoisted) na początek funkcji.

Ot, jedno z wielu dziwactw JavaScriptu.

Jaki z tego morał? Dobrą praktyką jest deklarowanie wszystkich zmiennych w jednej instrukcji var na samym początku funkcji. Taką też regułę posiada JSLint (i jego fork, JSHint), narzędzie sprawdzające styl kodu, którego używać powinien każdy programista JS.

Co się zmienia, co się nie zmienia

Jak rozplanować poszczególne części systemu, klasy, moduły, komponenty? Mnóstwo można by tu napisać, ale dziś tylko jedna zasad: oddzielaj to co się zmienia od tego, co się nie zmienia.

Każda nietrywialna aplikacja będzie się zmieniać. Będą zmieniać się wymagania, bo zmienia się wizja albo sytuacja klienta. Jak więc poukładać klocki tak, żeby zmiana wymagań nie wiązała sie z rozsypaniem całej budowli?

Zidentyfikować zawczasu, jaka część funkcjonalności będzie podatna na zmiany i oddelegować ją do osobnej klasy. Z projektu wyłonią się 3 obszary:

  1. Niezmiene serce systemu. Ten kod może się nie zmieniać całymi latami. Można raz napisać testy i one cały czas będą przechdzić, bo nic się nie zmienia.
  2. Polityki, używając terminologii DDD. Ten kod będzie sie zmieniał często. Klient wymyślił nowy sposób naliczania rabatu? Super, napiszmy nową klasę RebatePolicy, przetestujmy ją, a starą wyrzućmy. Wszystko inne działa, jak działało.
  3. Plumbing code. Niezbyt fascynujący kod, którego zadaniem jest sklejanie (1) i (2) w działający system.

Łatwo powiedzieć, trudniej zrobić. Cała sztuka w umiejętności zgadnięcia, co może się zmieniać i ukryciu tego pod niezmiennym interfejsem. Odwołując się do wspomnianego RebatePolicy – co metody tej klasy powinny mieć na wejściu? Cenę, cały produkt, historię użytkownika, jakiś kod rabatowy? A na wyjściu? Nową cenę, kwotę rabatu, procent? Nie wystarczy nam wiedzieć, że algorytm rabatu będzie się zmieniał. Trzeba jeszcze tak zaprojektować moduł, żeby zmiana logiki nie wymuszała zmiany API. Cóż nam po wydzieleniu rabatów do osobnej klasy, jeżeli jej zmiana będzie wymagała zmian także w klasach, które jej używają? Tych, które miały być niezmienne!

Polityki mogą się zmieniać, ale ich interfejsy powinny być stabilne.

eXtensively Messed up Language

Na dzisiaj przygotowałem zagadkę:
<ns2:element
    
xmlns="http://orb.net.pl/ns/namespace1"
    
xmlns:ns2="http://orb.net.pl/ns/namespace2"
     atrybut="i'm so confusing"
/>

Pytanie brzmi: do jakiej przestrzeni nazw należy atrybut?

a) do http://orb.net.pl/ns/namespace1, gdyż jest to domyślna przestrzeń nazw w tym kontekście

b) do http://orb.net.pl/ns/namespace2, gdyż jest to przestrzeń nazw elementu, do którego należy atrybut

c) do żadnej… bo tak

CSS image map na przykładzie JDM

W HTML-u były znaczniki <map> oraz <area> które pozwalały tworzyć linki we fragmentach obrazka. Mechanizm ten nie satysfakcjonował specjalnie ludzi, którzy rozumieją sens separacji treści od prezentacji, dlatego wymyśla się różne sposoby, aby analogiczny rezultat osiągnąć za pomocą samego tylko CSS.

Oto, jak zrealizowałem mapkę z propozycjami wakacyjnymi na stronie Xaverianum.

Zacznijmy od kodu XHTML:

<h1 id="homepage-map">A co z wakacjami?</h1>
<ul id="homepage-map">
 <li id="jdm">
  <a href="/wakacje/jdm" title="Jubileuszowe X Jezuickie Dni Młodzieży (JDM) w Świętej Lipce na Mazurach">
   <strong>Jezuickie Dni Młodzieży</strong>
   <small>w Świętej Lipce</small>
   <span></span>
  </a>
 </li>
 <li id="pielgrzymka">
  <a href="/wakacje/pielgrzymka" title="Pielgrzymka parafialna (pomarańczowa trójka)">
   <strong>Pielgrzymka</strong>
   <small>na Jasną Górę</small>
   <span></span>
  </a>
 </li>
 <li id="bialy">
  <a href="/wakacje/bialy" title="26. obóz adaptacyjny duszpasterstw akademickich Wrocławia i Opola w Białym Dunajcu w Tatrach">
   <strong>Obóz adaptacyjny</strong>
   <small>w Białym Dunajcu</small>
   <span></span>
  </a>
 </li>
</ul>

Mamy zatem zwykłą listę zawierającą linki, ze zwykłymi tekstami. Jedyne, co tutaj szczególne, to pusty znacznik <span/> – w idealnym świecie niepotrzebny, zaś w świecie wciąż zamieszkałym przez Internet Explorera 7 i starsze – konieczne, aby osiągnąć zamierzony cel.

W tle listy wstawmy obrazek z mapą Polski, używając atrybutu padding przesuńmy napisy, żeby jej nie zasłaniały i – uwaga – włączmy pozycjonowanie relatywne (przyda się za chwilę).

ul#homepage-map {
position: relative;
margin: 0; padding: 140px 0 0 0;
background: url(../images/homepage-map.png) no-repeat left top;
height: 460px;
}

Elementom listy <li/> ustawmy ładne tła.

#jdm {
background: url(../images/jdm-bg-hover.png) no-repeat;
}

Podobnie można ustawić tła linkom (które mają wyświetlanie blokowe i wypełniają cały obszar <li/>).

#jdm a {
background: url(../images/jdm-bg.png) no-repeat;
}

Teraz pierwsze czary-mary: Tło pod <li/> będzie tym “podświetlonym”, zaś tło pod <a/> – tym “niepodświetlonym”. Jesli dodamy teraz

#jdm a:hover {
background: none;
color: #503830;
}

to po najechaniu myszką, tło pod <a/> będzie znikać, ozsłaniając tło pod <li/>. Dzięki tej prostej sztuczce – przeglądarki pobierać będą oba obrazki od razu. Gdybyśmy ustawiali “zwyczajnie” – jedno tło dla a, a drugie dla a:hover, te drugie pobrałoby się dopiero w momencie wskazania myszką linka i przez to nie wyświetliło natychmiast.

Przejdźmy jednak do istoty zagadnienia. Tajemniczemu elementowi <span/> nadajmy pozycję absolutną i ustawmy go we właściwym miejscu mapki:

ul#homepage-map span {
display: block;
position: absolute;
cursor: pointer;
}
#jdm span {
left: 375px;
top: 160px;
width: 120px;
height: 140px;
}

Zwróć teraz uwagę, drogi czytelniku, względem czego ten span będzie się pozycjonował. Otóż, względem najbliższego przodka, który ma pozycjonowanie relatywne lub absolutne. Zarówno <a/>, jak i <li/> mają pozycjonowanie statyczne, a więc szukając punktu odniesienia, <span/> trafi na <ul/>.

Ot, cała filozofia. Działający przykład tego rozwiązania znajdziecie na stronie promującej Jezuickie Dni Młodzieży, na które – swoją drogą – serdecznie zapraszam.

Na koniec nie przetestowana idea: teoretycznie, można się pozbyć tego elementu <span/>, który zaśmieca kod i zamiast niego zastosować pseudoelement a::after. Gdyby tylko IE7 zniknęło z rynku…

Budzik

Pobierz programOd mniej więcej roku jako budzika używam komputera. A dokładniej programu WakeupOnStandBy. Jest to mały programik, który potrafi wybudzić komputer ze stanu uśpienia bądź hibernacji (to drugie nie na każdym komputerze) i uruchomić zadany program. Np. odtwarzacz multimedialny. Aplikacja ma bardzo dużo opcji co daje jej wielką uniwersalność. Ale z drugiej strony, ja potrzebowałem tylko budzika, a nie kombajnu.

W końcu ten nadmiar przycisków, checkboksów, pól edycyjnych mnie zirytował i postanowiłem napisać sobie budzik samemu. Taki, który będzie robił dokładnie to, czego potrzebuję – budził mnie – i nic więcej.

Aplikacja jest banalnie prosta: na górze okna mamy TimePicker z biblioteki AvalonControlsLibrary w który wprowadzamy pożądaną godzinę budzenia. Aplikacja domyślnie ustawia to pole na za 8 godzin i 10 minut. 8 godzin, bo tyle snu potrzebuje człowiek, a te 10 minut to zapas na jakieś czynności wykonywane tuż przed snem, typu gaszenie świateł, wyłączanie różnych rzeczy, modlitwa, kładzenie się, zasypianie… Pod godziną jest wielki przycisk z budzikiem – wystarczy go kliknąć i można uśpić komputer. O zadanej godzinie komputer sam się obudzi i zagra utwór, którego wybór umożliwia drugi przycisk. Wybór jest zapamiętywany w pliku konfiguracyjnym, więc nie trzeba używać tego przycisku za każdym razem.

Jak to w ogóle działa? Otóż – znów musiałem skorzystać z API Windows. Tym razem potrzebne są funkcje:

Uwaga: Funkcja SetWaitableTimer przyjmuje parametr czasu w formacie FILETIME. Obiekt typu DateTime można skonwertować do tego formatu używając metody ToFileTimeUtc().

Program przeznaczony dla systemu Windows Vista z .NET Framework 3.5 (używa klasy GlassWindow z poprzedniego postu).

Download:
Budzik
Budzik – kody źródłowe

PS: Zanim zaufasz budzikowi, upewnij się, czy twój komputer daje się programowo wybudzić z hibernacji. Jak nie, to go na noc tylko usypiaj i upewnij się, że nie zahibernuje się sam.

PPS: Nie biorę odpowiedzialności za szkody wywołane zaspaniem.

Okno ze szkła

Windows Vista udziwnił troszeczkę konstrukcję okna wprowadzając półprzezroczystą część nazywaną Glass (szkło). Jest to ewidentnie wodotrysk i trochę dziwi mnie, dlaczego wprowadzono do API funkcje, które mogą okazać się tylko chwilową modą, która zniknie wraz z nastepną wersją systemu.

No dobrze, w Windows 7 dalej będzie ten wodotrysk, więc skoro już jest, to warto może spróbować go użyć (byle nie nadużyć). Nie oszukujmy się – ludzie lubią wodotryski.

WPF nie daje bezpośredniej możliwości operowania na szkle – potrzebujemy wywołać funkcję API DwmExtendFrameIntoClientArea przyjmującą jako argument uchwyt okna i strukturę MARGINS. A może by tak postarać się trochę i utworzyć DependencyProperty – animowalną, bindowalną i elegancką (na tyle, na ile DependencyProperty można nazywać elegancką) właściwość pozwalającą regulować szklany obszar okna?

Proponuję zrobić to tak:

Teraz – zamiast tworzyć okna na bazie klasy Window, możemy użyć klasy GlassWindow posiadającej właściwość GlassFrame typu Thickness, którą możemy się posługiwać jak każdą inną DependencyProperty.

Ustawiając dodatnie wartości dla GlassFrame, możemy regulować grubość szklaj ramki. Jeśli ustawimy wartości ujemne – całe okno zrobi się szklane.