14/09/2010

Powrót do Ojczyzny

Home

Powrót do Ojczyzny to nazwa inicjatywy na rzecz ustawy o powrocie do Polski osób deportowanych lub zesłanych za czasów ZSRR. Jeszcze kilka dni temu nie wiedziałem, że taki ruch obywatelski istnieje i niewiele brakowało, a nie złożyłbym swojego podpisu pod projektem ustawy, a potrzeba ich 100 tysięcy aby trafił do sejmu. Do 14 września czyli ostatniego dnia trwania akcji zebrano 93480 głosów czyli bardzo dużo ale niestety za mało. Nowa ustawa jest ważna ponieważ przy obecnych rozwiązaniach prawnych czas oczekiwania na powrót do Polski może sięgać nawet 7-10 lata.

O akcji dowiedziałem się od żony, która zaproponowała, że po pracy przejdziemy się na Krakowskie Przedmieście 64 i złożymy podpisy. Podpis można było oczywiście wysłać pocztą ale nawet polecony nie zostałby doręczony w tak krótkim czasie. Wysiłek nieduży, a można komuś pomóc. Przy okazji postanowiłem spytać kolegów z pracy czy chcą złożyć podpis i w ciągu 2 godzin uzyskałem dodatkowe 12 głosów! Na Krakowskie Przedmieście spotkałem jeszcze sporą grupę ludzi myślących podobnie, część tak jak ja przyniosła listy z podpisami, inni przyszli się podpisać.

Jeśli ustawa wejdzie w życie będzie oczywiście kosztować. Według projektu ustawy potrzebnych będzie rocznie ok. 100 mln. Tu duże pieniądze ale ja wolę aby moje podatki były przeznaczane na takie szczytne rzeczy niż na ... i tutaj każdy może wpisać wiele pozycji w budżecie, które przejadają nasze pieniądze.

A teraz trzymam zaciśnięte kciuki żeby starczyło podpisów, okaże się jutro rano.

Internal .Net Framework Data Provider Error 30

Home

Ostatnio mam szczęście do "dziwnych" błędów. Dwa dni temu pisałem o htmlfile: Access Denied. Przy okazji podziękowania dla Tomka i Procenta za wskazówki jak sobie z nim poradzić. Teraz natknąłem się na błąd z zupełnie innej beczki związany z komunikacją z bazą danych. Zadanie do wykonania: wywołać procedurę składowaną. Zabrałem się do tego jak zawsze czyli nawiązałem połączenie do bazy danych, utworzyłem DbCommand, dodałem parametry, ustawiłem wartości parametrów i wywołałem procedurę. Niestety tym razem zamiast przejść do dalszej części zadania otrzymałem błąd Internal .Net Framework Data Provider Error 30. Konia z rzędem temu kto powie co ten błąd oznacza. Przeglądam kod jeszcze raz ale wszystko wygląda prawidłowo. Zresztą robiłem to już setki razy i działało. Jedyna różnica to taka, że teraz pracuję z bazą danych Oracle, a nie z bazą Microsoftu.

Od czego ma się jednak kolegów? Wysłałem maila z pytaniem czy ktoś już spotkał się z tym problemem i opłaciło się. Szybko uzyskałem wskazówkę, że błąd może być związany z błędną nazwą parametru i okazało sie to, że tak jest. W swoim kodzie użyłem metody, która w zależności od typu bazy danych zwraca odpowiednio przygotowany parametr nazwany. W przypadku Oracle parametry nazwane poprzedzone są dwukropkiem np.: :name, :date ale nie w przypadku przekazywania parametrów do procedury składowanej!!! Wspomniana metoda nie uwzględniała tego i stąd błąd. Inna sprawa to dlaczego sterownik Oracle nie ukrywa tej różnicy przed programistą oraz czemu ten błąd jest komunikowany w taki mało zrozumiały sposób.

Na zakończenie chciałbym podziękować Pawłowi za pomoc w rozwiązaniu problemu.

09/09/2010

htmlfile: Access Denied

Home

FileUploader to kontrolka, która umożliwia wybranie pliku przez użytkownika i przesłanie go na serwer. Po umieszczeniu na stronie renderuje się do pola tekstowego i przycisku Przeglądaj. Ja chciałem uzyskać efekt, w którym kontrolka ta jest ukryta, użytkownik naciska pewien przycisk, wyświetlane jest okienko do wyboru pliku, a następnie plik przesyłany jest na serwer. Zrobiłem to przy pomocy odrobiny JavaScript'u.
    function chooseFile()
    {
        var uploader = document.getElementById("<%= this.Uploader.ClientID %>");
        uploader.click();
    }

    function submitFile() 
    {
        document.forms[0].submit();
    }
