Pokazywanie postów oznaczonych etykietą web. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą web. Pokaż wszystkie posty

wtorek, 29 lipca 2008

Krok po kroczku - App Engine daje coraz więcej

appengine_lowres Tak naprawdę ku zabawie z Django skłoniła mnie premiera Google App Engine parę miesięcy temu. Dotąd nie byłem przekonany zbytnio do programowania aplikacji webowych w Pythonie, ponieważ PHP z Zend Frameworkiem jest całkiem niezłym kawałkiem biblioteki, a przełączenie się na coś zupełnie innego wymaga nieco wysiłku z początku. Ale załączenie Django w GAE SDK było wystarczającą rekomendacją tego projektu, jako rozwiązania dojrzałego i przyjaznego programiście. Google ma zwyczaj akurat o tę grupę dbać całkiem nieźle.

Będąc na co dzień programistą J2ME/J2EE, a tylko w prywatnych projektach robionych w domowym zaciszu wykorzystując bardziej nowoczesne lub po prostu inne zabawki, możliwość poprowadzenia z praktykantem małego projekciku w technologiach tak diametralnie różnych, to swoisty ratunek zdrowia psychicznego. ;)

Nie dość że zupełnie inne biblioteki, to jeszcze jazda całkowicie bez trzymanki! Jako platforma serwerowa posłuży Google App Engine z Django 1.0 alpha, natomiast po stronie klienckiej jest nic innego jak Android, w roli nowoczesnej platformy mobilnej. MIDP to przeżytek przecież. ;)

Cieszą mnie kolejne aktualizacje App Engine, jak ostatnio wypuszczona wersja 1.1.1, która teraz pozwala na utworzenie 10 aplikacji, zamiast dotychczasowych 3. Dodatkowo poprawiono sporo błędów, więc może być tylko lepiej. Żeby tak w androidowym SDK poprawili wreszcie najbardziej irytujące niedociągnięcia...

Źródło: Google App Engine Blog

wtorek, 8 lipca 2008

Jestem człowiekiem ery Web 1.0...

Już jakiś czas chodziło za mną przestawienie się całkowite z programowania webowego w PHP i Zend Framework na coś przynoszącego powiew świeżości i nowoczesności, a także większego porządku składniowego i dyscypliny.

Moje zauroczenie Pythonem trwa od przynajmniej dwóch lat, ale przekonać się do jego zastosowania w webie ciągle nie mogłem. Udało się wreszcie znaleźć do tego sposobność - projekt i w pracy i jeszcze zaległy zaliczeniowy, by móc złożyć pracę mgr z zaliczonym ostatnim semestrem. ;)

Django wygląda dojrzale i atrakcyjnie, sprawia wrażenie dobrze przemyślanego, a także porządnie wygrzanego w prawdziwych projektach, nie skupionego tylko na szybkim napisaniu aplikacji z tutoriala, by później się okazało że coś bardziej skomplikowanego, to wchodzenie pod stromy pagórek.

Co jednak mi pozostało w sposobie myślenia z twórczości phpowej, to poprzedni engine webowy do niedawna napędzający PDAclub.pl. Nieco się on zestarzał, a nie miałem czasu zająć się czymś nowszym, więc nowy główny programista przerobił mocno na użytek portalu Joomlę 1.5. Mniejsza o to.

