Template system a'la nowy Twitter

Błądząc ostatnio myślami wpadłem na ciekawy pomysł - template system zainspirowany nowym Twitterem(czyli HTML jest tylko klientem JSON-owego API) Wiem że takich pomysłów była już masa, ale zawsze pozostawały 2 problemy:

  1. Brak “rzeczywistego” HTML jest mało SEO-friendly
  2. Testować to trzeba przez Cucumbera albo całkowicie przez JS

Rozwiązaniem pierwszego zazwyczaj było tworzenie dodatkowych HTML dla robotów, ale to oczywiście psuję całą “czystość” rozwiązania. I tu pojawia się moja idea: zrobić system który automagicznie zwracał by odpowiedni kod. Szybki przykład:

Wersja produkcyjna to kod wynikowy dla użytkownika końcowego, wersja testowa to to co byśmy otrzymywali dla naszych testów oraz robotów internetowych. Pytanie tylko: jak? Ano w widoku widzimy zmienną “@source” która była by generowana poprzez parsowanie JSON-a zwróconego przez index.json. Dzięki temu mamy gwarancję że zawsze używamy dokładnie tego samego JSON-a co reszta API. Oczywiście rozwiązanie to jest wolniejsze niż podawanie “na żywca” JSON-a czy wręcz normalnych zmiennych, ale pamiętajmy że testy mogą się wykonywać trochę dłużej w imię poprawności kodu, a roboty nie zaglądają do nas aż tak często.

Co o tym sądzicie? Czy takie rozwiązanie było by użyteczne? Jeśli tak to co byście do niego dodali? A jeśli nie to dlaczego i co ew. należało by zmienić aby stało się użyteczne?

Ja tam słaby jestem i nic nie kumam z tego postu.

Nie do końca rozumiem jak to ma działać. Skoro masz aplikację w javascripcie, która komunikuje się z aplikacją tylko poprzez requesty JSONa, to dlaczego chcesz template’y generować po stronie serwera? Możesz wyjaśnić jak to miałoby działać?

Aplikacja od strony użytkownika miała by się komunikować przez AJAX i JSON - just like Twitter. Problemem są automatyczne testy oraz roboty internetowe. Dla tych dwóch przypadków aplikacja przechodziła by w tryb symulowania pobierania JSONa i automatycznie podpinała od strony serwera zamiast pozostawiać to javascriptowi. Tak więc można by całość testować za pomocą np. rspeca(bez odpalania przeglądarki i czekania na załadowanie się każdego requestu). Tak samo dla robotów internetowych nie trzeba by pisać oddzielnych widoków z zawartością - jeśli aplikacja wykryła by robota to przechodziła by w tryb symulowany, a więc automatycznie podpinała generowanego JSONa do template i go zwracała(to jest ten przypadek “test” w gist)

Tak czy siak z tego co widzę utrzymujesz 2 szablony, które mają robić to samo. Poza tym testujesz to co dostanie robot a nie to co dostanie user. Zrobisz błąd w JS, twój user nic nie dostanie a twój test dalej będzie sobie radośnie skakał oznajmiając Ci, że wszystko działa. Widzę tutaj za duży rozjazd między testem a produkcją z punktu widzenia użytkownika.

Paneq ma rację. Z tego, co piszesz to wygląda tak, jakbyś miał jedną cześć aplikacji nieprzetestowaną.

Dlaczego nie chcesz uruchamiać przeglądarki w czasie wykonywania testów?

teraz to się czepiasz szczegółów implementacyjnych (gdzie imanel napisał, że nie będzie uruchamiał przeglądarki? oczywiście że będzie, chodzi o to żeby test-suite narzędzia zapewniał ci jednakowość odpowiedzi, cobyś nie był zmuszony do selenium w każdej aplikacji z tego korzystającej).

mi się ten pomysł średnio podoba, ale czepianie się fragmentów implementacji w dyskusji o ogólnym pomyśle jest zbyt analne nawet jak dla mnie.