Pierwsza funkcja chooseFile znajduje na stronie kontrolkę i wymusza kliknięcie na nią czyli powoduje wyświetlenie okienka do wyboru pliku. Druga funkcja po prostu przesyła stronę na serwer. Kontrolka i przycisk zostały osadzone na stronie w sposób pokazany poniżej:
    ...
    <asp:Button ID="Upload" runat="server" OnClientClick="chooseFile();" Text="Wybierz plik"/>
    ...
    <asp:FileUpload ID="Uploader" runat="server" style="display:none" onchange="submitFile();" />
     ...
Dzięki ustawieniu atrybutu display na wartość none kontrolka renderuje się do kodu HTML nie jest natomiast widoczna dla użytkownika. Po napisaniu kodu uruchamiam stronę, wybieram przycisk Wybierz plik i ku mojemu zadowoleniu pojawia się okienko do wyboru pliku. Wybieram interesujący mnie plik i na tym niestety kończy się zabawa, a pojawia się problem. W linii zawierającej document.forms[0].submit(); raportowany jest błąd htmlfile: Access Denied.

Sprawdzam jeszcze raz te kilka linijek kodu ale wyglądają prawidłowo. No dobrze, a może błąd jest spowodowany tym, że schowałem kontrolkę. Usuwam atrybut style i próbuję jeszcze raz ale błąd znowu się pojawia. Teraz kontrolka jest widoczna, więc sprawdzam co się stanie kiedy nacisnę przycisk Przeglądaj samemu, a nie przy pomocy JavaScript'u. Próbuję i tym razem wybrany plik został przesłany na serwer! Dla pewności powtarzam eksperyment jeszcze raz i ponownie sukces. Innymi słowy błąd pojawia się jeśli kontrolka do wyboru pliku zostanie kliknięta z poziomu kodu.

Więcej pomysłów nie mam, a więc zaglądam do Google i od razu widzę kilku nieszczęśników z podobnym problemem jak mój. Niestety zamiast rozwiązania problemu znajduję tylko informację, że błąd ten związany jest z jakimś mechanizmem bezpieczeństwa, który nie pozwala wysyłać plików bez wiedzy użytkownika. Sprawdzam jeszcze jak sytuacja wygląda w innych przeglądarkach (Opera i Firefox) i błąd się nie pojawia ale to dlatego, że nie działa kod uploader.click(); i okienko do wyboru pliku nie wyświetla się.

Jedyne co mi jeszcze przychodzi do głowy do wypróbowanie innych kontrolek do wyboru plików np.: Talerik'a. Dopóki nie znajdę obejścia problemu będę natomiast stosował tradycyjne podejście do zagadnienia czyli pozwolę użytkownikowi samemu nacisnąć przycisk.

31/08/2010

Jeden duży projekt, czy może wiele małych 2

Home

Publikując artykuł na temat "małych" i "dużych" byłem ciekawy opinii innych ludzi z branży. Pierwszy odzew otrzymałem od kolegi ze studiów Marka Kozłowskiego i za jego zgodą przedstawiam go poniżej.

Marek po przeczytaniu postu wyraził zdziwienie, że taki temat w ogóle pojawił się w rozmowie, a rozbicie kodu na podprojekty jest dla niego czymś naturalnym i oczywistym. Stwierdził również, że nie wyobraża sobie pracy z jednym dużym projektem (Aspekt psychologiczny), na który składa się na przykład 100 plików z kodem zawierających wszystko począwszy od logiki biznesowej, przez konwersję obiektów biznesowych na obiekty bazy danych, po warstwę dostępu do danych oraz interfejsy i implementację obiektów zdalnych. Przytoczył również taki przykład.

Wyobraźmy sobie, że piszemy projekt, który ma realizować funkcjonalność zarządzania magazynem i składa się (w skrócie) z warstwy prezentacji, warstwy logiki biznesowej oraz warstwy dostępu do bazy danych. Jest to prosta aplikacja desktopowa, a implementacje poszczególnych warstw znajdują sie w osobnych projektach (Wymusza poprawną architekturę). Po roku klient prosi o przygotowanie tej samej aplikacji ale w wersji WWW. Co robimy? Budujemy interfejs użytkownika WWW ale dalej korzystamy z tego samej logiki biznesowej i warstwy dostępu do bazy danych (Łatwiejsze użycie tego samego kodu w innym projekcie biznesowym). Innymi słowy bierzemy sobie dwie dll'ki i dodajemy do referencji aplikacji WWW.

