Dec 20

Asa zic ei aici. Cum ca Internet Explorer 8 a trecut de testul ACID2. Daca scot la pensie si activex-ul poate o sa aiba si firefox ceva concurenta. Ca user linux nu sunt prea afectat de stire. Insa ca (uneori) web developer lucrul asta e un pas inainte.

Dorinta nerealizabila: poate in 3-4 ani nu sa sa mai scriem  glume prin stylesheeturi. Parca vad deja ca va merge numai pe Windows Vista si Microsoft Genuine stuff, si adoptia completa va fi pe undeva prin 2020 (nu glumesc cu cifra asta din nefericire).

Administrez printre altele si un siteulet de piese auto, si cca 10 la suta din useri inca au IE 5.5 sau mai vechi. Ceea ce inseamna ca in anno domini 2008 (cand urmeaza redesignul prin februarie) o sa trebuiasca sa ma ocup nu de bugurile din IE6 si 7 , dar si de cele din 5.5. Si probabil la urmatorul redesign si de alea din 8, deci in loc sa devina mai simplu devine mai complicat.

Nu pot decat sa dau din cap a neincredere si sa ma gandesc amarat : the web is broken and is your fault (Rasmus Lerdorf). Trist pentru ca astia de la Microsoft decat sa continue cu monstrozitatea de IE, mai bine ar lua webkitu si si-ar face si ei un browser modern (cum a facut apple). Oare nu s-au prins inca de faptu ca noi, astia cu css, javascript, webdev in general, ne-am saturat. O trece el acid2, dar acid2 testeaza CSS2 (standardul din 1996, 11 ani le-a luat, defapt 12 ca inca nu l-au lansat).

Dupa cate vad testu acid3 (curand se pare ca css3 va fi definitivat) o sa-l avem in IE, humm, calcul rapid, 12 ?

Mai multe pe Slashdot.

Dec 15

Voiam sa scriu cate ceva despre design patterns, observer model in special, si implementarea lor in PHP, insa am gasit acest document : link. Este foarte frumos explicat, si ce mi-a atras atentia e ca se folosesc interfetele pentru implementare. Sweet. Nu prea folosesc interfete (in PHP in special). Mi se pare foarte eleganta folosirea interfetelor in acest document. In fiecare zi invatam ceva, azi eu am invatat ca interfetele chiar pot fi utile cand vrei sa scrii cod frumos.

Dec 15

Cautam ceva gata facut (speram si eu la webservice mai destept). am gasit doar nsite scripte gata facute, da care aveam si eu, dar mult mai rau. Pentru cine intereseaza al meu arata cam asa :

function curs (){
	$buffer = file_get_contents ('http://www.bnro.ro/Ro/Info/pv.asp');
	if (empty($buffer)) $my=0;
	else {
		preg_match_all('/([0-9]{1,2},[0-9]{1,4})/', $buffer, $data);
		$my['eur'] = $data[0][4]; $my['usd'] = $data[0][9];
;
	}
	return ($my);
}

print_r(curs());
Dec 9

Pentru utilizatorii de mySQL e greu cand se vad pe o lpatforma MSSQL. Iata 2 chestii folositoare, care ne enerveaza la MSSQL (si nu numai), pentru ca in alte motoare de baze de date nu le avem :

In MSSQL nu avem LIMIT, nu avem LIMIT, cum procedam ? Iata o sugestie :

select * from (
   select top 10 user_id,user_name from (
  select top 30 user_id,user_name from employee order by user_name asc
  ) as table1 order by user_name desc
) as table2 order by user_name asc

O alta chestie care se comporta diferit este clauza GROUP BY.

In mySQL putem face chestii de genul (nu foarte intelepte, dar totusi utile uneori, si vazute destul de des in aplicatii) :

Select * FROM products
INNER JOIN properties on properties.product_id = products.product_id
WHERE status_id = 1
GROUP BY product_id

In MSSQL soate campurile din select trebuie sa fie agregate sau in clauza pentru a putea face un group by (suna ca dracu in romana).

asa ca query-ul se sparge in 2 si vom folosi operatorul IN (query) :

SELECT * FROM products
INNER JOIN properties on properties.product_id = products.product_id
where status_id IN (
 SELECT product_id FROM products
 WHERE status_id = 1
 GROUP BY product_id
)
Dec 9

Ok, presupunem o tabela cu urmatoarele campuri : id, event_date, user_id, client_id , tip, observatii. Acesta tabela este folosita si de un webservice. Care din cand in cand o ia razna (pe legaturi proste) si baga in ea duplicate. Presupunem ca tabela se numeste events. Hai sa vedem cum scapam de duplicate. E clar ca id-ul nu poate fi folosit (e unic, e cheie primara, are autoincrement, deci select distinct * from events nu ne va ajuta deloc). Pai si ce facem, vom zice ?

Pai creem o tabela temporara cu inregistrarile duplicate (fara a lua in considerare ID-ul) . Stergem tabela initiala si apoi recopiem din tabela temporara in tabela initiala:

CREATE TEMPORARY TABLE temp AS SELECT DISTINCT event_date, user_id, client_id , tip, observatii FROM events;
DELETE FROM events;
INSERT INTO events (event_date, user_id, client_id , tip, observatii) SELECT * from temp;

Nu e chiar asa de greu, nu-i asa ?
Ca observatie, daca folositi phpMyAdmin, rulati toate cele 3 queryuri odata (in acelasi formular).
NU incercati gluma direct pe tabela buna, incercati pe o copie :

CREATE TABLE events_copy
SELECT * FROM events;

Si faceti un backup inainte de operatie. Aveti oricum un backup de acum 1 ora, nu-i asa ? NU ? Rau faceti.

