Dlaczego XML odniósł sukces?
Sporo uczonych słów na ten temat napisano, najczęściej próbując dorobić różne złożone ideologie. A tymczasem, kluczem do sukcesu XML były te same dwa czynniki, które stały za sukcesem sieci WWW:
- prostota,
- łatwa amortyzacja zmian.
A przynajmniej, to o nie chodziło w zastosowaniach, którym chcę poświęcić ten artykuł: budowaniu API komunikacyjnych, procesach wymiany danych, integracji systemów.
Pęd ku XML jako wewnętrznemu formatowi danych aplikacji czy formatowi plików konfiguracyjnych był wtórny i wynikł z pojawienia się poręcznych bibliotek i popularyzacji hasła jako takiego. XML jako format wymiany dokumentów to niezależna historia ale nosząca wiele podobieństw.
Prostota
Najpierw o prostocie. Co robił pod koniec zeszłego tysiąclecia człowiek próbujący skomunikować ze sobą dwa systemy czy komponenty?
Albo tworzył jakiś własny binarny protokół, albo podpierał się protokołami systemów middleware, od OLE2/DCOM, CORBA czy DCE RPC, po pomysły z dużych middleware firm BEA, DEC czy IBM.
Tak czy siak sprowadzało się to najczęściej do napisania zbioru deklaracji w dedykowanym języku - czasem były to tylko deklaracje formatów danych, czasem całych interfejsów. Potem te deklaracje były kompilowane specjalizowanym narzędziem, powstawał z nich kod (jakieś szkielety do wypełnienia po stronie serwerów, proxy umożliwiające wywołania po stronie klientów). Dużo żmudnej pracy, wiele kroków do wykonania przed dojściem do pierwszego udanego testu, złożone procedury buildów i dystrybucji, trudny debugging i wyszukiwanie błędów, oczywiście konieczność posiadania tych samych narzędzi przez wszystkich tworzących komponenty. I jeszcze prowokujący błędy projektowe święty Graal twórców tych systemów, czyli tworzenie ułudy iż zdalne wywołanie jest tym samym co lokalne.
Wywołanie zdalnej usługi nie jest wywołaniem lokalnej procedury. Im lepiej programista to widzi, tym lepiej dla systemu, który tworzy. A zwłaszcza dla wydajności, bezpieczeństwa i obsługi błędów.
XML wprowadził tu niesamowity powiew świeżości i prostoty. W najprostszym ujęciu komunikat można było udokumentować przykładem, złożyć go konkatenując stringi, wyjąć potrzebne dane prostym parserem, a nawet wyrażeniem regularnym. Autorzy różnych komponentów mogli używać różnych narzędzi i języków. A przede wszystkim ... wszystko było widać.
Pisałem jakiś czas temu o znaczeniu małych sukcesów. Liczne projekty wymagające komunikacji XMLowej zaczynały się od ręcznego napisania tekstu XML w edytorze, wysłania go z palca i oglądania otrzymanej odpowiedzi. Szybki, bezpośredni efekt. Dodajmy jeszcze, że znaczenie treści dało się zwykle odgadnąć nawet bez formalnej dokumentacji.
No i klient wysyłał:
<get-client-contact-information>
<client-id>3344343434</client-id>
</get-client-contact-information>
serwer odpowiadał:
<client-contact-information>
<address>
<country>Polska</country>
<city>Warszawa</city>
<zip-code>01-711</zip-code>
<street>Wrocławska</street>
<house>17</house>
<flat>15</flat>
</address>
<phone country="48" area="22">8873311</phone>
</client-contact-information>
i obie strony były zadowolone.
Czasem występowały drobne kontrowersje (powiedzmy dyskusja, czy flat
jest obowiązkowe, czy krajem ma być Polska
, Poland
czy może PL
,
jakie właściwie mamy kodowanie znaków), czasem ktoś próbował
szczególnie dziwnych metod (zdarzyło mi się zderzyć z kooperantem,
który parsował XML przy pomocy gramatyki napisanej w Bisonie,
uwzględniającej konkretne nazwy tagów jako terminale, a gdy okazało
się iż tagi mogą występować w różnej kolejności, dodał do gramatyki
wszystkie permutacje) ale ogólnie działało to bardzo fajnie.
Amortyzacja zmian
Bodaj jeszcze ważniejszy aspekt adaptacji XML. Co się dzieje, gdy coś się zmienia?
Powiedzmy, że dodajemy do powyższych informacji kontaktowych adres
email (<email>Jan.Kowalski@wp.pl</email>
).
Co trzeba było zrobić przy użyciu tradycyjnych protokołów?
Zbudować nową specyfikację interfejsu, wygenerować nowe szkielety kodu, przebudować z nimi wszystkie aplikacje - nawet te od dwóch lat nie ruszane i do niczego owego emaila nie potrzebujące. I zaplanować proces synchronicznego upgrade.
Co trzeba było zrobić w przypadku XML?
Nic!
Programy tak czy siak wybierały sobie z komunikatów potrzebne dane, pojawienie się nowego pola nie miało dla nich żadnego znaczenia. Zmieniać trzeba było tylko te komponenty, które faktycznie używały nowo dodanych bloków.
Przechodziło nie tylko dodawanie nowych elementów, nieraz dawało się też gładko usunąć mało używane pole czy rozszerzyć jakiś format.
No i w 99% przypadków można było po aktualizować programy po jednym, począwszy od generujących nowe dane, bez jednego gigantycznego upgrade i mogąc rozkładać ten proces w czasie.
Zauważmy jak podobne jest to do kooperacji przeglądarka - serwis webowy. Narzędzia z obu stron się zmieniają, protokół także ale akcent jest położony na amortyzowanie problemów. Starszy browser trafiający na nowy content pominie nieznane sobie tagi, zbuduje inny layout ale główna treść strony pozostanie dostępna.
Po sukcesie
Technika się spopularyzowała, zaczęto ewidencjonować co popularniejsze problemy i je rozwiązywać. Niektóre pomysły (jak deklarowanie kodowania znaków) były ewidentnie dobre. Inne - miały dwie strony.
Swoistym znakiem czasu stała się XML Schema, narzędzie do definiowania formalnej struktury komunikatów.
Gdzie wcześniej po prostu składano odpowiedni tekst i uzupełniano opis, teraz trzeba było zacząć od sformalizowania struktury przez opisanie jej fragmentem koszmarnie nieczytelnego kodu. Pojawiło się numerowanie wersji protokołów i opisywanie do jakich wersji są dopasowane poszczególne aplikacje. Itd itp.
Nie twierdzę, że XML Schema jest jednoznacznie szkodliwa. Jestem autorem sporej specyfikacji, której obecność XSD na pewno pomogła utrzymać się przez lata bez popadnięcia w chaos. Ale widzę jak konieczność pisania schemy spowalnia rozwój systemów. Czas dokumentowania nowego komunikatu: 25% przygotowanie przykładów, 25% zrobienie tekstowego opisu, 50% definiowanie schemy i walka z ograniczeniami jej języka. A potem programiści i tak korzystają głównie z przykładów i opisów, do schemy odwołując się rzadko.
Interesującą alternatywą dla XML Schema jest RELAX NG. Jest to język znacznie czytelniejszy i wyczyszczony z wielu sztucznych ograniczeń i dziwacznych konstrukcji wszechobecnych w schemie, a mający tą samą siłę wyrazu. W projektach, w których formalna definicja XMLowych struktur danych jest potrzebna, na pewno wart rozważenia.
Oczywiście - schema pozwoliła wprowadzać weryfikacje poprawności, tak samych przykładów, jak żywych komunikatów w środowiskach testowych (a czasem i produkcyjnych). Ale znowu - szum wynikający z nieistotnych alarmów (wartość spoza enumeracji w nieużywanym polu, brak w jakimś bloku tagu, który został niedawno wprowadzony i którego brak programy obsługują, za długi komunikat błędu, brak wartości zakodowany pustym tagiem zamiast brakiem tagu...) zdecydowanie dominuje, prawdziwe problemy są wykrywane bardzo rzadko, częściej łapią je elementarne testy komponentów.
Jedyna faktycznie oczywista wartość schemy to możliwość weryfikowania syntaksu przykładów po wszelkich aktualizacjach.
No, ale to był pierwszy krok.
Znowu analogia: dawno, dawno temu pisano w C. Który miał słabą kontrolę typów parametrów, co owocowało chmarą nieprzyjemnych błędów. Na bazie tych doświadczeń za bardzo ważną cechę języków programowania uznano dokładną weryfikację typów danych. Apogeum to podejście osiągnęło chyba w C++, z ciągłymi walkami o to, by jakoś przekazać dane z
vector<const string>
do funkcji oczekującejchar *[]
.Tu w wielu zastosowaniach jesteśmy już krok dalej, okazało się iż weryfikacja zgodności typów pozwala wykryć masę błędów ale są to zgoła inne błędy niż te, które naprawdę chcemy wykrywać. Statystyka ilości aplikacji webowych napisanych w C++ jest najlepszym podsumowaniem.
Zamknięcie koła
Koło zamknęło się nieco później, w formie serii standardów nadbudowanych nad SOAP. Makabryczny język WSDL, niesławnej pamięci UDDI, WS-AtomicTransaction, WS-Coordination, WS-BusinessActivity, WS-Security, WS-BrokeredNotification, WS-Federation, WS-Topics, WS-BPEL, ... Kto czytał - powiedzmy - specyfikację CORBA-y, wiele z tych bytów rozpozna.
Tak naprawdę, nad komunikacją XMLową odbudowano cały sztafaż dawnych binarnych protokołów. Znowu wszystko jest bardzo skomplikowane, znowu mamy wielojęzykowy miks, znowu specjalizowane narzędzia generują tajemniczy kod, z którym trzeba łączyć własne oprogramowanie, znowu trzeba się długo i ciężko narobić (i mieć specjalizowane toolkity), by uzyskać pierwsze efekty pracy, znowu coraz trudniej o porozumienie między różnymi produktami, znowu wprowadzanie zmian jest bolesnym procesem. No i znowu walczymy o ułudę, iż zdalne wywołanie jest lokalne.
Trochę tylko niejasne, po co właściwie ten XML pod spodem.