Jednym z ciekawszych elementów, które tam opracowałem, to engine layoutów. Działało to w następujący sposób:

  • każda strona prezentująca jakieś treści była przedstawiona w postaci pliku html ze wstawionymi tagami komponentów (w tamtej nomenklaturze - "modułów"), jakie tam miały się pojawić; komponentem takim był np. fragment HTML (np. dla nagłówka, stopki), pobierający tytuł portalu i inne parametry z konfiguracji; inny to komponent wyświetlający parametryzowalną listę newsów, jeszcze inny postów na forum, inny wyświetlający pełną treść wybranego artykułu, kolejny listę nowych hotspotów, menu główne, reklamy, województwa, pliki w dziale download, kategorie itd. Strona główna przykładowo składała się z: nagłówka html, menu głównego, menu nawigacyjnego bocznego, listy najpopularniejszych artykułów, listy poprzednich 15 newsów, głównej części z listą aktualności, listy trzech komunikatów/ogłoszeń (spotkania klubów użytkowników), listy najnowszych wątków z forum, 5 ostatnich komentarzy w newsach, reklamy helionu, shoutboksa dla redakcji (tylko dla niej widocznego), stopki (copyright). Każdy element mogłem dowolnie ustawić, by wyświetlał dokładnie co chcę i jak to ma wyglądać, nigdy nie był uruchamiany niepotrzebny kod. Jeśli chciałem dodać listę trzech najnowszych recenzji sprzętu, wystarczyło wstawić odpowiedni tag do pliku layoutu i ewentualnie zdefiniować template dla takiego elementu - ani linijki kodu PHP do napisania!
  • parametry tych komponentów były podane w linijce z ich wywołaniem, przykładowo {mcm style="module: stories; template: stories_main; limit: 3d10; page: @p"}, oznaczało wstawienie listy newsów z trzech ostatnich dni, a minimalnie 10 najnowszych (jeśli przez ostatnie dni niewiele się działo - pomysł Alberta z czasów, gdy współpracowaliśmy nad pocketpage/palmpage ;) ), których kod html tworzony jest na podstawie templejtu templates/stories_main.tpl , @p-ta strona wyników, a wyrenderowana lista trafiała do pliku na dysku, by setki odsłon na minutę nie wywoływały ciągle tego samego kodu.
  • wartość @p brana była akurat z parametrów żądania HTTP, oczywiście w module stories zamieniana na int
  • Takie komponenty mogły być użyte wielokrotnie, nawet na tej samej stronie - często umieszczanych było kilka wariantów, np. inny z limit: 10; order: views; template: stories_popular, pokazywał najczęściej czytane artykuły za pomocą templejtu stories_popular.tpl
  • Był zatem główny skrypt, który pobierał plik layoutu. Kod html zostawiał nietkniętym, a tagi zamieniał na stosowną treść, uruchamiając dla każdego odpowiednie moduły z "module", przekazując im parametry z tagu, z urla (jeśli potrzebne), ewentualnie ze współdzielonej przez komponenty tablicy zmiennych.
  • Każde takie uruchomienie to był include_once skryptu "modules/{module}.inc.php" (odpowiednio zabezpieczone, by nie wywoływać nieistniejącego lub nie dopuścić do kombinacji ze ścieżkami), wywołanie funkcji a'la render i zwrócenie zamiennika dla taga

Dawało mi to sporą elastyczność, gdyż na różnych stronach mogły być te komponenty przedstawione w odmiennych wariantach, do dowolnych zastosowań. Założeniem było że są od siebie niezależne, ale nie przechowują żadnego stanu w sesji czy gdziekolwiek indziej - mają swoją pracę wykonać tylko na podstawie podanych parametrów i ewentualnie danych w bazie, jeśli z takiej korzystały (większość tak).

Było to bardzo mocno zoptymalizowane wydajnościowo rozwiązanie - jedyny narzut dawało samo parsowanie pliku layoutu, choć był na tyle pomijalny, że próby automatycznej "kompilacji" go do postaci kodu PHP (jak w enginie samych templejtów) skończyły się na eksperymentach.

Parę lat później stworzyłem nieco ulepszoną wersję także tego elementu. Można było robić include innego pliku layoutu, by najczęściej powtarzające się elementy dziedziczyć z innych stron, "moduły" były zrobione obiektowo, ale ogólna zasada działania pozostała.

Potem pojawił się Zend Framework. Zachwyciłem się nim, choć ze stratą tak dla mnie wygodnego rozwiązania jak owe "komponenty" się nie pogodziłem. Napisałem odpowiednie rozszerzenia frameworka, które realizowały ten sam pomysł na nowo. Tym razem opis layoutu to plik xml (kompilowany przez cache do kodu php), nie zawierający żadnego html, ani php, moduły robione w duchu ZF (wykorzystujące standardowe templejty ZF, tj. pliczki ze wstawkami kodu PHP). Ich obsługą w kontrolerach zajmował się helper uruchamiany w init() i postDispatch(). Bardzo proste i efektywne rozwiązanie - gdy wszelkie oprzyrządowanie było ustawione (przez mechanizmy ZF), tworzenie konkretnych stron z komponentami to była kwestia tworzenia pliku layoutu, napisania ewentualnie komponentu oraz templejta jakim prezentuje wynik swojej pracy. Skrypty kontrolerów poza tymi przyjmującymi dane z formularzy, to tylko proste klasy dziedziczące po bazowej, zawierające puste metody odpowiadające poszczególnym akcjom. To powstało przy okazji realizacji zamówienia kolegi na kilka mniejszych stronek i świetnie się sprawdziło. Ninjutsu, interaktywna część strony konkursowej ucha van gogha i kilka eksperymentów działa na nim w pełni sprawnie.

