Przez ostatnie trzy tygodnie mam przyjemność bawić się SDK dla Silverlight i WPF dostępu do serwerów map firmy ESRI. Po tych tygodniach mogę powiedzieć na pewno, że forum ArcGIS jest jednym z najgorszych, na jakie natrafiłem w ostatnich latach. Nie tylko pod względem zawartości (która jest rozbita pomiędzy starą wersją, jak i nową) czy też funkcjonalności wyszukiwania, ale przede wszystkim pod względem odpowiedzi lub braku odpowiedzi.

Nie zależnie gdzie się pójdzie czy to będą devpytania, StackOverflow, MSDN Forums czy też Telerik Forums na odpowiedź długo czekać nie trzeba – nawet jeżeli będzie ona typu: RTFM, ale będzie. Ja na forum ArcGIS czekam średnio dwa tygodnie na jakąkolwiek odpowiedź a jak już ktoś odpowiada – nawet pracownik ESRI, to odpowiedź brzmi „u mnie działa, masz coś źle”. Sorki ale to nie jest miejsce dla osób poszukujących wiedzę. Zaś dokumentacja API jest szokująco podobna do Ctrl+Shift+D w GhostDoc:

arg_gis_000

albo lepiej, dokładniejsza dokumentacja jest dla typów internal zamkniętych w bibliotece – dowód?

arg_gis_001

Ja tego po prostu nie rozumiem :) A w tym „useful” to się po prostu zakochałem :)

Wracajmy jednak do tematu. Przy wykorzystaniu w naszej aplikacji warstwy prezentacji ArcGISDynamicMapServiceLayer (służącej do prezentowania dynamicznie ładowanych obrazków z serwera – bez ich wcześniejszego z cachowania – za pomocą usługi REST), mamy możliwość określenia widocznych warstw, które mają być zwrócone po odpytaniu usługi REST. Wszystkie te widoczne warstwy przypisujemy do tablicy int VisibleLayers (wartością jest ID warstwy). Zaraz po przypisaniu, generowany jest odpowiedni request, który może trwać do kilku sekund i zwracany nam jest obrazek, który może być wielkości 100KB jak nie większej (lub mniejszej). Takie odpytanie jest robione za każdym razem, kiedy zmienimy zawartość VisibleLayers czy też kiedy zmienimy obszar widoczności mapy (zoom in/out, przesunięcie w bok itp.), działa to mniej więcej na tej samej zasadzie co Google Maps czy Bing Maps – obrazki które nie są wyświetlane w danym momencie nie są ładowane.

By mieć pewność, iż obrazek wyświetlany jest zaktualizowany (uległ zmianie od ostatniego ściągnięcia), ArgGISDynamicMapServiceLayer udostępnia nam możliwość określenia czy odpowiedź serwera ma nie być cachowana w naszej przeglądarce – DisableClientCaching. Domyślnie cachowanie jest włączone. Dzięki czemu jeżeli będziemy ładować te same dane dla VisibleLayers w takim samym obszarze mapy, to obrazek zostanie zwrócony z serwera tylko raz a następnie będzie on wykorzystywany ponownie. Przynajmniej takiej jest założenie.

Niestety nie działa to tak jak powinno – przynajmniej moim zdaniem, ale o tym później. Okazuje się, iż kolejność przekazywanych IDków warstw ma kolosalne znaczenie. Dla przykładu (przy założeniu, iż cachowanie nie jest wyłączone, oraz nie robimy zoom in/out i nie zmieniamy obszaru wyświetlania danych):

  1. Jeżeli przekażemy ID {1,2} do VisibleLayers, zostanie utworzony request i obrazek zostanie nam zwrócony;
  2. Jeżeli teraz wyzerujemy VisibleLayers {}, obrazek nam zniknie, request nie zostanie wywołany gdyż „background” mamy już załadowany;
  3. Jeżeli znów przekażemy ID {1,2} do VisibleLayers, zostanie nam zwrócony obrazek z cachu przeglądarki;
  4. Jeżeli teraz przekażemy ID {2,1} do VisibleLayers, zostanie utworzony request i obrazek zostanie nam zwrócony;
  5. Reszta działa tak jak w punkcie 2 i 3.

