28/09/2013

Szybkie tworzenie tabel w TeX/LaTeX

Home

TeX/LaTeX jest potężnym środowiskiem pracy ale ma to swoją cenę. Między innymi niektóre rzeczy robi się w dużo trudniejszy sposób niż w programach takich jak Word czy Excel. Dobrym przykładem jest tworzenie tabel. W TeX/LaTeX trzeba się napracować i wpisać odpowiednią sekwencję poleceń formatujących. Przy małych tabelach można jeszcze zagryźć zęby, ale przy dużych wielokolumnowych zbiorach danych szkoda nerwów. Ja akurat potrzebował przenieść kilka tabel z dokumentu Word do swojego artykułu.

Najpierw skopiowałem, więc tabele z Word'a do Excel'a, a potem skorzystałem z dodatku do Excel'a o nazwie Excel2LaTeX, który dodaje w zakładce Dodatki dwa polecenia: Convert table to LaTex oraz Convert all stored tables to LaTex. Wystarczy zaznaczyć interesujący nas zestaw komórek, wybrać polecenie, a potem wkleić wygenerowaną tabelę do dokumentu *.tex. Ja jeszcze dodatkowo musiałem zaimportować brakujący pakiet tj.: \usepackage{booktabs}.

Polecam też ten artykuł, w którym autor zebrał kilka sposób te wyeksportowanie tabel z programu Excel to TeX/LaTeX.

Unable to locate trace definition file...

Home

Jakiś czas temu w celu wykrycia przyczyny zakleszczenia (ang. deadlock) musiałem przeanalizować plik Trace File nagrany przez SQL Server Profile. Niestety przy próbie jego otworzenia pojawiły się problemy ponieważ plik został nagrany przy pomocy starszej wersji oprogramowania (10.50.0) niż moja (10.50.2550):



Nie miałem dostępu do maszyny, na której został nagrany log, a więc nie mogłem postąpić zgodnie z radą zawartą w komunikacie. Nie chciałem też tracić czasu i szukać kogoś kto wie gdzie dokładnie ten log został nagrany. Utworzyłem więc kopię pliku Microsoft SQL Server TraceDefinition 10.50.2550.xml i nazwałem ją Microsoft SQL Server TraceDefinition 10.50.0.xml.

Po tej zmianie kolejna próba otwarcia pliku z logiem powiodła się. Nie wiem jakie są różnice pomiędzy wersją 10.50.2550, a 10.50.0 ale ta prosta sztuczka wystarczyła aby odnaleźć przyczynę błędu i ją usunąć. Możliwe, że przy większym rozjechaniu się wersji to podejście nie zadziała ale zawsze warto spróbować.

23/09/2013

Moje spojrzenie na DevDay 2013

Home

Przez długi czas stałym punktem w moim kalendarzu była konferencja MTS, ale w pewnym momencie zaczęła mnie nóżyć. Zrobiłem sobie przerwę i rok temu spróbowałem jeszcze raz, ale podobało mi się jeszcze mniej niż wcześniej. Wtedy usłyszałem o organizowanej w Krakowie konferencji DevDay. W sieci zebrała ona doskonałe opinie, więc w tym roku postanowiłem ją odwiedzić i o tym będzie ten post.

Kilka słów wstępu

DevDay organizowane są przez firmę ABB, ale poza logiem na identyfikatorach oraz niewielkich plakatów rozstawionych tu i tam firma w ogóle nie narzuca się uczestnikom. Generalnie charakter konferencji jest mało komercyjny i to wielki plus. Mnie co prawda odrobinę drażniło, że co chwilę ktoś robił zdjęcia np.: podczas rozmowy z prelegentami ale coś za coś, ABB też coś chciało mieć za wyłożenie pieniędzy :)

Organizacyjnie nie mam żadnych zarzutów, poza kolejką do obiadu, ale to drobnostka. Zresztą nie byłem jeszcze na konferencji, na której udało się to naprawdę dobrze zorganizować. Ekipa organizacyjna spisała się w 100%.

Z organizacyjnych rzeczy bardzo spodobało mi się kontrolowanie czasu, czyli pokazywanie prelegentom kartki z informacją ile jeszcze mogą mówić. Fajny był też system oceny sesji. Przy wychodzeniu z sali do dyspozycji miało się karteczkę czerwoną - nie podobało mi się, żółtą - było średnio i zieloną - podobało mi się. System może mało precyzyjny ale prosty, szybki i nie wymagający wypełniania żadnych ankiet.