Teraz siedzę, rozpływam się w zachwytach wobec Django, ale brakuje mi tego rozwiązania. Nie chcę zawartości poszczególnych podstron definiować w kodzie pythonowym. Chciałbym móc layouty generować też dynamicznie z jakiegoś prostego designera, a to moja idea komponentów umożliwiłaby jak najbardziej. No cóż. zuber z blipa mi dał znać, iż tego typu mechanizmy nie sprawdziły się we frameworkach ery "Web 2.0", ale ja jestem chyba starej daty. W końcu jeśli to jest dla mnie ekstremalnie wydajne w tworzeniu, bardziej elastyczne i atrakcyjne od dziedziczenia szablonów Django, nie będę trzymał się sztywno MVC, MTV czy innych trzyliterowców nowego stulecia. ;)

A może jednak czegoś do końca nie zrozumiałem? Może w podobnie elastyczny sposób można to zrobić w domyślnej implementacji Django? Jak Ty to robisz, drogi Czytelniku? :)

piątek, 25 stycznia 2008

WikiSpider - zabawa dla geeków :)

Daniel niedawno zaproponował pewną zabawę dla programistów-geeków. Polega ona na stworzeniu aplikacji wspomagającej szukanie jak najkrótszej ścieżki między dwoma dowolnymi hasłami na Wikipedii. Była to okazja do zapoznania się bardziej praktycznego z paroma bardzo zachęcającymi nowościami w C# 3.0, przy których Java niestety wygląda trochę jak relikt (choć ją uwielbiam). Podjąłem wyzwanie, stworzyłem coś takiego, wykorzystując m.in. LINQ to XML, inicjalizatory konstruktorów, automatyczne atrybuty klas i kilka mniejszych ciekawostek (np. operator ??, typy anonimowe).

Miałem okazję też zauważyć, że w Visual Studio 2008 dodano sporo opcji refactoringu kodu - kapsułkowanie, zmiana nazw, porządkowanie importów, usuwanie tych zbędnych i sporo innych możliwości - prawie jak w Eclipse (choć przynajmniej większy porządek w menu kontekstowym). ;)

ide-context

Ciekawe swoją drogą, czy ten refactoring działa z rozumieniem kodu. Świetne też są pewne niewielkie detale - przy świeżo napisanej nazwie obiektu, klasy, zmienionej nazwie dowolnego elementu kodu, proponowane jest w tagu inteligentnym rozwiązanie - czy to refactoring, czy dodanie using, czy uzupełnienie do pełnej nazwy w przestrzeni nazw. Dodatkowa niespodzianka - przytrzymajcie CTRL mając rozwiniętą listę podpowiedzi IntelliSense. :)

Rozwiązanie konkursu w niedzielę! Potem szczegóły na temat programu i link do instalacji ClickOnce. ;)

Technorati Tagi: ,,,

poniedziałek, 4 września 2006

Z persystencją rozterki

Mój frejmłork webowy, zastosowany w pdaclub działa sposób nieco odmienny od MVC, ale gdyby się tam spróbować tej metodyki doszukać, to pewnie by się dało. Nie mam jednak jednego, wspólnego kontrolera frontowego. Różnymi funkcjami frameworka zajmują się różne skrypty, odseparowałem do osobnego katalogu skrypty akcji typu cynk, kontakt, wysyłanie komentarza.

Konsola administracyjna z kolei to nieco inny twór - te kwestie rozwiązuje na swój sposób, chyba bardziej zbliżony do MVC, gdyż wszystkim zajmuje się jeden skrypt, który zależnie od modułu i akcji wywołuje odpowiedzialne za nie skrypty, wykorzystując też podane parametry.

Wszędzie mam przynajmniej dobrą separację logiki od prezentacji, jednak dopiero porządnie jest to wykonane w nowej wersji Content Managera, który zadebiutuje najpierw jako intranet Urzędu Gminy Granowo, później rozbuduję o stronę internetową dla interesantów, która pozwoli załatwiać różnorakie sprawy urzędowe, sprawdzać ich stan, poczytać najnowsze wpisy do BIPu, jak i ponarzekać na gminę na forum.

