posted on Styczeń 4th, 2010 ·
Początkowo, wpis ten miał charakter szyderczy i kpiący z Gmaila. Po dłuższym badaniu okazało się jednak, że to Gmail ma rację i to on najlepiej wykonuje to, co RFC przykazało. Część szyderczą pozostawiam, aby potem wykazać swoją niewiedzę.
From: Nowaker
To: Gmail
Nazywasz się Gmail, jesteś tworzony przez Google, to myślisz, że RFC dla ciebie nie istnieje? Że niby po co ci RFC? Cały Internet tylko dzięki mojej firmie się trzyma kupy, więc myślisz, że to ty ustalasz zasady? I ustaliłeś sobie, że dodanie spacji na końcu linii ma od teraz specjalne znaczenie. Wg ciebie taka spacja ma oznaczać, że znak końca linii ma zostać zignorowany. Nie podoba mi się to.
Wytłumaczenie: Jeśli linia tekstu posiada jakąkolwiek spację na swoim końcu, znak nowej linii zostanie zignorowany. W RFC 2822 nie znajduje się jakakolwiek wzmianka, jakoby spacja przed znakiem końca linii miała mieć jakieś specjalne znaczenie.
From: Gmail
To: Nowaker
Panie Nowaker, słabo pan korzystał z naszej wyszukiwarki. Gdybyś jej dobrze użył, na pewno znalazłbyś informację o RFC 3676. Ba, znalazłbyś piękne polskie opracowanie nt. format=flowed. Gdybyś był świadomy tego, nie dodałbyś format=flowed do Content-Type twojej wiadomości. My zaleceń RFC przestrzegamy, nawet jako jedni z niewielu dobrze interpretujemy format=flowed! Nie dodaj bezmyślnie format=flowed, to nie będziesz miał takich problemów.
Wytłumaczenie: standard e-maili powstał w 1982 roku. Standard był odświeżany, jednak część niedoskonałości już pozostała. Jednym z nich jest ograniczenie do siedemdziesięciukilku znaków w jednej linii. O ile kiedyś, w dobie terminali tekstowych o stałej rozdzielczości, miało to bardzo ważne znaczenie, teraz staje się to problemem. Rozdzielczości monitorów się zwiększają, a linie zawijane są nadal przy tych 70 znakach. Z kolei w urządzeniach przenośnych e-maile czyta się jeszcze gorzej.
format=flowed i jego RFC stanowi uzupełnienie standardu wiadomości e-mail i dostosowanie go do realiów tych czasów. Nadal łamiemy linie w okolicach 70 znaków, ale jeśli znak nowej linii został wymuszony (łamanie jednego paragrafu na wiele linii), wtedy na końcu takiej złamanej linii dodajemy spację. Wtedy klient poczty rozumie, że nastąpiło w tym miejscu sztuczne łamanie. Może więc usunąć je, scalić paragraf w jedną linię i potem połamać paragraf wg preferencji użytkownika, np. dostosować do rozmiaru okna programu.
Więcej o format=flowed przeczytasz tutaj. Artykuł przedstawia praktyczne zastosowanie tego wynalazku.
From: Nowaker
To: Gmail
Sorki, Gmail, że na ciebie tak najechałem. Okazało się, że to ty masz jednak rację. Wielki plus, że porządnie interpretujesz składnię wiadomości e-mail. Na swoją obronę chcę tylko powiedzieć, że nie zauważyłem, że moje narzędzie do generowania e-maili dodaje domyślnie format=flowed.
Tags: Internet
posted on Grudzień 28th, 2009 ·
Jakiś czas temu zastanawiałem się nad kupnem netbooka. Najważniejszym kryterium był dla mnie czas pracy na baterii, dlatego wybór padł na Asus Eee 1005HA. Problemem jednak okazały się całkowicie niespójne oznaczenia – 1005HA(M) i 1005HA(H). Ten wpis ma na celu podanie najważniejszych różnic pomiędzy wersjami 1005HA, aby potencjalni kupujący nie dali wprowadzić się w błąd.
W Internecie panuje zamieszanie związane z oznaczeniami. Objawia się tym, że każdy twierdzi coś innego nt. modeli H oraz M. Najpopularniejsze są dwa mity:
- Mit 1: wersja H posiada procesor Intel Atom N280, zaś M – N270.
- Mit 2: wersja H posiada pojemniejszą baterię od M
Generalnie, “lepszą” wersją jest H. Ale wcale nie oznacza to, że każda wersja H na pewno będzie “lepsza” od M, w kilku przypadkach może być mniej więcej taka sama.
Oznaczenie M/H wprowadza tylko mętlik, bo nie określa dokładnie wszystkich parametrów. Dokładnie określa wyłącznie kod producenta w postaci:
1005HA-[BLK/WHI/...][ID], np. 1005HA-BLK059S
To pierwsze to nic innego, jak kolor. ID określa dokładne, niezmienne parametry tej konkretnej wersji. To ID jest najważniejsze, a nie literka M/H, która w kodzie producenta nawet nie występuje (kto ją wymyślił?).
Poniżej przedstawiam listę kilku wersji wraz różnicami, które zauważyłem.
- ID = 059S ma Atom N270, “największą” baterię, matrycę matową, dysk 250GB, ma BlueTooth. Oznaczona jako 1005HA(H).
- ID = 060S ma Atom N270, “średnią” baterię, matrycę matową, dysk 160GB, nie ma BlueTooth. Oznaczona jako 1005HA(M).
- ID = 031S ma Atom N270, “średnią” baterię, matrycę matową, dysk 160GB, nie ma BlueTooth. Oznaczona jako 1005HA(M).
- ID = 045S ma Atom N270, “średnią” baterię, matrycę matową, dysk 250 GB, ma BlueTooth. Oznaczona jako 1005HA(H).
- ID = 135X ma Atom N270, “średnią” baterię, matrycę matową, dysk 160 GB, ma BlueTooth. Oznaczona jako 1005HA(M).
- ID = 126X ma Atom N280, “największą” baterię, matrycę glare, dysk 160 GB, ma BlueTooth. Oznaczona jako 1005HA(H).
- ID = … i wiele innych
Jak więc widać, mówiąc sobie H bądź M wcale nie przekazujemy informacji o procesorze, pojemności baterii, pojemności dysku, rodzaju matrycy oraz czy posiada BlueTooth. Jaki jest więc sens tego oznaczenia? Kto je w ogóle stworzył, skoro na stronie producenta nie znajdziemy takiego oznaczenia?
Starałem się, aby porównanie było jak najbardziej rzetelne. Specyfikacje dot. konkretnej wersji porównywałem w co najmniej dwóch różnych sklepach. Sam zaś gwarantuję poprawność specyfikacji 1005HA-059S, ponieważ taką właśnie posiadam.
Mity związane z wersjami H i M uznaję za obalone. Przy okazji postaram się jednak poruszyć kilka innych kwestii związanych z tym netbookiem.
Atom N270 czy N280?
W ogólności (dotyczy to wszystkich netbooków), jeśli tylko jest to możliwe, warto wybrać procesor Intel Atom N280. Chociaż, że jest on o 3% wydajniejszy od N270, jest to praktycznie nieistotne. Atom N280 zjada mniej prądu, co na “największej” baterii z 1005HA daje mu dodatkowe półtorej godziny pracy wg producenta.
Problem jednak pojawia się taki, że w modelu Asus Eee 1005HA ten procesor występuje tylko i wyłącznie z matrycą błyszczącą (glare). Różni ludzie lubią różne typy matryc. Pozostaję neutralny i tylko ostrzegam, że konsekwencją wyboru N280 jest wybór matrycy glare.
Czas pracy na baterii wg producenta – prawda czy fałsz?
Mogę powiedzieć, jak to wygląda w przypadku modeli 1005HA-059S w systemie Ubuntu Linux (ps aux | wc -l = 150 po zalogowaniu się).
Czas pracy na baterii wg producenta to 9 godzin (bez WiFi). W rzeczywistości mogę wykonywać “lekką” pracę (przeglądanie stron internetowych, jakiś Notatnik) ok. 7,5 godziny. Ciężkie rzeczy, jak programowanie w NetBeansie to ok. 6,5 godziny. Wartości nie są z palca, lecz wzięte z last | grep reboot. Bez WiFi nigdy nie pracowałem, jednak nie zdziwiłbym się, gdyby w takim przypadku czas pracy zbliżył się do gwarantowanego przez producenta czasu.
Jak mieć pewność, że otrzymam dokładnie taką wersję, jaką chcę?
Jeśli sklep nie podaje kodu producenta, tylko H i M, nie można mieć żadnej pewności. Pod tymi oznaczeniami kryje się tyle różnych konfiguracji, że nie wiadomo, co się dostanie.
Ja u sprzedawcy zamówiłem konkretny model wg kodu producenta (1005HA-059S, jeden z wariantów H) i poinformowałem sprzedawcę, że na fakturze ten kod musi się znaleźć. Jeśli otrzymam nieodpowiedni model, mogę go zwrócić i żądać wydania sprzętu zgodnego z dowodem sprzedaży.
Nie chcę Windowsa
Firma Asus nie robi w kwestii zwrotu systemu Windows żadnych problemów. Jedyny warunek to zgłoszenie rezygnacji z systemu Windows w ciągu siedmiu dni od daty zakupu. Liczy się data wysłania pierwszego e-maila.
W moim przypadku dokumenty do wypełnienia dostałem jakoś po tygodniu od zgłoszenia rezygnacji. Poinformowali mnie najpierw, że muszą ustalić wartość Windowsa 7 Starter. Czyżbym był pierwszą osobą, która zgłosiła rezygnację z tego super systemu?
Chociaż, że zwracana kwota jest śmiesznie niska, doceniam sam fakt możliwości zwrotu. Ja otrzymałem 6,75$ zwrotu za Windows 7 Starter. Na innym blogu przeczytałem, że za Windows XP otrzymuje się 7€. Warto podjąć działanie choćby po to, aby w przyszłości móc kupić komputer bez narzuconego systemu operacyjnego. Wystarczy, że co drugi kupujący odda Windowsa – Asusowi przestanie się to opłacać. ;-)
Na Linuksie wszystko działa?
Używam Ubuntu 9.10. Na tym systemie miałem tylko jeden problem. Gdy przez WiFi szły dane z szybkością 2 MiB/s, sieć przerywała transfery co ok. 10 sekund. Problemem okazał się sterownik, wystarczy zainstalować nowsze sterowniki z serii “backports” – sudo apt-get install linux-backports-modules-wireless-karmic-generic. Problem nie występował przy mniejszych transferach rzędu kilkuset KiB/s. Błąd występował również w Mandrivie i Fedorze (oba LiveCD, czy raczej LivePenDrive). Nie odnotowałem zaś tego błędu na OpenSuse – system został wypuszczony później, niż Ubuntu 9.10 i zawiera już w sobie nowy sterownik.
Wszystkie inne peryferia, jak czytnik kart pamięci, kamera internetowa i BlueTooth działają OOTB. Co do BlueTootha, to czasami psuje się gnomowy aplet. Nie psuje się za to program z pakietu blueman, oferując przy okazji lepszą funkcjonalność. Przy jego pomocy udało mi się nawet użyć telefonu Nokia E51 do połączenia z Internetem. Domyślny aplet nie ma możliwości użycia modemu z telefonu komórkowego i odpowiedniego skonfigurowania pppd. Tutaj przeczytasz więcej o łączeniu się z Internetem za pośrednictwem komórki.
Działa większość z przycisków funkcyjnych – te najważniejsze. Włączenie/wyłączenie WiFi, przyciemnienie/rozjaśnienie podświetlenia wyświetlacza, kontrola głośności (o ile się nie wyrzuci znienawidzonego przeze mnie PulseAudio). Nie działają takie, których znaczenia nie jestem w stanie się domyślić, patrząc na ikonkę.
Netbook posiada kartę graficzną Intela. Na niektórych kartach były problemy z DRI i niedziałającym xrandr (więc i gnome-display-settings). Tutaj nie występuje ten problem – można podłączyć drugi monitor 24” i cieszyć się wirtualnym obszarem roboczym o szerokości powyżej 2048px.
Uwaga, nie instalować programu eee-control i jego pochodnych (nie ma go w repo, jest dostępny gdzieś w sieci). Jego zainstalowanie dodaje bardzo niewiele ficzerów, psuje z kolei klawisz włączający WiFi. :-)
Tags: Ogólne
posted on Wrzesień 28th, 2009 ·
Dzisiaj klient zgłosił mi problem z jedną z jego starych stron. Problem polegał na tym, że zawartość strony wyświetla się trzy razy. Rzeczywiście, kilka dni wcześniej majstrowałem trochę w kodzie kontrolera i widoku, aby ulepszyć generowanie meta-danych pod SEO i przy okazji popsułem inne miejsce.
Ta sytuacja zmotywowała mnie, aby napisać trochę o testach jednostkowych. Stosuję je w codziennej pracy przy niektórych projektach w Javie i PHP – i często ratują mi skórę.
Czym są testy jednostkowe?
Testy jednostkowe można porównać z testami wybranej partii produktów z fabryki. Testowane są pod kątem zgodności z założeniami – długością, szerokością, wagą i położeniu nadruków. Testowane jest również działanie tych produktów w jakimś symulowanym środowisku.
W inżynierii oprogramowania wygląda to analogicznie. Bierzemy naszą klasę, wykonujemy kilka operacji na niej i sprawdzamy, czy rezultat jest zgodny z naszymi oczekiwaniami.
Po co testować?
Praca z kodem to dość skomplikowany proces. Implementacja nowych funkcjonalności nie tylko wymaga tworzenia nowych klas, ale i częstokroć modyfikowania obecnych. O ile niedziałająca nowa klasa nie jest żadnym problemem, to popsucie istniejącej klasy niesie z sobą już poważne konsekwencje. Inni komponenty programu mogą korzystać z tej klasy i nagle cała aplikacja się sypie. W dodatku, błąd może się ujawniać tylko dla specyficznych przypadków i wtedy znalezienie takiego błędu jest naprawdę kosztowne. Testy jednostkowe mają zabezpieczyć programistę przed przypadkowym popsuciem czegoś innego. W przypadku negatywnego wyniku testów jednostkowych, mamy podane na tacy miejsce występowania błędu. Bez testów błędu trzeba samemu szukać.
Jak testować?
Każdy test powinien testować niewielki fragment systemu, aby w przypadku jego negatywnego wyniku można było łatwo znaleźć miejsce błędu. Ważne jest, aby test wykonywał się szybko. Tylko wtedy programista będzie miał ochotę uruchamiać test co kilka minut. Test, który wykonuje się długo, np. pół godziny nie będzie chętnie uruchamiany.
Poprawność wyniku
Na samym początku sprawdzamy przede wszystkim poprawność wyniku. Weźmy za przykład koszyk z zakupami. Przykładowymi testami koszyka mogą być:
- Do pustego koszyka wkładam jeden test jednostkowy i jedną klasę. Potem czyszczę zawartość koszyka. Czy ilość kodu w koszyku jest równa zeru?
- Do pustego koszyka wkładam jedną test jednostkowy i dwie klasy. Czy w koszyku znajduje się jeden test jednostkowy i dwie klasy? Testujemy od razu metodę zliczającą. Czy łączna ilość kodu w koszyku wynosi dwa? Czy łączna ilość sztuk kodu w koszyku wynosi trzy?
- Do pustego koszyka wkładam jeden test jednostkowy. Potem wkładam jeszcze dwa testy. Czy łączna ilość testów jednostkowych to trzy?
- Do pustego koszyka wkładam dwa takie same testy jednostkowe. Potem zmieniam ilość testów na jeden. Czy w koszyku znajduje się tylko jeden test?
Warunki brzegowe
Każdy programista pewnie przyzna, że najwięcej błędów daje o sobie znać, gdy zachodzą tzw. warunki brzegowe. Jednym słowem, gdy kod zachowuje się nietypowo, inaczej niż zawsze. Typowym przykładem jest dzielenie przez zero.
Odsyłam do rozdziału czwartego książki „JUnit. Pragramtyczne testy jednostkowe w Javie”. Tak się składa, że Helion udostępnił ten rozdział za darmo w Internecie w formacie PDF. (P.S. Nie polecam tej książki, nie jest warta swojej ceny, omawia starą wersję JUnit oraz nie pokazuje dobrych praktyk pisania testów jednostkowych)
Skorzystam z listy przedstawionej w tej książce, aby omówić najważniejsze aspekty testowania warunków brzegowych.
Zgodność
Często nasze metody oczekują danych w ściśle określonym formacie. Np. adresy e-mail muszą być zgodne ze swoim RFC, a liczby dziesiętne zapisane jako string powinny używać kropki jako separatora dziesiętnego.
Uporządkowanie
Jako przykład wezmę znajdowanie najmniejszej liczby całkowitej w liście. Warto przetestować, czy metoda zwraca poprawny wynik, jeśli najmniejsza liczba znajduje się na początku listy, gdzieś w środku oraz na końcu. Może się bowiem okazać, że w wyniku naszej pomyłki metoda, która miała zwracać najmniejszą liczbę na liście zwraca jej pierwszy element. Przy sprzyjających warunkach nasza metoda będzie działała, tj. gdy lista będzie posortowana. Wszystko popsuje się, gdy lista nie będzie uporządkowana. Test jednostkowy nam w tym pomoże i ostrzeże o nieodpowiednim działaniu.
Zakres
Jasne jest, że metoda konwertująca stopnie w skali Kelvina na Celsjusza może przyjmować wartości większe lub równe zeru. Przetestujmy więc działanie metody dla skrajnego przypadku – zera bezwzględnego oraz wartości ujemnej. W przypadku zera bezwzględnego zwyczajnie sprawdzamy, czy nie pomyliliśmy się przy implementacji, np. dając nieodpowiednie równanie (>= zamiast >). Wartość ujemną sprawdzamy, aby upewnić się, że rzucany jest odpowiedni wyjątek.
Warunki początkowe
Wyobraźmy sobie malarza. Malarz może malować ściany tylko, jeśli jest w odpowiednim pokoju oraz ma pędzel w ręce. ;-) Przetestujmy więc, czy malarz zachowuje się prawidłowo, tj. nie maluje, jeśli nie ma pędzla w ręce.
Istnienie
NullPointerException to chyba jeden z najczęściej pojawiających się błędów w aplikacjach Javy. Łatwo jest się ich pozbyć, jeśli przygotujemy odpowiedni wachlarz testów. Warto przetestować zachowanie metod, próbując dać null jako parametr, gdzie tylko się da.
Czas
Czy obiekt zachowuje się poprawnie, jeśli korzysta z niego wiele wątków naraz? Co się stanie, jeśli wywołam metody w nieodpowiedniej kolejności?
Czym testować?
Dla Javy istnieje kilka narzędzi do testowania, najpopularniejszym jest JUnit – każde szanujące się IDE obsługuje jego testy. Można więc wydajnie i co chwilkę uruchamiać test i oczekiwać zielonego światełka. ;-) Szczególnie polecam JUnit w wersji 4 z powodu jego uproszczeń.
PHPUnit to narzędzie do testowania kodu PHP. Nie widziałem integracji IDE z PHPUnitem, jednak nie jest to aż taki problem. W Eclipse PDT zdefiniowałem zewnętrzne narzędzie, które uruchamia testy PHPUnit w konsoli. Nie zapomniałem też o skrócie klawiszowym dla tej akcji.
Zakończenie
Niedługo postaram się napisać coś o pisaniu testów zgodnie z szablonem „given-when-then”, które zwiększają jakość oraz czytelność testu. Należy bowiem pamiętać, że test powinien być takiej samej dobrej jakości, jak kod testowej aplikacji.
Tags: Java · Programowanie · Ynne