Jak by to wyglądało w przypadku jednego dużego projektu? Albo musielibyśmy kopiować kod między projektami co doprowadziło by do redundancji i konieczności poprawiania tych samych błędów w dwóch projektach albo dodalibyśmy do projektu interfejsu WWW referencję do jednej dużej biblioteki albo nawet pliku exe!!!, która zawierać będzie wiele niepotrzebnych rzeczy.

Na koniec Marek słusznie zauważył, że wraz z wprowadzeniem obiektowych języków programowania nastąpił czas tworzenia pakietów, bibliotek, które tworzą sieć powiązań oraz, że jest to wręcz intuicyjne i naturalne.

Opinia Marka jest więc zgodna z moim zdaniem, co mnie bardzo cieszy, ale kij ma zawsze dwa końce. W najbliższej przyszłości postaram się, więc znaleźć i zachęcić do wypowiedzi kogoś z przeciwnego obozu.

15/08/2010

Jeden duży projekt, czy może wiele małych

Home

Kilka dni temu dyskutowałem z kolegą na temat tego czy całość/większość kodu powinna być umieszczona w jednym dużym projekcie (jak On uważa) czy rozłożona pomiędzy mniejsze projekty (jak uważam Ja). Przez projekt rozumiem tutaj jednostkę organizacji kodu np.: csproj w Visual Studio. Duży projekt to dla mnie taki, który zawiera wszystko czyli: implementację GUI, logikę biznesową, interfejsy, struktury danych, klasy dostępu do danych itd. Może się to przekładać na liczbę linii kodu ale nie musi. Dalej, aby odróżnić projekt jako jednostkę organizacji kodu od projektu jako przedsięwzięcia biznesowego będę używał sformułowania projekt biznesowy dla tego drugiego.

Wracając do wspomnianej dyskusji to zakończyła się impasem ponieważ żaden z nas nie zmienił swojego zdania. Spowodowała jednak, że postanowiłem jeszcze raz gruntownie przemyśleć sprawę. W ten sposób powstała poniższa lista zalet i potencjalnych wad małych projektów. Listy te są skonstruowałem w ten sposób, że na początki znajdują się najważniejsze/najpoważniejsze zalety i wady.

Zalety
  • Łatwiejsze użycie tego samego kodu w innym projekcie biznesowym. Przy dużych projekcie również jest to możliwe ale oznacza dodanie referencji do wielu innych niepotrzebnych w danym kontekście rzeczy czyl bałagan.
  • Wymusza poprawną architekturę. Na przykład jeśli GUI, logika biznesowa i dostęp do bazy danych znajdują się w innych projektach to projekt z GUI będzie miał referencję na projekt z logiką biznesową ale nie na odwrót ponieważ referencje cykliczne nie są dozwolone.
  • Ułatwia dalszy rozwój. Wyobraźmy sobie sytuację, w której projekt biznesowy jest na etapie stabilizacji i zbliża się termin oddania. Z drugiej strony istnieje konieczność dalszego rozwijania jakiejś jego części. Po wdrożeniu klient zapewne będzie zgłaszał błędy. Po jakimś czasie może pojawić się potrzeba złączenia (merge) dwóch (lub więcej) ścieżek rozwoju czyli przeniesienia poprawek błędów z wersji produkcyjnej na rozwojową i dodanie nowych funkcji z wersji rozwojowej do wersji produkcyjnej. W przypadku małych projektów łatwiej zorientować się co się zmieniło, co trzeba przenieść, a co nie, czy merge spowoduje jakieś błędy itd.
  • Aspekty psychologiczne. Nie przytłacza liczbą plików i folderów. Łatwiej zorientować się "o co biega" - łatwiej jest pracować z małym projektem odpowiedzialnym za jedną konkretna rzecz niż z dużym odpowiedzialnym za dziesiątki różnych rzeczy.
  • Łatwiejsze utrzymanie testów jednostkowych. W przypadku podejścia, w którym testy jednostkowe są umieszczane w innym projekcie niż testowany kod będzie mieli kilka małych projektów z testami jednostkowymi. W podejściu przeciwstawnym w danym projekcie będziemy mieli ograniczoną liczbę testów dotyczących tego jednego projektu. Należy to przeciwstawić dużym projektom gdzie powstanie nam albo kolejny duży projekt na testy jednostkowe albo bardzo duży projekt zawierający wszystko plus jeszcze testy jednostkowe tego wszystkiego.
  • Prostsze i łatwiejsze w utrzymaniu pliki konfiguracyjne. Ma to znaczenie jeśli używamy technologii wymagających wielu plików konfiguracyjnych, najczęsciej dokumentów XML np.: Spring.
  • Krótsza kompilacja. Jeśli nie zmieniły się interfejsy to można skompilować pojedynczy, mały projekt.
  • Wykonywanie brancha małego projektu trwa szybciej