Otóż kwestia samej prezentacji jest rozwiązana na zasadzie javowych resourców. Mam osobne pliczki językowe, które zawierają klucze i wartości różnych elementów interfejsu użytkownika. W szablonach stron wywołuję je tagami a'la {@zmienna}, gdzie owa zmienna jest wyszukiwana w zasobach i wybierana z pliku odpowiedniego dla aktualnego wybranego w przeglądarce. Jeśli chodzi o kwestię kontrolera i akcji, nadal występują różne skrypty dla różnych stron, jest jeden skrypt zajmujący się wywoływaniem odpowiednich metod modyfikujących informacje w portalu. Ponieważ zazwyczaj takie informacje modyfikuje się przez POST lub GET, zestaw tych klas to form-processors. Każda akcja obsługiwana jest przez osobny skrypcik, rozszerzający podstawową klasę, zawierającą metody odbierania z formularza/urla informacje, których się skrypt spodziewa, oczyszczenia ich z niebezpiecznych treści (XSS), udostępniającą też możliwość stworzenia redirecta http w razie potrzeby (akcja wymaga zalogowania lub wyższych uprawnień). Całość napisana jest w pełni obiektowo, choć muszę jeszcze wszystko dostosować do obiektowości PHP5, gdzie widać już oznaki cywilizacji.

Widok, kontroler – ok. A co z modelem? A tutaj są na razie dwie, właściwie trzy warstwy. Pierwsza to konkretne funkcje obsługi baz danych w PHP. Druga to warstwa abstrakcji - wspólny interfejs dla poszczególnych baz danych. Klasy dają możliwość zabezpieczania zapytań przez stosowne dla danej bazy ocytowywanie (quotowanie ;) ) wartości, dobierają też do zapytań ograniczanych albo LIMIT, albo TOP, zależnie czy to baza ANSI, czy MS. Nie wiem czy jednak pomysłu Microsoftu nie zbojkotować i zupełnie porzucić obsługe SQL Servera. Bo niby jak wygodnie wybrać z bazy dane stronicowane, np. drugie 20 najnowszych newsów? A jeśli chcę 20 od końca wybrać? A jak takie coś dla tabel łączonych zrobić? W MySQL czy od niedawna w PostgreSQL to jest prawie zawsze po prostu tak:

SELECT

 * FROM news ORDER BY date DESC LIMIT 10 OFFSET 10

Aż boję się próbować wymyślić, jak to zrobić w bazach bardziej "czystych", zgodnych z ANSI SQL, szczególnie z joinami. Może ktoś ma pomysły? Brzydactw typu zagnieżdżone SELECTy w zagnieżdżonych SELECTach nie akceptuję. ;)

Trzecia warstwa to coś a'la DAO. Są obiekty reprezentujące odpowiednie tabele w bazie i obiekty zajmujące się manipulacją na bazie za ich pomocą. Obawiałem się tutaj pewnego problemu od początku, ale chciałem sprawdzić, czy może da się to rozwiązać jakoś cywilizowanie. Co z joinami? Co jeśli dane o użytkowniku w systemie mam podzielonego między różne tabele, zawierające różne szczegóły? W jednej te podstawowe, jak login, data rejestracji, hasło, email. W drugiej szczegóły, jak nazwisko, data urodzenia, płeć. W trzeciej dane obywatela, tj. miejsce urodzenia, pesel, adres pocztowy, adres zameldowania stałego, tymczasowego, a w innej tabeli dane pracownika urzędu - biuro, telefon, stanowisko, fotka, wymiary (no, tu się zapędziłem). Do tego tabela z różnego typu własnościami uzytkownika - strona WWW, dodatkowe adresy email, komunikatory, preferencje w portalu, forum, połączona ze słownikiem wiele-do-wielu (można mieć np. kilka komunikatorów). I co teraz? Otóż to.

Postanowiłem zmienić nieco podejście i uczynić dla takiego zestawu tabel jeden obiekt, reprezentujący użytkownika. Zawierałby on dane na temat tabel "uczestniczących", byłby świadomy takich zagadnień jak klucze obce, klucze główne, a pobieranie informacji by polegało na deklarowaniu, które pola zechcę otrzymać i w zależności od tego generowałby odpowiednie zapytanie, razem z tworzeniem joinów i uwzględnianiem istnienia wielokolumnowych kluczy głównych. Do tego dochodziłaby możliwość keszowania słowników w pamięci lub w plikach na dysku, co by pozwoliło nieco zapytania odchudzić w czasie pracy systemu. Taka klasa zawierałaby zatem także informacje, która tabela to słownik, czy ów słownik może być przechowywany w pamięci podręcznej. Zbędne by było sprawdzanie w bazie daty modyfikacji słownika, bo już sama modyfikacja by przechodziła przez klasę. Co na to jury?

poniedziałek, 21 sierpnia 2006

Nieco o nawigacji

Temat stary jak samo WWW - intuicyjna nawigacja po stronie. Jeden z redaktorów A List Apart postanowił go nam przypomnieć. Przyjemnej, odświeżającej lektury. A Tour de Bornholm postaram się w tym tygodniu uzupełniać, zanim wszystko wyleci z glowy. ;)