În Wikipedia, Zope este succint definit ca fiind un server obiectual de aplicaţii web, open source, scris în limbajul de programare Python. Evident, o astfel de definiţie este potrivită pentru o enciclopedie, însă pentru a face lumină asupra subiectului e nevoie de o abordare ceva mai aprofundată.
Pornind de la suprafaţă, primul termen care s-ar
cere detaliat e cel de "aplicaţie web". În principiu, o aplicaţie web
ar putea fi aproximată ca un sit web ale cărui pagini sunt generate
dinamic. Din punctul de vedere al utilizatorului, acest lucru este în mare
măsură transparent, deoarece către client sunt trimise pagini
HTML obişnuite. Totuşi, faptul că URL-urile nu indică
fişiere cu extensia "html" este un indiciu că paginile sunt generate
dinamic. De asemenea, un grad ridicat de interactivitate bazat pe formulare web
este un semn sigur că avem de-a face cu o aplicaţie şi nu cu un
sit static.
Din această perspectivă, Zope poate fi
asemănat cu Php. Diferenţa notabilă este însă că Php
este un limbaj de programare utilizat pentru realizarea de aplicaţii web,
în vreme ce Zope este un o aplicaţie complexă, care tratează în
mod coerent o întreagă paletă de probleme specifice aplicaţiilor
web, începând de la autentificarea şi autorizarea utilizatorilor până
la sincronizarea serverelor şi echilibrarea încărcării. Deoarece
o bună parte din funcţionalitate este furnizată nativ de Zope,
se poate spune că este totodată un framework.
Fiind o aplicaţie care se plasează între partea de
prezentare (în general browserul web) şi diverse alte resurse software din
partea server, Zope este un server de aplicaţii, fiind din acest punct de
vedere asemănător cu Macromedia ColdFusion şi similar ca
funcţionalitate cu IBM WebSphere sau alte servere bazate pe J2EE. Poate fi
considerat şi un middleware software care gestionează logica
aplicaţiei, furnizând altor aplicaţii serviciile pe care le
implementează. În paranteză fie spus, Zope poate să comunice nu
doar cu browsere web, ci cu orice programe capabile să utilizeze HTTP sau
protocoale bazate pe acesta, precum SOAP sau XML-RPC.
Caracterul obiectual se referă atât la modul în care
este construită aplicaţia, cât şi la modul în care este
utilizată. De fapt, Zope se bazează pe o bază de date
obiectuală numită ZODB (Zope Object Database) care
stochează diferitele obiecte Python ce formează aplicaţia web.
Obiectele Zope (ca orice obiecte de altfel) constau dintr-o structură de
date împreună cu o serie de metode specifice clasei de obiecte respective.
În fine, ar mai trebui spus că:
Zope are înglobat şi un server HTTP, care în mod implicit foloseşte portul
8080. Are însă şi posibilitatea să folosească un server
extern, cum ar fi Apache sau IIE, rezervându-şi astfel doar sarcina de a
genera paginile HTML. De asemenea, cuprinde un server FTP.
Zope poate fi aproape integral administrat printr-o interfaţă web,
numită ZMI (Zope Management Interface). Pentru editarea unor
anumite tipuri de obiecte se poate folosi un editor de text extern, care
rulează pe computerul local şi comunică prin FTP cu serverul
Zope.
Zope are o arhitectură modulară, bazate pe componente care se numesc
"produse" (products). Aceste componente pot fi dezvoltate de oricine pe
baza modulelor şi interfeţelor Python specifice, pot reprezenta
simple obiecte care pot fi stocate în ZODB sau chiar aplicaţii complexe
şi uşor integrate în orice instalare Zope.
Puţină istorie
Totul a început în 1996, când Jim Fulton de la firma Digital
Creations a trebuit să ţină un curs despre CGI. Cum nu prea
ştia mare lucru despre subiect, a studiat în avion documentaţia
existentă şi a constatat că metoda tradiţională de a
publica pagini web dinamice prin intermediul CGI este greoaie şi
ineficientă. Povestea spune că în cele câteva ore cât a durat zborul
de întoarcere, Fulton şi-a ocupat timpul schiţând o metodă mai
elegantă de a dezvolta aplicaţii web.
Din aceste schiţe s-au conturat trei produse software
care ar trebui să conlucreze pentru a facilita crearea unor situri web
dinamice complexe: un program care să furnizeze funcţii de publicare
(Bobo), unul care să permită crearea de machete de pagini (Document
Template) şi un sistem de stocare obiectual (BoboPOS). Deoarece
programele urmau să fie complexe, dinamice şi orientate pe obiecte,
pentru implementare a fost ales limbajul Python. Cele trei programe au fost
apoi reunite într-un produs complex, numit Principia. În ciuda
calităţilor şi caracterului inovator al produsului, acesta nu
s-a făcut remarcat pe piaţă iar cei de la Digital Creations au
apelat la un investitor care să-i ajute să-şi promoveze
produsul.
În noiembrie 1998 a apărut şi investitorul -- pe
nume Hadar Pedhazur -- care le-a sugerat celor de la Digital Creation o cale
diferită de a-şi promova şi dezvolta produsul: să-l publice
în regim open source. Ideea s-a dovedit cât se poate de productivă,
deoarece sub noul nume, Zope (Z Object Publishing Environment), produsul
a adunat foarte repede o comunitate entuziastă de programatori care au
contribuit masiv la îmbunătăţirea produsului şi au creat
sute de componente pentru cele mai variate domenii, astfel încât în scurt timp
Zope a căpătat o nesperată popularitate.
Digital Creations şi-a schimbat numele în Zope
Corporation şi a devenit o companie specializată pe servicii şi
integrarea unor sisteme complexe bazate pe Zope, printre clienţii săi
numărându-se mari organizaţii din cele mai diverse domenii:
comandamentul NATO, US Navy, Bank of America, Duke University, NASA, Viacom
Television etc. În paralel, Zope Corporation supervizează în continuare
dezvoltarea Zope.
Cum funcţionează
Sarcina fundamentală pe care o îndeplineşte Zope
este să "publice" obiecte pe care le stochează în baza sa de date
ZODB. Deoarece această structură de stocare este riguros ierarhică
-- fiecare obiect este plasat într-un obiect de tip container -- mecanismul de
publicare realizează la fiecare apel o mapare a căii de acces la un
obiect din baza de date într-un URL.
Spre exemplu, dacă vom considera un obiect de tip
document numit DocEx plasat într-un obiect de tip folder (care este un
container) numit Nod2, la rândul său conţinut într-un folder
numit Nod1, atunci documentul în chestiune poate fi apelat printr-un URL
de genul:
http://localhost:8080/Nod1/Nod2/DocEx?nume=Vasile
Am considerat că serverul Zope este pe computerul local
(dar ar putea fi oriunde în internet) şi funcţionează pe portul
8080. Maparea este cât se poate de simplă, cu condiţia să
ţinem seama că totul porneşte de la un folder
rădăcină, care este baza unei instalări Zope şi care
în cazul nostru poate fi accesată prin URL-ul:
http://localhost:8080/
Dacă documentul numit DocEx (majusculele
contează) conţine doar cod HTML, atunci acesta este trimis browserului apelant, iar acesta îl
afişează ca pe oricare altă pagină web. În felul acesta
putem să realizăm foarte simplu situri web similare cu cele statice,
cu diferenţa că documentele nu sunt stocate în structura de
fişiere a serverului ci într-o bază de date. Deşi Zope oferă
o serie întreagă de avantaje chiar şi în acest caz trivial de
aplicaţie web (de pildă mecanismele de control al accesului, accesul
prin interfaţă web etc.), puterea produsului se manifestă plenar
abia atunci când este vorba de a genera dinamic conţinutul paginii.
Până acum am făcut abstracţie de stringul de
interogare (query string), însă intenţia este evidentă:
documentele sunt obiecte active, care au posibilitatea să-şi
"compună" conţinutul şi să interacţioneze cu alte
obiecte Zope. În exemplu de mai sus, documentul DocEx va dispune de
variabila nume cu valoarea "Vasile", pe care o poate plasa în
conţinut (ca şi în Php) astfel încât utilizatorului i se va trimite o
pagină web personalizată.
O observaţie finală referitoare la modul de
funcţionare ar fi că acesta poate fi exprimat în mod obiectual.
Publicarea unui obiect Zope înseamnă de fapt trimiterea unui mesaj HTTP
(eventual cu parametri) obiectului, al cărui răspuns este trimis apoi
clientului.
Obiecte Zope de bază
Zope dispune de o serie destul de extinsă de clase de
obiecte, fiecare dispunând de un API public şi riguros documentat. Este
greu (dacă nu imposibil) de distins între obiectele "native" şi cele
dezvoltate de terţi proiectanţi. Numeroase componente (products)
se concretizează în obiecte care, odată instalate, pot fi folosite
exact ca cele furnizate în distribuţia standard. Totuşi, câteva pot
fi considerate "de bază" datorită faptului că sunt cel mai
frecvent utilizate iar Zope n-ar putea funcţiona fără ele.
Folder
Este principalul container folosit în Zope. Practic orice
obiect Zope se află într-un folder (la limită în folderul
rădăcină). Ca orice obiect Zope, este identificat printr-un
proprietate id şi dispune de proprietatea title (care este
cea utilizată pentru vizualizare, dacă este definită). În plus,
utilizatorii pot adăuga (prin ZMI sau programatic) orice
proprietăţi doresc. Proprietăţile folderului sunt implicit
accesibile obiectelor conţinute şi în mod explicit celorlalte.
Clasa Folder este sub-clasă a clasei ObjectManager,
de la care moşteneşte cea mai mare parte a funcţionalităţii,
care constă în principal din metode care asigură accesul la obiectele
conţinute. De pildă, metoda objectItems returnează o
listă de perechi (id, object) corespunzătoare obiectelor
conţinute (eventual restrânsă la cele de anumite tipuri, precizate
prin argumentul type).
De notat că apelul direct al unui obiect de tip folder
este implicit redirectat către un obiect numit index_html din
folderul respectiv.
DTMLDocument şi DTMLMethod
Ambele sunt obiecte al căror rol principal este să
genereze conţinut text (HTML, XML, text simplu etc.) care este apoi trimis
apelantului. Apearea unui astfel de document determină interpretarea
codului DTML cuprins în conţinut (dacă există) şi
returnarea conţinutului astfel obţinut.
DTML (Document Template Markup Language) este un
limbaj de marcare care cuprinde o serie de construcţii exprimate prin
tag-uri de forma:
Aceste construcţii -- pe care, printr-un abuz de limbaj,
le voi numi instrucţiuni -- pot fi intercalate oriunde în conţinutul
textual al obiectului şi furnizează funcţionalităţi
tipice unui limbaj de programare: teste, iteraţii, apeluri de
procedură etc. Un exemplu simplu poate furniza o sugestie:
Este vorba de o iteraţie prin lista obiectelor
conţinute în folderul container (obţinute apelând metoda objectValues).
Vor fi prezentate doar cele de tipul "DTML Method", pe baza testării
atributului meta_type. Metoda title_or_id furnizează titlul
obiectului curent, sau id-ul în cazul în care titlul lipseşte. E de
remarcat că dtml-var nu are tag de închidere, expresiile
urmează sintaxa Python iar interpretorul ştie să aleagă
între atribute şi metode.
Diferenţa dintre documentele şi metodele DTML este
oarecum subtilă. Documentele pot avea atribute definite de proiectant în
vreme ce metodele nu. În schimb, metodele au acces la API-ul folderului care le
conţine, în schimb documentele nu -- deci fragmentul de cod furnizat ca
exemplu nu va funcţiona decât într-o metodă DTML, nu şi într-un
DTMLDocument.
Zope Page Template (ZPT)
Machete Zope Page Templates sunt o alternativă la
obiectele de prezentare bazate pe DTML şi reprezintă la momentul
actual modalitatea recomandată. Ca şi metodele şi documentele
DTML, documentele ZPT produc conţinut HTML (sau XML) cu diferenţa
că folosesc un alt limbaj pentru generarea dinamică a paginilor: TAL
(Template Attribute Language). Diferenţa majoră este că
TAL se exprimă integral ca atribute dintr-un spaţiu de nume XML
şi se pot aplica documentelor HTML (sau XML), cu avantajul că acestea
rămân valide. Aceasta înseamnă că ele pot fi schimbate liber
între un graficieni (sau web designeri) şi programatori, primi ocupându-se
de aspect (folosind editoare HTML, care vor ignora atributele TAL) iar ultimii
de chestiunile procedurale.
Pentru a simţi "aroma" machetelor ZTP, iată
echivalentul fragmentului DTML prezentat anterior exprimat în TAL:
Este de remarcat că deoarece "instrucţiunile" TAL
sunt atribute HTML, a fost nevoie să forţăm puţin nota
şi să introducem elemente structurale (în cazul acesta span)
la care să putem ataşa atributele. Dacă prezentarea ar fi fost
tabelară, am fi putut recurge la elementele tr şi td.
Ar mai fi de remarcat că un acelaşi element HTML poate avea mai multe
atribute TAL şi că textul de afişat (în cazul acesta "Titlu sau
id") este doar un placeholder care va fi înlocuit cu valoarea
actuală ce trebuie afişată. Este important însă pentru
designer, deoarece are astfel posibilitatea să vizualizeze aspectul
paginii populată cu date. Există în plus posibilitatea de a plasa
şi "elemente fantomă", care vor fi vizibile în faza de design dar nu
vor fi generate în cazul unui apel în Zope (servesc doar pentru ghidarea
vizuală a graficianului).
Ar mai fi de notat că TAL este folosit în
conjuncţie cu METAL (Macro Expansion TAL) care este utilizat pentru
a include blocuri de cod numite macro-uri, care pot fi particularizate
în funcţie de context prin intermediul unor aşa-numite slot-uri.
În plus, sintaxa expresiilor folosite de atributele TAL şi METAL este
standardizată prin TALES (TAL Expression Syntax).
DTML şi TAL sunt alternative care însă nu se exclud reciproc. DTML are o mai mare putere procedurală şi, în plus, permite unele procesări care nu sunt posibile în ZTP (de pildă generarea de mesaje e-mail).
Fişiere
Fişierele Zope (File) sunt simple depozitare de
conţinut textual sau binar. Spre deosebire de fişierele
obişnuite, acestea sunt stocate în baza de date obiectuală (ZODB)
şi, desigur, sunt şi ele obiecte, dotate cu atribute şi metode.
Pentru cele care cuprind text există posibilitatea de a fi editate prin
ZMI. Tipul conţinutului este desemnat prin metoda standard MIME -- de
pildă text/plain, text/xml, application/pdf etc. --
şi poate fi obţinut prin metoda getContentType.
Evident, conţinutul fişierelor -- fie importate,
fie generate în Zope -- poate fi inclus în documentele generate. Ele
reprezintă metode tipice de a stoca, de exemplu, declaraţii CSS,
programe JavaScript, applet-uri Java, conţinut Flash etc.
Este de notat că deşi fişierele pot
conţine imagini, Zope pune la dispoziţie şi un obiect
specializat în această privinţă: Image. Explicaţia
constă în faptul că acestea beneficiază implicit de
proprietăţile corespunzătoare dimensiunilor, ceea ce
facilitează controlul afişării.
Scripturi Python
Scripturile Python sunt exact ceea ce par: obiecte
Zope care cuprind cod Python şi care se interpretează. Desigur,
şi ele dispun de câteva proprietăţi specifice, cum ar fi lista
de argumente. Deşi limbajul DTML poate rezolva în mare parte
necesităţile procedurale ale unei aplicaţii, scripturile Python
reprezintă metoda recomandată pentru implementarea logicii
aplicaţiei, lăsând în seama machetelor ZTP şi a documentelor sau
metodelor DTML implementarea "logicii prezentării".
Este de remarcat că scripturile Python nu
beneficiază -- din motive de securitate -- de întreaga forţă a
limbajului Python. Astfel, scripturile pot importa doar un set limitat de
module, nu pot accesa fişiere şi nu dispun de anumite funcţii
native. De pildă, funcţia type lipseşte, fiind însă
disponibilă o funcţie alternativă same_type care poate
determina tipul unui obiect prin comparaţie. De asemenea, funcţia range
nu va putea genera numere sau secvenţe foarte mari.
În schimb, scripturile Python beneficiază de un
mecanism numit bindings, care permit acestora să acţioneze în
contextul unei aplicaţii Zope. De pildă, obiectul context este
cel care furnizează unui script Python informaţii legate de
localizarea sa în ierarhia obiectelor Zope. Iată, spre exemplu, cum ar
arăta scriptul Python echivalent cu exemplul dat în DTML:
for o in context.objectValues():
if o.meta_type == 'DTML Method':
print o.title_or_id()
return printed
E de observat utilizarea obiectului context pentru a
aplica metoda objectValues folderului care conţine scriptul precum
şi utilizarea instrucţiunii print. Deşi scripturile
Python sunt menite în principal să returneze rezultate, ele pot să
şi "tipărească", caz în care obiectul printed reţine
întreg textul emis de instrucţiunile print.
De notat că deşi Python este "alegerea
naturală" pentru Zope (fiind limbajul în care Zope este implementat)
există şi posibilitatea ca, prin intermediul unei componente, să
se folosească scripturi Perl.
Metode externe
Metodele externe sunt în mare măsură similare
scripturilor Python. Şi ele servesc la implementarea logicii
aplicaţiei şi sunt exprimate în limbajul Python. Diferenţele
notabile sunt următoarele:
Textul sursă Python nu este memorat în baza de date ZODB, ci într-un fişier extern, plasat în subdirectorul Extensions al instalării Zope de pe server. Obiectul memorat în ZODB nu este decât o referinţă la
fişierul respectiv şi la funcţia corespunzătoare. Aceasta
înseamnă că mai multe metode externe îşi pot avea codul în
acelaşi fişier, deoarece obiectul External Method corespunde
unei funcţii Python. În plus, metodele externe nu pot fi editate prin
interfaţa web ZMI.
Metodele externe nu au limitările scripturilor Python: pot importa orice module, pot accesa fişiere etc. După măsurătorile mele, sunt adesea cam cu un ordin de mărime mai rapide decât scripturile Zope echivalente.
Metodele externe nu au acces la mecanismul de binding. Cu toate acestea,
dacă funcţia este definită ca metodă (cu primul argument self), ea va fi considerată metodă a containerului (adică a folderului în care a fost creat obiectul External Method) şi va avea astfel acces la folder şi la obiectele din acesta.
Request şi response
Clasele Request şi Response conţin
fiecare câte un singur obiect -- REQUEST şi respectiv RESPONSE
-- corespunzătoare dialogului tipic cerere/răspuns pe baza căruia
funcţionează web-ul. Dacă RESPONSE este folosit mai ales pentru
redirectări şi manevrarea cookie-urilor, REQUEST este omniprezent
într-o aplicaţie Zope non-trivială. REQUEST poartă alături
de informaţiile de context (cele din specificaţiile CGI) o serie de
date extrem de importante, cum ar fi datele culese din formularele web, care
ajung astfel la dispoziţia metodelor care le procesează.
AuthenticatedUser
Zope dispune de un mecanism complex de control al accesului
utilizatorilor la diverse resurse şi obiecte. Trebuie mai întâi notat
că întreg acest mecanism este decuplat de serviciile de securitate ale
sistemului de operare gazdă: cu excepţia administratorului unei
instalări Zope, ceilalţi utilizatori nu au nevoie de conturi pe
server. Desigur, pentru aplicaţiile publice dezvoltate în Zope, este cel
mai adesea permis accesul utilizatorilor anonimi, însă aceştia nu vor
avea decât drepturile minimale necesare pentru a utiliza serviciile furnizate.
Pentru orice altfel de activitate, întră în joc mecanismele Zope de
control al accesului, care încep cu autentificarea utilizatorilor şi
continuă cu autorizarea lor pe bază de roluri şi permisiuni.
Fiecare folder din Zope poate avea asociat un folder de
utilizatori. Autentificare se face pe baza conturilor din acest folder iar un
utilizator, odată ce a fost autentificat pe baza numelui şi a
parolei, primeşte unul sau mai multe roluri, pe baza cărora este
autorizat să acceadă la anumite obiecte sau funcţii. Odată
cu autentificarea, este generat un obiect din clasa AuthenticatedUser,
care dispune de metode prin care se pot afla rolurile şi permisiunile de
care dispune utilizatorul respectiv. Acestea sunt folosite atât de sistemul de
administrare din Zope, dar pot fi folosite şi de proiectanţii de
aplicaţii.
Este de notat granulaţia extrem de fină a
mecanismului de securitate din Zope. Practic, fiecare obiect din Zope îşi
are propriul său sistem de securitate, în care fiecare drept este
specificat pentru fiecare rol în parte. Acest mecanism permite delegarea
responsabilităţii pe diverse clase de activităţi în cadrul
unui sit Zope.
Baze de date
Baza de date obiectuală ZODB poate cuprinde o mare
varietate de obiecte, care pot satisface în mare cam orice fel de cerinţe
ale unei aplicaţii. Cu toate acestea, pentru aplicaţiile care
utilizează volume mari de date complex structurate, utilizarea bazelor de
date relaţionale devine obligatorie. Din fericire, Zope dispune de un
instrumentar bogat şi eficient, care permite o excelentă integrare a
bazelor de date relaţionale în aplicaţiile Zope. Există câteva
obiecte şi componente care fac acest lucru posibil.
Adaptoare de baze de date
Adaptoarele (database adapters) sunt componente care
asigură accesul aplicaţiei Zope la baze de date relaţionale.
Distribuţia standard nu cuprinde decât un singur adaptor, destinat unui
mini-sistem relaţional numit Gadfly, implementat chiar în Zope (rolul
acestuia este pur demonstrativ). Din fericire sunt disponibile numeroase
adaptoare open source pentru toate sistemele relaţionale majore ÂÂÂÂÂÂ
de pildă, pentru PostgreSQL există PoPy si Psycopg -- plus adaptoare
ODBC (acesta din urmă este comercial, dar ieftin). Vestea proastă
este că instalarea acestora nu este întotdeauna trivială şi
veţi avea nevoie de ajutorul administratorului de sistem (mai ales pe
sisteme de tip unix).
Odată instalat, un adaptor va corespund unui obiect
numit conexiune (specific SGBD-ului). Este importat de notat că a
aplicaţie poate folosi mai multe conexiuni simultan, la diverse baze de
date (chiar gestionate de SGBD-uri diferite). O menţiune merită
sistemul tranzacţional din Zope, care controlează şi bazele de
date. Practic, tot ce se întâmplă între două pagini succesive
afişate este o tranzacţie, aşa că orice eroare (indiferent
dacă apare în Zope sau baza de date) va declanşa un rollback
general.
Metode SQL
Metodele SQL reprezintă un alt tip de obiecte
menite să implementeze logica aplicaţiei, care au însă şi
calitatea de a izola "logica stocării". Într-un fel, seamănă cu
scripturile Python, prin faptul că au o listă de argumente -- dar,
atenţie, acestea sunt tipizate -- şi pot fi apelate explicit, ca orice
funcţie. Pe de altă parte, seamănă cu metodele DTML, prin
faptul că utilizează acest limbaj. Spre deosebire însă de
acestea, o metodă SQL nu trimite rezultatul evaluării către
browserul apelant, ci către baza de date corespunzătoare conexiunii
de care este legată. Deci, rezultatul evaluării trebuie să fie o
frază SQL validă.
Din fericire, DTML a fost dotat cu o serie de
construcţii care ajută enorm la această sarcină. De
pildă, argumentele pot fi referite prin variabile de tipul sqlvar,
ceea ce asigură tratarea lor corectă din perspectivă SQL (de
pildă, închiderea între apostroafe a argumentelor de tip text etc.). În
plus, există construcţia sqltest care asigură
construcţia automată a frazei where, cu toate
subtilităţile de rigoare (de pildă, în cazul în care un argument
este o listă, se foloseşte operatorul IN, corespunzător
incluziunii). În fine, posibilitatea de grupare prin sqlgroup este
extrem de utilă în conjuncţie cu operatorii logici, astfel încât
dacă -- de exemplu -- una dintre condiţiile conectate cu and sau
or lipseşte, condiţia va fi omisă împreună cu
operatorul aferent.
Un exemplu simplu poate fi sugestiv. Să considerăm
o tabelă Angajati cu coloanele cod, nume, prenume
şi salar. O metodă SQL (s-o numim SQLTest) va avea
lista de argumente:
angs:int:list
sal:float
Corpul metodei poate arăta aşa:
În felul acesta vom selecta angajaţii desemnaţi
printr-o listă de coduri angs care au salariul mai mare decât o
valoare sal. Dacă angs va cuprinde codurile 1 şi 2 iar sal
este 250, se va genera fraza SQL:
SELECT * FROM Angajat
where
(cod in (1, 2)
and salar > 250.0
)
Dacă angs va cuprinde doar codul 1, fraza va fi:
SELECT * FROM Angajat
where
(cod = 1
and salar > 250.0
)
Dacă angs nu va cuprinde nici un cod, fraza va
fi:
SELECT * FROM Angajat
where
salar > 250.0
Deşi simplist, exemplul este concludent în
privinţa puterii metodelor SQL. O variantă echivalentă în -- de
pildă -- Php ar însemna câteva zeci de linii de cod. Complicat şi
deschis erorilor.
Pluggable brains
Înainte de altceva, trebuie spus că rezultatul unei
selecţii SQL este un obiect complex, dotat cu metode puternice care pot
extrage numărul de linii returnate, definiţiile coloanelor,
rezultatul ca listă de tuple sau ca listă de dicţionare etc. Însă magia de-abia acum începe.
În Zope, putem
asocia unei metode SQL (de selecţie) definiţia unei clase Python.
Astfel, fiecare linie a rezultatului poate fi tratată ca un obiect, deci
ca o instanţă a clasei definite. Desigur, clasa poate avea metode
specializate, care pot apela scripturi Python, metode externe sau chiar alte
metode SQL, constituindu-se astfel într-un "creier" înglobat într-un
rezultat (de unde şi numele pe care-l poartă în Zope).
În exemplul precedent, putem ataşa metodei SQL o
clasă, pe care o putem numi Angajat:
Este evident: metoda numeIntreg va formata numele
complet al angajatului (pentru simplitate, n-am mai procesat stringurile prin
capitalizare). Un exemplu trivial de utilizare într-un script Python:
a = [1, 3, 4]
for r in context.SQLTest(angs=a, sal=250):
print r.numeIntreg(), r.salar
return printed
Ar mai trebui spus doar că aceste clase asociate sunt
într-un fel asemănătoare metodelor externe, deoarece codul lor este
stocat în fişiere pe disc şi nu sunt supuse limitărilor aplicate
scripturilor Python.
Moştenirea şi achiziţia
În lumea programării obiectuale (sau orientată pe
obiecte), moştenirea este calea firească prin care obiectele unei
clase sunt dotate cu un comportament implicit pe care-l primesc de la
"părinţi" (clase de un nivel superior din perspectiva
generalităţii), comportament pe care pot să-l specializeze prin
adăugarea unor noi metode sau prin suprascrierea celor moştenite.
Procedeul se numeşte "subclasare" şi întregul edificiu Zope se
bazează pe această tehnică. Spre deosebire de cele mai multe
limbaje obiectuale, Python este un limbaj cu moştenire multiplă -- adică
o clasă poate moşteni comportament de la mai mulţi ancestori. De
exemplu, clasa Folder moşteneşte de la clasa ObjectManager
comportamentul de container de obiecte (de pildă capacitatea de a
cunoaşte obiectele pe care le conţine), de la clasa OnjectManagerItem
comportamentul tipic al oricărui obiect ce poate fi administrat prin web
(aproape toate) iar de la clasa PropertyManager abilităţile
privind gestionarea proprietăţilor.
Desigur, moştenirea este extrem de importantă
pentru proiectarea componentelor, fie from scratch (în Python) fie pe
baza aşa-numitelor ZClasses (un procedeu mai simplu, prin ZMI, dar
mai limitat). Însă pentru proiectanţii de aplicaţii Zope mult
mai important este un alt procedeu prin care obiectele îşi
specializează comportamentul: achiziţia (aquisition).
Intuitiv, achiziţia este extrem de simplă:
obiectele "achiziţionează" comportament de la obiectele care le
conţin (adică de la container -- de regulă folder). Cum şi
containerele sunt cuprinse în alte containere, rezultă că
achiziţia funcţionează pe ramuri ale ierarhiei de obiecte din
ZODB. De exemplu, dacă un obiect (să zicem o metodă DTML) face
referire la un obiect care nu există în folderul său, atunci obiectul
referit va fi căutat în folderul părinte. Şi aşa mai
departe, până la rădăcină.
Ca de obicei, un exemplu simplu se impune. De obicei,
construcţia unei pagini HTML printr-un document sau printr-o metodă
DTML urmează următorul tipar:
Adică se plasează la început şi la
sfârşit nişte obiecte (de fapt metode DTML) care la modul minimal
arată aşa:
Standard_html_header:
Standard_html_footer:
Aceste metode pot fi plasate în folderul
rădăcină, ceea ce înseamnă că orice pagină astfel
construită le va achiziţiona. Dacă pe o anumită ramură
dorim să particularizăm prezentarea (de pildă să punem o
altă culoare de fundal), vom plasa în folderul corespunzător un alt standard_html_header,
astfel încât pentru obiectele conţinute în folderul respectiv (şi în
sub-arborele corespunzător), achiziţia se va opri la noul obiect.
Farmecul achiziţiei constă în specializare: chiar
dacă headerul este achiziţionat, atributul title_or_id este
cel propriu. Aceasta ne sugerează o altă metodă de a schimba
fondul paginii în funcţie de context: putem crea o proprietate color
în folderele care ne interesează, pe care o includem în tag-ul body:
Achiziţia funcţionează şi aici. Pentru
obiectele care nu au proprietatea color aceasta va fi
achiziţionată. La fel se întâmplă şi cu utilizatorii
şi drepturile acestora şi cu orice altceva. De fapt, achiziţia
este un mecanism bazat pe containerizare şi implementat prin spaţiile
de nume.
Ce-a mai rămas...
Oricât de întinsă ar fi această prezentare, ea nu
poate decât să puncteze câteva dintre aspectele acestui produs extrem de
complex. Nu am vorbit nimic cataloage, despre aplicaţiile de administrare
a conţinutului bazate pe Zope (CMF, Plone etc.) şi doar am amintit
despre comunitatea Zope, care a creat sute de componente extrem de utile, de la
cele mai simple (cu valoare mai mult didactică) şi până la
blog-uri sau portaluri comerciale la cheie...
Admit că acest articol are şi o notă
propagandistică şi că urmăreşte să vă
stârnească interesul pentru un produs open source exemplar.
Resurse
www.zope.org -- situl oficial al comunităţii
Zope. Aici se pot găsi sursele Zope, distribuţiile oficiale,
documentaţie (începând cu "biblia" The Zope Book), sute de
componente (products) realizate de comunitate precum şi
referinţe la alte situri despre Zope.
www.zope.com -- situl oficial al Zope Corporation. Pe
lângă prezentarea produselor comerciale al firmei, se pot găsi
numeroase studii de caz privind diferite organizaţii care au implementat
soluţii Zope.
Plone.org -- situl oficial al comunităţii
Plone, un sistem de administrare a conţinutului complet, open source,
bazat pe Zope.
www.cps-project.org -- situl proiectului CPS (Collaborative
Portal Server), în sistem open source de colaborare dezvoltat de firma
franceză Nuxeo împreună cu o comunitate de voluntari. Produsul a fost
prezentat în NetReport nr. 9.