Claudiu Persoiu

Blog-ul lui Claudiu Persoiu


Archive for 26 January 2010

Oracle cumpara Sun – un nou episod

without comments

Se pare ca Oracle a primit aprobarea de la EU pentru a cumpara Sun conform Yahoo! News.

Acum aproximativ un an jumatate ma gandeam sa sustin examenul pentru MySQL Certified Developer. Acum dupa ce am devenit Sun MySQL Certified Developer se pare va voi deveni Oracle MySQL Certified Developer. Si toate acestea fara nici un ban in plus! 🙂

Partea buna este ca vom ajunge sa lucram cu Oracle chiar si fara voia noastra (ok, nu e chiar Oracle, dar e un produs al lor).

Written by Claudiu Persoiu

26 January 2010 at 9:57 PM

Posted in Diverse,MySQL

Tagged with , ,

Factory method pattern folosind PHP 5.3 si late static bindings

without comments

Factory method design pattern introdus de GoF (Gang of Four) pe care l-am abordat si eu intr-un blog anterior, are la baza ideea unei metode care genereaza obiecte. In general implementarea este destul de “slaba” pentru ca “factory”-ul este destul de hardcodat (la fel ca mine in blogul anterior).

PHP 5.3 ofera totusi posibilitatea unei implementari foarte interesante folosind “Late static bindings“.

Clasele pe baza carora se vor genera obiectele:

// clasa abstracta de baza care urmeaza sa fie mostenita
abstract class Drink {

    // ingrediente
    protected $ingredients;

    // metoda publica care genereaza bautura
    abstract public function MakeDrink();
}

// o clasa derivata pentru ceai
class Tea_Drink extends Drink {

    // ingrediente pentru ceai
    protected $ingredients = array('tea', 'sugar', 'mink', 'water');

    // generare ceai
    public function MakeDrink() {

        // fa ceai
    }
}

// clasa derivata pentru Bloody Mary
class BloodyMary_Drink extends Drink {

    // ingrediente Bloody Mary
    protected $ingredients = array('votka', 'salt', 'tomato juice');

    // generare Bloody Mary
    public function MakeDrink() {

        // fa BloodyMary

    }
}

Idea este de a avea o clasa abstracta care va fi extinsa intr-un mod cat mai simplu pentru a genera noi clase factory.

PHP 5

In PHP 5 clasa ar arata cam asa:

// clasa Factory abstracta
abstract class absFactory {

    // numele clasei de baza
    static protected $base_class = '';

    // metoda factory
    public static function getInstance($type) {

        // numele clasei rezultat
        $class_name = $type . '_' . self::$base_class;

        // se testeaza daca clasa exista
        // aici se poate adauga si un autoloader eventual
        if(!class_exists($class_name)) {
            throw new Exception( 'Class ' . $class_name . ' not loaded!');
        }

        // se verifica daca clasa mosteneste clasa de baza
        if(!is_subclass_of($class_name, self::$base_class)) {
            throw new Exception(
                'Class ' . $class_name . ' is not a child of ' . self::$base_class
            );
        }

        // noul obiect
        return new $class_name;

    }

}

Pentru ca metoda getInstance este statica si proprietatea este statica.

Daca incercam:

class DrinkFactory extends absFactory {

    static protected $base_class = 'Drink';
}

try {

    $obj = DrinkFactory::getInstance('Tea');

} catch (Exception $e) {

    echo $e->getMessage();
}

Output-ul va fi:

Class Tea_ not loaded!

Din pricina “self”, nu putem apela pur si simplu metoda getInstance() din clasa copil pentru ca valoarea lui $base_class va fi “” in loc de “Drink”, trebuie suprascrisa metoda getInstance(). Lucru prea “complicat”.

O versiune functionala in PHP 5 ar fi:

class DrinkFactory extends absFactory {

    public static function getInstance($type) {

        self::$base_class = 'Drink';

        // metoda factory a clasei factory de baza
        parent::getInstance($type);

    }

}

try {

    $obj = DrinkFactory::getInstance('Tea');

} catch (Exception $e) {

    echo $e->getMessage();
}

Dar nu mi se pare tocmai “elegant”.

PHP 5.3

Aici avem “Late static bindings”, care in principiu este introducerea cuvantului “static”.

Clasa de baza factory arata cam asa:

// clasa Factory abstracta
abstract class absFactory {

    // numele clasei de baza
    static protected $base_class = '';

    // metoda factory
    public static function getInstance($type) {

        // numele clasei rezultat
        $class_name = $type . '_' . static::$base_class;

        // se testeaza daca clasa exista
        // aici se poate adauga si un autoloader eventual
        if(!class_exists($class_name)) {
            throw new Exception( 'Class ' . $class_name . ' not loaded!');
        }

        // se verifica daca clasa mosteneste clasa de baza
        if(!is_subclass_of($class_name, static::$base_class)) {
            throw new Exception(
                'Class ' . $class_name . ' is not a child of ' . static::$base_class
            );
        }

        // noul obiect
        return new $class_name;

    }

}