Dec 8

Odata cu invazia frameworkurilor bazate pe paradigma MVC, in special Ruby on Rails un now buzzword a lovit puternic : “Active Record”. Eh, la ce e bun oare.

Active record este o metoda de abstractizare a bazei de date, prin incaplsularea fiecarei tabele din baza de date intr-o clasa. Ralatiile dintre tabele pot fi si ele declarate, astfel incat anumite tipuri de relatii (Has And Belongs to Many) devin si ele transparente (tabela care tine relatiile de fapt devine transparenta pentru programator). In general din ceea ce am vazut relatiile se mai numesc si “Binds” in jargon Cake.

Probabil cea mai cunoscuta implementare de ActiveRecord pe in PHP este cea din CakePHP.

Sa vedem cam cum arata insa o implementare “virtuala” de ActiveRecord.

Presupunem ca avem o clasa activeRecord si o exitindem cu o incapsulare peste tabela usertable, cu 3 campuri, id (identity, autoincrement), username si password. Codul nostru ar arata cam asa (seamana vag cu ce ai scrie in Cake) :

class User extends ActiveRecord {
    public function __construct() {
        parent::__construct(‘usertable’);
    }
}

Acum avem posibilitatea de a scrie cod de genul :

$user = new User();
$user->username = ‘John’;
$user->password = ‘secret’;
$user->save();

Wow, preety neat. Sa vedem ce putem face mai cool …

//list

foreach($user->findAll() as $myuser) {
    echo ‘id: ‘.$myuser->id;
    echo ‘name: ‘.$myuser->name;
}

//update

$user->findBy('name','Gogu');
$user->name="Gigel";
$user->save();

Frumos , minunat. Insa avem cateva mari probleme cu ActiveRecord :

1. Majoritatea implementarilor care necesita inserturi-update-uri dese omoara masini, indiferent daca motorul de baze de date stie sau nu caching.
2. A folosi active record inseamna ca esti constient ca multe din queryes sunt absolut inutile.

So use it wisely. In general pentru aplicatiile care au un numar limitate de insert-uri/update-uri si multe selecturi e mai sanatos sa foloseti the real thing, SQL pentru partea de prezentare. De asemenea pentru cazurile cand exista cu adevara multe selecturi, diverse “abstraction layers” de baze de date, (adodb sau peardb de ex in cazul PHP) au metode de caching. Bineinteles ca mai exista si mamcached, dar asta e in alta sfera.

Dec 8

Unul din “design patterns” foarte hulit, totodata foarte folosit, si mai ales prost inteles, in mintea multora fiind echivalent cu variabila globala.

Este un termen care insa se refera la Object Oriented Programming, si in general nu are a face cu variabilele globale. Un Singleton e pur si simplu o clasa care odata instantiata nu va permite crearea reinstantierea. Orice incercare de reinstantiere trebuie sa intoarca o referinta la instanta deja existenta.

Pentru a asigura acest comportament trebuie sa observam ca nu avem cum sa ranforsam “unicitatea” decat avand un constructor privat. In aplicatiile care ofera procesare concurenta trebuie de asemenea sa ne asiguram cumva de aceasta unicitate, clasica fiind folosirea mutex pe metoda care intoarce instanta.

Voi da un exeemplu generic din PHP5. constructorul e privat, clone e definit pt a limita clonarea, getInstance e functia publica pe care o vom folosi. $_instance si getInstance() sunt statice, ceea ce inseamna ca pot fi apelate chiar daca clasa nu e instantiata. Ca sidenote, proprietatile si metodele statice nu pot fi apelate prin operatorul sageata “->”, iar cuvantul cheie $this nu are inteles intr-o metoda statica. Iata de ce orice metoda sau proprietate statica poate fi apelata doar prin “sintaxa” className :: myName () respectiv ClassName::$myName

class singleton (
private $myData = array();
private static $_instance = null;

private function __construct() {}
protected function __clone() {}

static public function getInstance() {
if(is_null(self::$_instance))
{
self::$_instance = new self();
}
return self::$_instance;
}

public function import() {...}
public function get() {...}

}

Ce este insa dificil folosind Singleton Pattern ? Pai testarea ar fi una dintre ele. Daca pentru a testa un modul ai nevoie de un mockup object in locul singletonului, si atunci avem o problema. Presupunand ca avem o clasa :

MyClassThatUsesTheSingleton  {
...
public function __construct($settings=null) {
$this->;myData = Singleton::getInstance();
}
...
}

putem redefini constructorul cam asa

MyClassThatUsesTheSingleton {
...
public function __construct($myMockup=null) {
if (is_null($myMockup))  {
$this->;myData = Settings::getInstance();
}
else {
$this->t;myData=$settings;
}
}
...
}

si astfel am rezolvat problema.

Desigur ca se pune intrebarea “la ce e bun singleton”. Eh, nu la prea multe. Un obiect in care sa tii setarile e una din primele chestii care vin in minte. De asemenea in unele aplicatii dorim ca daca avem deja o conexiune la o baza de date s-o folosim pe accea. Exista insa deja conexiuni persistente, probabil mult mai sane de folosit (mai ales in aplicatii web) . Sau daca avem nevoie de log-uri. Logging-ul in general inseamna un obiect apelabil global .

Pentru a afla daca chiar avem nevoie de un singleton trebuie sa vedem daca fiecare parte a aplicatiei pe care o dezvoltam va avea nevoie de o singura instanta a clasei noaste. De asemenea trebuie sa fim siguri ca toate clasele vor apela acest obiect in acelasi fel. Desi este un pattern destul de des folosit, nu este foarte intelept sa-l suprafolosim doar de dragul faptului ca suna cool.