Mój przewodnik po sesjach

Sesja początkowo

Pierwsza sesja miała być podobno krótka, ciekawa i motywująca. Prelegent porównał programowanie do biegania. Moim zdaniem wyszło niestety średnio (szczególnie na tle innych prezentacji) było krótko, ale niezbyt ciekawie i niezbyt motywująco.

Ocena: Na pograniczu żółtej i czerwonej karteczki.

"Back to basics: the mess we've made of our fundamental data types"
Jon Skeet

Przed prezentacją nie wiedziałem czego się po niej spodziewać. O prelegencie wiedziałem, że to łebski koleś, legenda StackOverflow, ale nie kojarzyłem go jako prelegenta. Temat też trochę budził moje podejrzenia, bo co można powiedzieć o podstawowych typach danych.

Jak się okazuje można i to jeszcze w jaki sposób. Prezentacja była poprowadzona we wspaniały sposób, z humorem, do tego była ciekawa i można było z niej dużo wynieść. Spróbujcie na przykład odwrócić ciąg znaków zapisany w zmiennej s na poniższym przykładzie:

var s = "Les Misérables".Normalize(NormalizationForm.FormD);

Ocena: Bardzo zielona karteczka.

"Scaling agile"
Dariusz Dziuk

Jedyny Polak w gronie prelegentów. Mówił o organizacji pracy w szwedzkiej firmie Spofity, która udostępnia utwory muzyczne prawie za darmo. W tej chwili zatrudnia kilkuset pracowników technicznych. Podzieleni są na kilkuosobowe zespoły, które są trochę takimi małymi firma tj.: same wybierają sobie narzędzia, sposób pracy, są wielo-platformowe, czyli jeśli pracują nad jakąś nową funkcjonalnością to mają ją dostarczyć na wszystkie platformy np.: Android'a i iOS. A drugim nadrzędnym celem Spotify oprócz zarabiania pieniędzy jest uszczęśliwiania pracowników :)

Prezentacja została poprowadzona bardzo sprawnie, ale bez porywów, momentami mi się dłużyła. Nietypowe (dla mnie na plus) było wprowadzenie podczas, którego Dariusz opowiedział kilka słów o historii Jazz'u.

Ocena: Żółta karteczka.

"SPA Made Breezy"
Tiberiu Covaci

Najbardziej techniczna sesja na jakiej byłem dotyczą tworzenia aplikacja SPA (ang. Single Page Application) przy pomocy Breeze.js oraz MVC. Trochę nie wyszedł pokaz możliwości biblioteki na żywo, co jednak nie zraziło prelegenta (tutaj widać obycie i doświadczenie).

Mi sesja nie przypadła do gustu, może dlatego, że na co dzień nie programuję aplikacji WWW, a może dlatego, że ostatnimi czasy prezentację, w których przewija się dużo kodu pisanego na żywo do mnie nie trafiają.

Ocena: Na pograniczu żółtej i czerwonej karteczki.

"Building Startups and Minimum Viable Products"
Ben Hall

Lekka, bardzo fajnie poprowadzona sesja dotycząca startup'ów, a prelegent wiedział o czym mówił, bo ma dwa na swoim koncie, a teraz pracuje dla firmy, która wyszykuje obiecujące firmy i w nie inwestuje. Ben zwrócił uwagę, że startując ze swoim pomysłem przede wszystkim trzeba mieć pasję, a najlepiej bardzo dużo pasji. Jego zdaniem na początek  należy unikać pisania kodu, jak najwięcej wykorzystywać istniejące rozwiązania, skupić się na dostarczeniu wartości, a nie na jakości kodu czy pisaniu testów jednostkowych. Dobry wynik dla firmy inwestującej w startup'y to podobno 30%, czyli jeśli 3 inwestycje na 10 zaczną na siebie zarabiać to jest dobrze.

Ocena: Zielona karteczka.

"Full-text search with Lucene and neat things you can do with it"
Itamar Syn-Hershko

