10/04/2014

Jak komputer wpływa na na...

Home

W książce Płytki umysł. Jak internet wpływa na nasz mózg Nicholas Carr napisał, że Internet jest wspaniałym narzędzie, ale równocześnie wpływa na nasz sposób myślenia w niekoniecznie pozytywny sposób. Jako przykład podaje obniżoną możliwość skoncentrowania się na lekturze długich tekstów czy to artykułów czy książek.

Uważam, że niestety jest w tym dużo prawdy. Z wnioskami poszedłbym nawet dalej. Tutaj nie chodzi tylko o Internet, ale o używanie komputera w ogóle. Ostatnio zaobserwowałem u siebie skłonność do wykonywania nawet prostych obliczeń przy pomocy systemowego kalkulatora. Robię to wręcz bezrefleksyjnie. Niby nie ma w tym nic złego ponieważ w ten sposób ograniczam możliwość pomyłki. Z drugiej strony pamiętam czasy kiedy dużo bardziej skomplikowane zadania matematyczne rozwiązywałem w pamięci, na przykład zdarzało się, że wracając z uczelni liczyłem w głowie całki ;).

Komputer to pożyteczne narzędzie, ale rozleniwia. Postanowiłem, więc pilnować się i teraz nawet jeśli siedzę przed komputerem to staram się wykonywać obliczenia w głowie i ewentualnie później je sprawdzam. Mała rzecz, ale odzwyczaja od używania komputera do wszystkiego, nawet do rzeczy, które z powodzeniem można zrobić samemu.

Jestem ciekaw czy zauważacie u siebie takie lub podobne nawyki/tendencje spowodowane spędzaniem dużej ilości czasu przed komputerem? Jak sobie z tym radzicie?

06/04/2014

Zależności funkcyjne - kiedyś mnie tego uczono

Home

Ostatnia przeglądając pytania na stackoverflow.com natknąłem się na takie dotyczące wyznaczania kluczy głównych na podstawie zależności funkcyjnych. Uczono mnie tego na studiach, ale obecnie w praktyce tego nie stosuję i kiedy projektuję bazę danych to nie zaprzątam sobie tym głowy.

Pytanie skłoniło mnie  jednak do odświeżenia sobie wiedzy i sięgnąłem po klasykę w tej dziedzinie czyli "Systemy baz danych" Connollly'ego raz Begg'a. Po kilku minutach lektury okazało się, że w głowie pozostało więcej informacji niż się spodziewałem. Doszedłem jednak do wniosku, że może i zabawa z zależności funkcyjnymi jest dobra dla naszych szarych komórek, ale jednak jest to żmudny proces i fajnie by to zautomatyzować.

Trochę poszperałem w Internecie i znalazłem narzędzie dostępne on-line, które na podstawie zależności funkcyjnych wyznacza klucze kandydujące, weryfikuje w której postaci normalnej jest baza danych itp. Ma ograniczenia, ale zamieszczam link ku pamięci. A to dwa przykłady użycia tego narzędzi do rozwiązania pytań zadanych na stackoverflow.com:
A tak na marginesie. Czy w swojej praktyce zawodowej stosujecie lub znacie kogoś kto stosuje przy projektowaniu relacyjnych baz danych zależności funkcyjne i na tej podstawie sprawdza czy baza danych jest w odpowiedniej postaci normalnej?

29/03/2014

Słów kilka na temat Attach to Process

Home

Post z serii ku pamięci, o poleceniu Debug->Attach to Processz, które umożliwia podczepienie się pod już uruchomiony program i jego debugowanie, a które znane jest chyba wszystkim programistom pracującym z Visual Studio. Rzadziej stosowaną i znaną opcją Attach to Process jest możliwość wybrania rodzaju kodu jaki chcemy debugować (Native, Managed, Script...). Służy do tego okno Select Code Type, które pojawia się po wybraniu przycisku Select. Domyślnie typ kodu określany jest automatycznie i w większości wypadków jest to najlepsza opcja, można to jednak zmienić i wybrać debugowanie kodu na przykład tylko dla platformy .NET w określonej wersji.


Problem z tą opcją jest taki, że jak już się jej użyje to łatwo o tym zapomnieć,a Visual Studio zapamiętuje wybrane ustawienia. Załóżmy, że wybraliśmy debugowanie kodu zarządzanego w wersji 3.5. Wszystko fajnie działa, ale po paru dniach chcemy debugować kod dla platformy 4.0. Podczepiamy się pod wybrany proces, a tu nic się nie dzieje, żaden z naszych breakpoint'ów nie zadział, a Visual Studio nie zgłasza żadnych problemów.

I bądź tu mądry człowieku w takiej sytuacji, albo sobie przypomnimy, że zmieniliśmy tą opcję (o ile wiemy jak dokładnie działa) albo będziemy sobie rwać włosy z głowy.

27/03/2014

SizeLimit, PageSize i dokumentacja

Home

W poście wspomniałem o właściwościach DirectorySearcher.SizeLimit oraz DirectorySearcher.PageSize, których poprawne ustawienie zapewnia, że z bazy danych AD można pobrać więcej obiektów niż ustawiony na serwerze limit. Tym razem chciałbym sprecyzować do czego służą obie właściwości bo moim zdaniem dokumentacja nie jest precyzyjna, co potwierdza zresztą spora liczba pytań w Internecie na ten temat.