Diferentele fata de PHP 5 sunt marcate cu bold. O schimbare atat de mica permite totusi o clasa factory mult mai “atragatoare”:

class DrinkFactory extends absFactory {

     static protected $base_class = 'Drink';

}

try {

    $obj = DrinkFactory::getInstance('Tea');

} catch (Exception $e) {

    echo $e->getMessage();
}

Practic in aceasta varianta nu se inlocuieste decat proprietatea statica relevanta in acest context.

Written by Claudiu Persoiu

24 January 2010 at 5:46 PM

Posted in Design patterns,PHP

Tagged with , , ,

Factory method design patten in PHP

without comments

Un design patten creational care reprezinta o solutie pentru a genera obiecte fara sa se specifice clasa acestuia. In mod particular orice metoda care genereaza obiecte reprezinta o implementare de Factory Method pattern.

Motivatie:

O motivatie este ca, sarcina de a creea obiectul este delegata catre metoda factory.

Diagrama:

factory method pattern

Implementare:
Clasele care genereaza obiecte prin factory, clasa comuna care va fi extinsa si clasa cu metoda fatory:

// clasa comuna care va fi extinsa
abstract class OutputBase {
     // output headerele necesare
     abstract public function header();

     // corpul rezultat
     abstract public function body($data);

}

// clasa pentru output xml
class XMLOutput extends OutputBase {

     // output header xml
     public function header() {
          header('content-type: text/xml');
     }

     // document xml
     public function body($data) {
          $res = '';

          $res .= '';

          foreach ($data as $root => $item) {

               $res .= '';

               foreach ($item as $key => $val) {
                    $res .= '<'.$key.'>'.$val.'';
               }

               $res .= '';
          }

          $res .= '';

          return $res;

     }

}

// clasa pentru output csv
class CSVOutput extends OutputBase {

     // output header csv
     public function header() {
          header("Content-type: text/plain");
     }

     // corp csv
     public function body($data) {
          $res = '';

          $keys = array_keys($data[0]);

          foreach ($keys as $key) {
               $res .= '"'.$key.'";';
          }
          $res .= "\r\n";

          foreach ($data as $item) {
               foreach ($item as $val) {
                    $res .= '"'.$val.'";';
               }

               $res .= "\r\n";
          }

          return $res;
     }
}

// clasa cu metoda factory
// este abstracta pentru a nu fi instantiata
abstract class OutputFactory {

     // constanta pentru timpul xml
     const XML = 1;

     // constanta pentru tipul csv
     const CSV = 2;

     // metoda statica factory
     public static function getInstance($type) {
          // in functie de constanta primita ca parametru
          // va intoarce unul din obiecte
          switch ($type) {
               case self::XML :
                    return new XMLOutput();
               break;

               case self::CSV :
                    return new CSVOutput();
               break;
          }

          // daca valoarea primita ca parametru nu este una din constante
          // se arunca o exceptie
          throw new Exception('Invalid class type!');
     }

}

Exemplu:

// se de date
$data = array(
               array(
                    'a' => 1,
                    'b' => 2,
                    'c' => 3
                    ),
               array(
                    'a' => 4,
                    'b' => 5,
                    'c' => 6
                    )
          );

//Bloc try-catch pentru a prinde eventualele exceptii
try {
     // generare obiect
     $obj = OutputFactory::getInstance(OutputFactory::XML);

     // output headere
     $obj->header();

     // afisare body
     echo $obj->body($data);

} catch (Exception $e) {

     $e->getMessage();

}

Written by Claudiu Persoiu

23 January 2010 at 6:21 PM

Posted in Design patterns

Tagged with ,

A mai trecut un an iar PHP 6 tot nu este aici…

without comments

A mai trecut un an iar PHP 6 tot nu e aici…

Dar asta nu este tocmai o noutate, este al 4-lea an in care aceasta versiune mult asteptata nu se lanseaza, nu degeaba este numita cea mai asteptata versiune.

Totusi a fost un an bun pentru comunitate, chiar daca Unicode nativ nu exista inca intr-o versiune stabila, acum avem cam toate celelalte noutati asteptate in PHP 5.3, care probabil va mai avea nevoie de cativa ani ca sa devina folosit pe scara larga.

Chiar daca toata lumea astepta in acest an ca Oracle sa intre in forta pe piata de baze de date medii si mici prin achizitia Sun, marind portofoliul deja detinut pe piata enterprise. Se pare ca nu a fost asa, CE inca analizeaza propunerea.

Oricum MySQL nu mai este ce era acum 5-6 ani, cand nimeni nu indraznea sa-l foloseasca pentru produse enterprise, acum MySQL este un produs gata pentru a fi folosit atat pentru proiecte mici cat si pentru produse care necesita muta scalabilitate.

Dar revenind la anul care tocmai s-a incheia, a fost un an plin, chiar si in timp de criza.

Written by Claudiu Persoiu

13 January 2010 at 8:30 AM

Posted in Diverse,MySQL,PHP

Tagged with , ,