Prezentacja była nie tyle o Lucene, co o rozproszonym serwerze przeszukiwania pełnotekstowego opartym o Lucene. Lekka techniczna sesja, z wprowadzeniem dla początkujących. Słyszałem głosy, że temat prezentacji sugerował co innego i było za dużo o rzeczach podstawowych, ale mi sesja się podobała, bo odświeżyłem sobie wiedzę.

Ocena: Zielona karteczka.

"The Architecture of StackOverflow"
Marco Cecconi

Portalu StackOverflow chyba nikomu nie należy przedstawiać. Na tym samym silniku stoi ponad 100 innych serwisów typu Q&A, a sam portal StackOverflow jest w czołówce najczęściej odwiedzanych stron na świecie. Wbrew pozorom do obsługi tego wszystkiego wystarczy 11 serwerów WWW, 4 serwery bazodanowe i dwa serwery cache'ujące używające technologii Redist. Każdy serwer bazodanowy ma ponad 300GB pamięci, tak aby pomieściła się cała baza danych.

Kod aplikacji podzielony jest raptem na kilka projektów (całość to ok. 100 tyś linii kodu). Testów jednostkowych jest bardzo mało, bo użytkowników jest tak dużo, że wszelkie błędy wykrywane są bardzo szybko. Ewentualne poprawki można dostarczyć w kilka minut. Co z tym związane, w wielu miejscach użyto klas statycznych, bo i tak nie będą mock'owane, a przede wszystkim ma być prosto. Zespół StackOverflow nie zastanawia się też na przejściem do chmury, czy użyciem bazy NoSQL, ponieważ wszystko działa dobrze tak jak jest. Lubię takie zdrowie podejście do tematu.

Prezenter skończył mówić z 15-20 minut przed czasem, ale pozostałą część sesji zajęły pytania z publiczności.

Ocena: Na pograniczu żółtej i zielonej karteczki ale bliżej zielonej.

"The software journeyman's guide to being homeless and jobless."
Rob Ashton

Kolejna genialna sesja. Rob pokazał niesamowity warsztat, a mówił o tym jak rok temu zrezygnował z pracy w korporacji bo miał dosyć, a pieniędzy i tak nie miał na co wydawać. Od tego czasu podróżuje po świecie z jedną walizką i pracuje tam gdzie dostanie lokum oraz bilet lotniczy. Teraz jest w Belgii i, jak sam mówi, to strasznie nudne miejsce, w Izraelu pracował nad RavenDB, w międzyczasie zaliczył wypadek samochodowy, kodował w Closure w czasie koncertu Eurowizji itd. A tak w ogóle trochę mu się śpieszyło bo chciał napić się piwa :)

Mi bardzo spodobało się też podsumowanie, w którym Rob powiedział coś w stylu (bardzo luźną parafraza) "No tak, ale ja nie mam żony, dzieci czy innych zobowiązań, a więc mi jest łatwiej. Wy też jednak możecie coś zrobić, zmienić pracę na ciekawszą, blogować, występować na konferencjach, uczyć się nowych rzeczy, dzielić się wiedzą..."

Ocena: Bardzo zielona karteczka.

Sesja końcowa

Sesja końcowa to dużo powiedziane, bo trwała małe kilkanaście minut. Nie zabrakło zasłużonych podziękowań dla prelegentów oraz dla ekipy obsługującej konferencję. Była też fala, poważnie, taka jaką widuje się na meczach piłkarskich oraz pamiątkowe zdjęcie :)

Ocena: Bardzo zielona karteczka

Podsumowanie

W dwóch słowach Było super! i już szykuję się na przyszły rok. Przyznam, że od strony technicznej dużo się nie nauczyłem, ale zdobyłem dużo miękkiej wiedzy i zastrzyk pozytywnej energii.

18/09/2013

Indeksy, LIKE oraz =

Home

Prosta zagadka. Rozważmy następującą tabelą z dwoma kolumnami:
CREATE TABLE Test
(
   ID Int IDENTITY(1,1) PRIMARY KEY,
   Name CHAR(10)
)