Wady
  • Defragmentacja pamięci. Pisałem o tym już wcześniej. Problem polega na tym, że przy ładowaniu do pamięci moduły nie są ustawiane jeden po drugim ale są umieszczane w "losowo" wybranych miejscach co powoduje poszatkowanie pamięci. W większości wypadków nie jest to problemem ale na przykład przy alokacji dużej bitmapy potrzebny jest ciągły obszar pamięci. W wyniku defragmentacji system będzie dysponował dostatecznie dużą ilością pamięci ale nie w jednym kawałku. Problem nie występuje na systemach 64-bitowych, które są coraz powszechniejsze.
  • Dłuższe uruchamianie VS. Jeśli utworzymy Solution i dodamy do niego kilkadziesiąt projektów to jego otwieranie będzie trwać długo. Z drugiej strony czy aby na pewno praca z kilkudziesięcioma projektami ma sens?
  • Konieczność zarządzania dużą liczbą referencji. Każdy lub prawie każdy projekt będzie miał kilka lub więcej referencji do innych projektów. Zgadzam się, że może to być problem. Z drugiej strony pracowałem przy rozwijaniu naprawdę dużego systemu składającego się z kilkunastu podsystemów, każdy z kilkunastoma małymi projektami z czego część była współdzielona i radziliśmy sobie.
  • Trudniejsza instalacja. Wynika to z dużej ilości bibliotek dll, które powstają w wyniku kompilacji wielu małych projektów. Mogą również wystąpić konflikty wersji. Podobnie jak wyżej zgadzam się, że jest to możliwe ale podobnie jak wyżej przeciwstawiam tej wadzie swoje doświadczenie, które mówi co innego.
  • Dłuższa kompilacja całego systemu. Zgadzam się, przy wielu małych projektach kompilacja wydłuży się i to znacznie. Jednak i tutaj dołożę swoje trzy grosze. Jak często istnieje potrzeba przekompilowania całego systemu? Jeśli w danym momencie pracujemy z kilkoma konkretnymi projektami to po co wykonywać build wszystkich pozostałych? Ma to sens, jeśli zostały zmienione klasa, struktury lub interfejsy używane w wielu innych projektach.
  • Problemy z konfiguracją tych samych rzeczy w różnych projektach. Przy odpowiedniej architekturze systemu i zastosowaniu odpowiednich wzorców projektowych (singleton, fabryka) nie jest to dla mnie żaden problem.
  • Zwiększony czas uruchamiania aplikacji. Tak ale o ułamki sekund.
Ponieważ w powyższych wyliczeniach powoływałem się na to, że coś trwa tyle, a tyle przytoczę bardzo fajne zestawienie porównujące czasy kompilacji, ładowawania solution'a przez Visual Studio itd. dla różnej liczby projektów, które pojawiło sie w dyskusji na portalu stackoverflow - odpowiedź autorstwa jerryjvl'a.

Reasumując jestem przekonany, że zalety dzielenia kodu na małe projekty przeważają potencjalne wady. Co więcej uważam, że problemy z małymi projektami wynikają głównie ze złego podejścia i przyjęcia nieodpowiednich rozwiązań takich jak: budowanie wszystkich projektów zamiast kilku wybranych lub z dogmatycznego trzymania się małych projektów czyli bezrefleksyjnego tworzenia małego projektu na wszystko co się da. Co za dużo to jednak nie zdrowo :)

Na koniec jedna uwaga. Na początku projektu biznesowego może się wydawać, że lepiej trzymać wszystko w dużym projekcie bo tak prościej, bo kodu mało. Ale o ile nie jest to rzeczywiście malutki projekt biznesowy to szybko okaże się, że podzielenie kodu na mniejsze projekty będzie wymagać tyle pracy, że nikomu nie będzie się tego chciało zrobić.