Widzę że wszyscy koncentrują się na opcjonalnym dodatku w postaci ułatwionych testów, zamiast na meritum - sam pomysł ma służyć zwiększeniu czytelności oraz utrzymywalności widoków w stronie. Prawda - możemy wszystko wyrzucić do partiali a potem je zaciągać AJAXem ręcznie, ale z czasem okazuje się, że coraz trudniej tym zarządzać. Stąd ta idea - tak naprawdę piszemy normalne widoki, które są automatycznie konwertowane w poprawny system oparty o API. Znika więc potrzeba dopisywania JS do każdej akcji aby zaciągnąć JSON i wrzucić go w odpowiedniej formie w odpowiednie miejsce. Znika potrzeba utrzymywania dodatkowych akcji, które służą wyłącznie udostępnieniu fragmentów strony do zaciągnięcia przez JS. Zmniejsza się wreszcie obciążenie strony, bo każdy widok jest generowany poprzez 2 requesty(HTML + JSON) zamiast dużo więcej(HTML + JSON + AJAXy pobierające template dla fragmentów strony) Oraz zwiększa się czytelność - otwierając widok od razu widzisz wszystko co jest w nim zawarte i nie musisz szukać po wielu(często mało oczywistych) plikach jakiegoś partiala albo template-u. Potrzebujesz dodać nazwisko rodowe do widoku? Dodajesz kolejny paragraf w widoku dokładnie tam, gdzie tego chcesz. Bez szukania, zastanawiania się, ani martwienia czy czegoś nie popsujesz - jak za starych dobrych czasów, kiedy widok był jednym plikiem a nie Frankensteinem złożonym z 200 innych :wink:

Drugą sprawą jest to że zamiast utrzymywać 3 widoki(JSON, HTML z zaciąganym JSONem, HTML dla robotów) możemy utrzymywać 2, bo 3 jest generowany automatycznie. Testy frameworka pozwalają mieć pewność, że wygenerowany HTML dla robotów zawiera całą treść którą widzi użytkownik, oraz że widzi ją tak jak użytkownik(kontekst!) Oczywiście jeśli robi się tam jakąś dodatkową magię to można dopisać 3 widok, ale dzięki automatycznemu includowaniu JSONa można to zrobić duża łatwiej(większość jest generowana za nas, a my tylko smaczki implementujemy ręcznie)

Co do testowania - jest to tylko “miły dodatek” z którego można korzystać lub nie. Oczywiste jest, że przy takiej stronie piszemy Cucumbery dla sprawdzenia JavaScriptu - ale jeśli razem z gemem dostajemy obtestowany JS to możemy założyć, że sama funkcjonalność zaciągania danych działa i dopóki my czegoś nie spapramy to będzie działała. Dzięki temu robiąc 20 CRUDa można pominąć dokładne testy Cucumberem(o ile samemu się nie dokłada JS) i wrzucić same RSpec wiedząc, że będzie to działało. Różnica jest taka, że testy “zwykłe” pisze się zazwyczaj dużo szybciej, oraz są dużo dokładniejsze, podczas gdy Cucumber jest raczej testem końcowym - wykonuje się długo, i napisanie w nim kilkuset testów tylko po to, by sprawdzić czy nigdzie nie popsuliśmy wrzucania JSONa w odpowiednie miejsce, jest czasochłonne - pomijając oczywiście czas jaki później zajmie wykonanie tego. Ale jeśli ktoś ma ochotę to oczywiście może - jak mówiłem jest to opcjonalne, i należy to traktować jako miłe ułatwienie, a nie jako główną funkcjonalność.

Rozumiem już teraz zamysł, ale ciężko mi sobie wyobrazić jak by się tego używało w praktyce, nie do końca potrafię uwierzyć, że dałoby się to jakoś fajnie zautomatyzować. Jakbyś zrobił jakiś nawet bardzo prosty proof of concept, to pewnie dużo łatwiej by się rozmawiało.

Na chwilę obecną, jakby mi bardzo zależało na crawlowaniu, to pewnie wolałbym pójść w stronę wytycznych googla dla stron używających ajaxa, a testy integracyjne zaawansowanych javascriptowo aplikacji zrobiłbym w oparciu o webdrivera lub jakieś nowe wynalazki w stylu phantom.js albo WebkitGTK+ z jakimiś bindingami w ruby.