CREATE INDEX IX_TEST_NAME ON dbo.Test (Name)
Teraz na wejściu dostajemy pewien ciąg znaków i przechowujemy go w zmiennej:
DECLARE @Variable CHAR(10);
SET @Variable = '1234567890';
Chcemy znaleźć wszystkie te rekordy, dla których N pierwszych znaków w kolumnie Name jest takie samo jak N pierwszych znaków w zadanym ciągu. Można to zrobić tak (N=3):
SELECT * FROM dbo.Test WHERE  LEFT(Name, 3) = LEFT(@Variable, 3)
Albo tak:
SELECT * FROM dbo.Test WHERE Name LIKE LEFT(@Variable, 3)+'%'
Oba zapytania dadzą ten sam wynik ale jedno z nich będzie zdecydowanie szybsze (dla dużej ilości danych) niż drugie. Które?

W tym przypadku użycie LIKE okazuje się lepszym wyborem. Dlaczego? W pierwszym zapytaniu zostanie użyty INDEX SCAN (czyli de facto odczytane zostaną wszystkie wiersze z tabeli), a w drugim  INDEX SEEK. Dzieje się tak gdyż w pierwszym zapytaniu użyto funkcji LEFT (może to być dowolna inna funkcja) na kolumnie, na której nałożony jest indeks.

Do problemu można też podejść w inny sposób czyli stworzyć indeks na kolumnie wyliczanej tj.:
ALTER TABLE dbo.Test ADD NAME2 AS LEFT(Name, 3)
CREATE INDEX IX_TEST_NAME2 ON dbo.Test(Name2, Name)
W takiej sytuacji pierwsze z pokazanych zapytań (te z operatorem =) również użyje operacji INDEX SEEK.

16/09/2013

Gdzie znaleźć cytowania w formacie BibTeX

Home

BibTeX to narzędzie do tworzenia bibliografii używane przez LaTeX'a. Wpis w bibliografii w formacie wymaganym przez BibTeX'a wygląda na przykład tak:
@inproceedings{komorowski2010configuration,
  title={Configuration management of mobile agents based on SNMP},
  author={Komorowski, Micha{\l}},
  booktitle={Rough Sets and Current Trends in Computing},
  pages={456--465},
  year={2010},
  organization={Springer}
}
Przykład zawiera tylko część z możliwych atrybutów i może być dużo bardziej rozbudowany. Kiedy piszę artykuł nie mam ochoty samemu tworzyć takich wpisów, ale niestety nie zawsze razem z artykułem znajdziemy przygotowany wcześniej wpis dla BibTeX'a. W takim wypadku polecam skorzystać ze strony ACM Digital Library lub Google Scholar.

W pierszym portalu po znalezieniu artykuły u góry, z prawej strony zobaczymy pole Tools and Resources, a w nim link BibTeX. Po jego kliknięciu otrzymamy sformatowane cytowanie. W przypadku Google Scholar po znalezieniu publikacji klikamy link Cytuj, a następnie Zaimportuj do programu BibTeX. Z mojego doświadczenia wynika, że cytowania wygenerowane przez oba programy są sobie równoważne, te wygenerowane przez ACM Digital Library są trochę obszerniejsze ale przeważnie i tak nie używamy wszystkich możliwych atrybutów.

14/09/2013

LEd i nowa wersja MiKTeX

Home

Z MiKTeX'a czyli implementacji systemu składu tekstu TeX/LaTeX dla Windows'a oraz programu LEd wspomagającego pracę z TeX/LaTeX'em korzystam już od bardzo dawna. Ponieważ należą do osób, które nie wyczekują wszelkiego rodzaju aktualizacji z drżącym sercem i instaluję je dopiero kiedy jest mi to rzeczywiście potrzebne to do tej pory zadowalałem się wersją MiKTeX 2.5 i pewnie pracowałbym z nią jeszcze długo, gdyby nie okazało się, że nie jest już wspierana i nie mogą ściągnąć potrzebnych mi pakietów.

Pobrałem więc najnowszą wersję 2.9, zainstalowałem, zmieniłem ścieżkę w zmiennych środowiskowych, a także dostosowałem ustawienia LEd'a wskazując katalog z nową wersją Configuration->Options->Application->DVI Viewer->TeX Executables. Następnie uruchomiłem kompilację projektu i LEd bez ostrzeżenia wywalił się. Spróbowałem otworzyć projekt jeszcze raz ale tym razem nawet to było niemożliwe. Usunąłem, więc wszelkie stworzone pliki tymczasowe i spróbowałem jeszcze raz otworzyć projekt. Tym razem udało się ale tak czy inaczej kompilacja znowu się nie powiodła. Kilka kolejnych prób zakończyło się tak samo. W logu systemowym nie znalazłem żadnych błędów.