Ok, takie działanie miałoby ręce i nogi gdyby obrazek zwracany różnił się i gdyby kolejność ID miała znaczenie, niestety przy serwerze REST kolejność ID nie ma znaczenia gdyż zdefiniowana ona jest w pliku MDX na serwerze. Więc jeżeli chcemy zwrócić warstwy {1,2} zaś MDX ma kolejność {2,1} to zostanie nam zwrócony obrazek zgodnie z kolejnością MDX czyli {2,1}.

Co takie zachowanie powoduje? Jeżeli damy użytkownikowi końcowemu możliwość wybierania widocznych warstw na mapie, to dla zbioru n warstw (przy założeniu, że zawsze na tym samym zbiorze operujemy i zawsze pokazujemy n warstw) możemy wygenerować n! (silnia) requestów, które ściągną nam ten sam obrazek n! razy. Teraz wyobraźcie sobie, iż operujecie na 4 warstwach, obrazek zwracany jest wielkości 100KB. 4 warstwy to 24 kombinacje, które użytkownik może sobie wybrać, dające łącznie ~2,5MB ściągniętych danych tego samego obrazka, nie różniącego się niczym od tego jak go raz nam się udało pobrać.

Dzieje się tak gdyż w bebechach SDK istnieje sobie taki fragment kodu:

arg_gis_002

Który nie zwraca uwagi na kolejność przekazanych ID. Przez co request idący do serwera różni się tylko i wyłącznie tym fragmentem zamiast 1,2 w stringu jest 2,1 co oznacza inne zapytanie (i słusznie przeglądarki tak to rozumieją), zaś dla serwera ArcGIS nie ma to żadnego znaczenia.

Rozwiązanie problemu jest dość proste, wystarczy posortować tablicę przed przypisaniem jej do VisibleLayers, dzięki czemu zachowany zawsze taką samą kolejność i zamienimy n! requestów na 1 request.

Teraz wracając do „nie działa to jak powinno – przynajmniej moim zdaniem”. Napisałem na forum ArcGIS o tym i dostałem odpowiedź, że jest to szczególny przypadek, który powinien obsłużyć programista. Ja się z tym nie zgadzam, z kilku powodów:

  1. Programista o tym nie wie – ja się dowiedziałem przypadkiem, kiedy bawiłem się FireBugiem, dokumentacja zaś na ten temat całkowicie milczy;
  2. Kontrolka umożliwia wyłączenie cachowanie zwracanych wyników przez przeglądarkę – czyli pozostałe wyniki powinny być cachowane;
  3. Kolejność VisibleLayers nie ma znaczenia dla serwera ze względu na plik MDX;
  4. Istnieje taka dokumentacja do klasy internal którą wkleiłem wyżej mówiąca „The throttle timer is useful for limiting the number of requests” – w typ wypadku Throttle jest wykorzystywany do ograniczenia odpytywania REST przy zoom in/out, niestety działa to jak działa ale nie o tym jest ten post, to co jest ważne to to, iż goście od ESRI chcą ograniczyć liczbę requestów… ale chyba tylko w tedy kiedy jest im wygodnie.

Jak dla mnie jest to funkcjonalność, którą powinna dostarczyć kontrolka a nie programista. A jakie jest wasze zdanie? Powinno to być pozostawione programistom z odpowiednią adnotacją w dokumentacji, czy skoro nie ma znaczenia kolejność przekazywanych warstw to powinna to obsłużyć kontrolka?