Otóż SizeLimit określa maksymalną liczbę obiektów jaka może zostać zwrócona w wyniku wyszukiwania (zero oznacza brak limitu) przy czym limit ustawiony na serwerze ma priorytet. PageSize służy natomiast do skonfigurowania stronicowania i wartość różna od zera je włącza. Na przykład wartość 100 oznacza, że obiekty będą zwracane w paczkach po 100, przy czym .NET jest na tyle miły, że samemu obsługuje doczytywanie kolejnych stron.

Teraz spójrzmy na przykład. W bazie danych AD znajdowało się 1580 obiektów spełniających kryteria wyszukiwania, a limit ustawiony na serwerze wynosił 1500. Poniższa tabelka pokazuje ile obiektów zwróci zapytanie w zależności od ustawień.

SizeLimitPageSizeLiczba obiektów w ADLiczba zwróconych obiektówUwagi
0015801500Brak stronicowania + domyślny limit z serwera
10001580100Brak stronicowania + limit określony przez nas
010015801580Stronicowanie włączone
20010015801580Stronicowanie włączone + limit określony przez nas
1002001580100Stronicowanie włączone + limit określony przez nas

Dwa ostatnie scenariusze są trochę zagadkowe. W obu przypadkach obie właściwości są różne od zera, ale liczba zwróconych obiektów jest inna tj. jeśli SizeLimit > PageSize to z AD pobrano wszystkie dostępne obiekty, a w przeciwnym wypadku tyle ile wynosił SizeLimit. Przypuszczam, że DirectorySearcher działa tak, że pobiera dane póki nie zostanie przekroczony limit. W pierwszym przypadku przy pobieraniu kolejnych stron liczba pobieranych obiektów nie przekracza limitu, a więc udało się odczytać wszystko. W drugim wypadku już przy pobraniu pierwszej strony liczba obiektów przekroczyła limit i dalsze pobieranie zostało zakończone. Pewnie można było to zaimplementować inaczej, ale cóż zrobić i po prostu warto o tym wiedzieć.

18/03/2014

Jak napisać szybki program pobierający dane z AD

Home

Post ten dotyczy tematu efektywnego pobierania danych z Active Directory. Załóżmy, że chcemy pobrać listę użytkowników przy czym interesują nas tylko niektóre właściwości, które ich opisują. Pokażę trzy niewiele różniące się z pozoru sposoby odczytania potrzebnych nam danych. Pozornie ponieważ te trzy podejścia znacząco różnią się wydajnością. W celu zademonstrowania różnic napisałem prostą klasę ADTester. Zawiera ona tylko jedną metodę Run w parametrach, której określamy tryb działania oraz liczbę obiektów do pobrania. Różnica pomiędzy trybami jest następująca:
  • W trybie szybkim (Mode.Fast) dla każdego obiektu z bazy danych Active Directory pobrane zostają tylko wybrane 4 właściwości, a to dzięki zastosowaniu właściwości DirectorySearcher.PropertiesToLoad
  • W trybie normalnym (Mode.Normal) dla każdego obiektu z bazy danych Active Directory pobrane zostają wszystkie dostępne dla danego obiektu właściwości.
  • W trybie wolnym (Mode.Slow) zamiast użyć danych zawartych w obiektach SearchResult korzystam z metody SearchResult.GetDirectoryEntry.
Poniższa tabela pokazuje czas działania programu w ms w zależności od trybu działania oraz liczby obiektów do pobrania:

maxNumberOfObjectsMode.FastMode.NormalMode.Slow
1003634637507
2004076611600
500797221239323
10001353306075935

W najlepszym przypadku tryb prosty jest 2.7 szybszy niż tryb normalny i prawie 60 razy szybszy niż tryb wolny. Różnica jest wręcz powalająca, a wnioski nasuwają się same.
  • Jeśli z góry wiemy jakie właściwości nas interesują to używajmy właściwości DirectorySearcher.PropertiesToLoad.
  • Korzystajmy z danych zwróconych przez klasę DirectorySearcher w postaci obiektów SearchResult.
  • Tylko jeśli to absolutnie konieczne korzystajmy z metody SearchResult.GetDirectoryEntry. Taka potrzeba zachodzi na przykład wtedy jeśli chcemy zmodyfikować dane w AD.
Na koniec jeszcze jedna uwaga. Wyniki czasu działania programu będą się różnić w zależności od tego gdzie znajduje się serwer Active Directory. W moim przypadku znajdował się on poza krajem. Na koniec zamieszczam kod programu do własnych testów:
public class ADTester
{
    public enum Mode { Fast, Normal, Slow }

    public void Run(Mode mode, int maxNumberOfObjects)
    {
        var ldapPath = "YOUR_LDAP_PATH";

        using (var root = new DirectoryEntry(ldapPath))
        {
            using (var searcher = new DirectorySearcher(root)
                    {
                        Filter = "(&(objectClass=user))", SearchScope = SearchScope.Subtree, SizeLimit = maxNumberOfObjects
                    })
            {
                if (mode == Mode.Fast)
                    searcher.PropertiesToLoad.AddRange(new[]{ "displayName","name", "pwdLastSet","userAccountControl" });

                using (SearchResultCollection searchResult = searcher.FindAll())
                {
                    foreach (SearchResult user in searchResult)
                    {
                        if (mode != Mode.Slow)
                        {
                            var displayName = user.Properties["displayName"];
                            ...
                        }
                        else
                        {
                            var entry = user.GetDirectoryEntry();
                            var displayName = entry.Properties["displayName"];
                            ...
                        }
                    }
                }
            }
        }
    }
}