Zacząłem więc dokładnie przyglądać się konfiguracji LEd'a i okazało się, że przeoczyłem jedną opcję Configuration->Options->Application->DVI Viewer->TeX distribution. Ustawiona była na MiKTex2.5 co wydało mi się podejrzane. Na liście nie widziałem jednak opcji MiKTeX2.9 ale za to znalazłem opcję based on MiKTeX. Spróbowałem i zadziałało.

Mam nadzieję, że to oszczędzi komuś czasu i nerwów.

12/09/2013

Nullable<T>.Equals(T value) 2

Home

Pytanie o opinię na temat Nullable<T>.Equals(T value) z poprzedniego postu zadałem również na portalu stackoverflow. Jeden z odpowiadających bardzo słusznie zwrócił uwagę, że opisany przeze mnie "problem" nie dotyczy tylko typu Nullable<T>. Aby przekonać się o czym mowa uruchomcie następujący kod:
Console.WriteLine((2m).Equals(2));
Console.WriteLine((2).Equals(2M));
Pierwsza myśli to 2xTrue ale poprawny wynik to True, False. Dzieje się tak ponieważ istnieje niejawna kowersja z typu int na decimal ale nie na odwrót. Czyli w pierwszym przypadku zostanie użyta metoda Equals(decimal value), a w drugim Equals(object value) A piszę o tym ponieważ to jedna z tych rzeczy, o których bardzo łatwo zapomnieć.

11/09/2013

Nullable<T>.Equals(T value)

Home

Po dłuższej urlopowej przerwie w blogowaniu zacznę od zagadki z serii co zostanie wypisane na ekran, którą podsunął mi kolega Przemek:
decimal d = 2;

Console.WriteLine("d == 2 = {0}", d == 2);
Console.WriteLine("d == (decimal)2 = {0}", d == (decimal)2);

Console.WriteLine("d.Equals(2) = {0}", d.Equals(2));
Console.WriteLine("d.Equals((decimal)2) = {0}", d.Equals((decimal)2));
Tutaj jeszcze nie ma haczyka i odpowiedź to 4XTrue. Zmieńmy jednak jedną liniję:

decimal? d = 2;

Tym razem odpowiedź jest mniej oczywista. Na ekran zostanie wypisane: True, True, False, True. Czym więc różni się pierwsze wywołanie Equals od drugiego?

W obu przypadkach wołana jest metoda wirtualna. W obu przypadkach metoda ta wołana jest dla struktury Nullable<T>. Zmienna d nie jest null'em, a więc to też nie jest problemem. Spójrzmy zatem jak zaimplementowano Equals dla Nullable<T>:
public override bool Equals(object other)
{
    if (!this.HasValue)
    {
        return (other == null);
    }
    if (other == null)
    {
        return false;
    }
    return this.value.Equals(other);
}
Nic skomplikowanego, jeśli zmienna jest ustawiona to ponownie wywoływana jest metoda Equals w tym przypadku Decimal.Equals Odpowiedzi musimy szukać więc dalej. Wszystkie typy numeryczne mają przeciążoną metodę Equals w następujący sposób:
public override bool Equals(object value)
public override bool Equals(decimal value)
Która z nich zostanie wywołana w tej sytuacji? Nullable<T>.Equals ma parametr typu object, a więc Decimal.Equals(object value) pasuje lepiej niż Decimal.Equals(decimal value). Ta pierwsza działa natomiast w ten sposób, że jeśli przekazany parametr nie jest typu decimal to zawsze zwraca false nie sprawdzając czy przekazany obiekt można bezpiecznie konwertować na decimal. I ot cała tajemnica ;)

Moim zdaniem działanie Nullable<T> nie jest teraz intuicyjne. Wzorując się na typach numerycznych, można by dopisać do Nullable<T> jeszcze jedną metodę:
public bool Equals(T other)
{
    if (!this.HasValue)
        return false;

    return this.value.Equals(other);
}
Z jakiegoś powodu tego nie zrobiono. Przeoczenie czy celowe działanie? Jestem ciekawy Waszych opinii.