2 KOMENTARZE

  1. Miałem przyjemność (wątpliwą) pracować jakieś 5 lat temu z kontrolkami firmy ESRI, tylko że to była aplikacja w Javie, na dodatek desktopowa – ArcServer dopiero był później w powijakach, ale jakoś mnie nie zachwycił wtedy. Pamiętam to makabryczne forum, zgłaszałem nawet bugi w API, byłem odsyłany do "polskiego oddziału", tam "pan Kazio" przeklejał mój email "panu Johnowi" z oddziału w USA, wyszło przypadkiem, potem dogadałem się już z docelowym odbiorcą i pomijałem tzw "polski oddział".

    Ale to nie o tym komentarz, to API było z grubsza fajne, ale pochodziło z zamierzchłych czasów kiedy VisualBasic miał swój szczyt popularności. Czy dalej tak jest Kubo? Dziwaczne proxowanie obiektów, worek train-crash methods. etc? Pamiętam, że cała aplikacja oczywiście okazała się wielkim sukcesem, ale programistycznie – to jak z komunizmem – składało się z bohaterskiego zmagania się z problemami, które nie występują nigdzie indziej. Np. żeby mapa się cachowała, trzeba było pokazać okienko About :) (!), oczywiście oprogramowane zostało to w ten sposób, że DLL zdejmował modalność i otwierał to okienko o rozmiarze 1×1 piksela. Ciekawe czy jakbym dzisiaj w jakiś sposób uzyskał dostęp do obecnej wersjii tego kodu, czy znalazłbym tam to "cudo" :)

    Ale to znowu nie o tym… otóż jak się dowiedziałem przebywając po drugiej stronie stawu – dokumentacja jest w większości przypadków wygenerowana automatycznie (przynajmniej ta dla C# i Java, natomiast kluczem było zerkanie w dokumentację dla VisualBasica – tam było wszystko wytłumaczone, a koszmar architektoniczny osiągnięty podczas portowania 1:1 aplikacji na API Javy – okazał się umożliwiać praktycznie dosłowne wykorzystanie przykładów i podpowiedzi :).
    Z drugiej strony, osoby które uczyły się w college’ach np. Rutgers, albo King’s miały możliwość w ramach stażu – na kierunku Computer Science – pobawić się całym stackiem technologicznym firmy ESRI. I wiesz co się okazało? Gość, po półrocznych praktykach miał tę samą wiedzę praktyczną dotyczącą bibliotek, co ja po roku użerania się z wybrakowaną dokumentacją, opieszałą obsługą w ESRI polska i enigmatycznym "u mnie działa" forum. Rezultat oczywisty – gdzie nam do takiej ameryki, ale jednak software "u nas" powstaje, szkoda tylko, że nie są dostępne szkolenia o podobnej jakości co za oceanem. Nie wiem jak jest teraz, ale kilka lat temu brałem udział w szkoleniach ESRI, niestety były tak lapidarne, że szkoda gadać. Rozumiem konieczność podążania za międzynarodowym podręcznikiem, jednak prowadzący mógłby odrobić swoją "pracę domową" i chociaż zerknąć w ćwiczenia które będzie prowadził. Odpowiedz na podstawowe pytanie – zadawane przez kursanta, który powinien mieć zerową wiedzę w temacie, typu "nie wiem, nigdy tego nie robiłem" jest karygodna.

  2. Przejrzałem kilka sesji Deep Dive firmy ESRI i zrozumieć o co chodzi w warstawch i jak mozna je wykorzystac. Kazda sesja trwała około 1h i pochodziła z konferencji z 2009 i 2010 roku. Lacznie bylo ich az 3-4 (nie za duzo) jednakze na kazdej z nich byl taki sam wstep 15 minutowy ktory tlumaczyl co to jest WPF i Silverlight – halo, to ma byc sesja deep dive? a nastepnie gosciu pokazywal prosty przyklad ladowania mapy lub pokazywal istniejace przyklady (w sensie zobaczcie co mozna zrobic a nie jak mozna zrobic). Wiedzy nie wyciagnalem zadnej, 4h zmarnowane jak nie wiem co. Wiec chyba sie nic nie zmienilo.

    Dodatkowo dokumentacja do WPF i SL jest jedyna w swoim rodzaju bo nie ma odpowiednika w innym jezyku – no chyba ze flex, js, ale to znow jest taka sama dok. tak jak wspomnialem jakby generowana za pomoca GhostDoc.

    Zalamujace jest to iz nawet odkrylem ich system zglaszania nowych funkcjonalnosci albo naprawiania istniejacych. Dopiero przy 2300 glosach rzecz zaczyna byc rozpatrywana przez ESRI… 2300 glosow, a nie dawno @KKozmic chcial 15 by zaimplementowac funkcjonalnosc…

    no nic, musze sie przemeczyc z tym, do tego sie mecze jeszcze z MVVM co nie jest takie proste gdyz nie wszedzie wspieraja bindowanie :/ przez co wychodzi niezla miasga :)

Comments are closed.