Tuesday, December 1, 2009

AJAX; more than a gimmick || AJAX; Bien plus qu'un gadget

English:


I post this ticket just after the release of a massive web app that extensively use Asynchronous request though javascript (i have a A, i have a J, maybe the other A and sometime the X, sometime the J or also the T). The main reasons were:
- To enhance the user experience.
- To avoid the connection lost between to page.
- And also, to please the client.

However some unexpected benefits emerge; in term of architecture and performance.

For the story , the concept of asynchronous request is not new (i consider the iframe as the first attempt) and the old flash dog will remember this wonderfull actionscript 1.1 function (2002 baby). But it came really popular around 2006 and the rise of the so-called web 2.0 and bring back javascript from the dead.

Anyway, in term of architecture, everybody agree on the fact that the best thing to do when you develop a web app is to split in distinct entities the stacks; That most of the people , do/call MVC pattern. So when to take the time to think about it, you realize that you can use some old school HTML page as view (no template engine or i-push-header-myself-in-the-http-request), your javascript code act as your controller (ndlr. grab asynchronously the data from the server and insert them in the page A.K. the view) and your server-side technology/db act as your model.

So if you already have developed any dynamic web page (a web app is in the approach not that different) you now see me coming.
What is the common data-flow ? "get what should be displayed"(controller) -> "get the proper data from the database" (model) -> fetch them into the view (controller) -> be read by the user (view). On the traditional approach this is all done by the server, the same that all your users connect to. So now imagine you have 2 users at the same time the previous flow is down 2 time and so on. Isn't lot to ask for a poor computer that even don't have a screen and is somewhere in a huge data center ?

When you can do "get what should be displayed"(controller) -> "get the proper data from the database" (model) -> fetch them into the view (controller) -> be read by the user (view) (red stand for process on the client side and orange on the server side).

You see, using AJAX i just free my server from 75% of the tasks, meaning i now have more resources to handle more users, meaning i won't need to buy a second box now and then save money for christmas :D. And to keep on the financial aspect, don't forget that a JSON(that is gziped in the HTTP request)  at least 100 time smaller than a page or event the portion of the page that supposed to contain those data (HTML elements are then created dynamically on the client-side and not sent from the server to the client). So you also save bandwidth (A.K.A. money).

In conclusion, i would say that:
- AJAX is a sort a distributed programming, not in a grid but using your server and the user's machine.
- AJAX help you to save money (less stress on the server, less bandwidth).
- AJAX can help you in you architecture by keeping the logic and the presentation the hard way (we even can say physically).

So was is the downside of it ? It's javascript, or it would be better to say, the web browsers. It's literally each one have it's own implementation of JS. Of course syntax is the same, but the behaviors is so different, and you realize that the biggest part of the work is not to develop the feature, is to make it compatible with the various browsers.

You might ask: Do it worth it ? That's a good question :-)

P.S.: This article is directed toward web application and toward dynamic web contents. Use those technics for a web page is at your own risk of bad indexing.

Francais:
Ca viens

Sunday, October 18, 2009

Do we still need DBMS in web systems ? || A-t'on encore besoin des SGBD dans les systèmes orientés web ?

English:
I am actually working (quite a lot actually) on a system makeover for one of my clients. In a nutshell, it's an on-line (some would call it "cloud") system for their clients to administrate their business. The main issue with this system is the complexity of the process (a lot of the data are generated not just "proccessed") and the traffic. In this configurtion, what is the bottle neck ? The DBMS, and nobody will object.


Since the main reason behind this makeover is because of the intensive usage of the DBMS, the system was slow as hell. I know sql optimization etc... i am not a n00b, but think about this: Event if your sql statement is over-boosted etc... a sql that return 5000 records is still and sql that return 5000 records. That mean, there still 5000 records that the system have to processed, display etc. and i am not talking about the memory space used to store those 5000 records.


So,  i had to think a solution that use as less as possible the db. And i was able to redesign a system by reducing the number of db connection by 90% (maybe more i need to find a way to properly calculate it) and without any lost in term of functionlity and a definitly huge gain in speed and server load.


I then look at my documentation and ask myself: Why using a db for an applicative usage ? i don't put in line the need of a db, i clearly understand the benefit of it for reporting, analysis and other "off-line" operations.


It was possible by using what i call SOCS (Smart Object Caching System) and don't use db at all. Basically SOCS is like ORM, the difference is that instead of using the object as a bridge between the db and the application, the object IS the data and decide whether informations should be read from the db or written in the db. I will write an article later about it when the concept will be "clear enough" in my mind.


When i said "don't use db at all", i really meant it. For example content/file association. the best practice actually is the following flow:
 user access the content page -> retrieve the associed files' informations from the db -> integrate those information in the page
Don't you think there is a problem in this approch ? I always heard that the shortest and fastest path between two point is a straight line (event if i recently discussed the concept of "straight" line recently).
Let's illustrated this statement why the example of articles.
Most of the time, articles (blog tocket, articles etc...) are associated with pictures, pdf files etc... I won't discuss the silly practice you can find in every cms that store the text contents in db instead of a static html version. Anyway, in a decently structured system, every article have a unique id. So now ask yourself, why should you trigger the db to get the path to the images etc... when you can use the god speedly computer file system ? Why storing the file description in a db when you can use it as a file name ? Problem with space or special caracters ? You should maybe have a look at url encoding, base64 encoding etc... (i personanaly like url encoding).
isn't :
<?php
$article = 123456;
$file_list = sandir("/imgs/article/$article_id");
 ?>
<?php foreach($file_list as $image): ?>
<img src="/imgs/article/<?=$article_id?>/<?=$image?>" alt="<?=urldecode(substr($image,0,strrpos($image,'.')))?>"/>
<?php endforeach;?>

Faster than:
<?php
$article = 123456; 
$connection = new connection_to_db();
$sql = "SELECT file_name, file_description from file where article_id = $article";
$result = $connection->query($sql);
?>
<?php while($image = $result->fetch()): ?>
<img src="/imgs/article/<?=$article_id?>/<?=$image['file_name']?>" alt="$image['file_description']?>"/>
<?php endwhile; ?> 




I would simply conclude why the title: Do we still need DBMS in web systems ?


Français: 
Ces dernier temps je travaillais (et pas qu'un peu) sur la refonte d'un système d'un de mes clients. En gros, il s'agit d'un système de gestion en ligne pour aider leurs clients à gérer leur business. Le gros problème avec ce système est que la plupart des informations sont générées et non pas traitées en plus d'un trafic relativement élever. Dans ce cas de figure, quel est le point de rupture ? Le SGBD et personne ne me contredira.


Comme la raison principale de cette refonte et du au fait que le précédant système  utilisé de manière intensive la SGBD ce qui a eu pour conséquence que le système était devenu lent à en mourir. Bien sur je connais les optimisation de sql et ces conneries, mais une sql super optimisée qui retourne 5000 enregistrements, reste une sql qui retourne 5000 enregistrements. 5000 enregistrements qui doivent être traités, affichés etc... Et je ne parle pas de l'espace mémoire.

 Je me suis alors retrouvé penser un système qui solicite le moins possible la bd. Et le pire c'est que j'ai réussit à designer un système où le nombre de connection à la bd a été réduit de 90% par rapport à la précédente version (peut-être plus, mais faut que je trouve le moyen de calculer ça), le tout sans perte fonctionnel et avec un grand gain en terme de vitesse et de charge serveur.


Je me suis alors demandé: Pourquoi utiliser un bd à usage applicatif ? je ne remet pas en cause l'intérêt d'une base de données, je comprend très clairement leurs bénéfices dans les domaines du reporting, de l'analyse et autre traitement hors-ligne.


Ceci fut possible grace a ce que j'appelle SOCS (SMART OBJECT CACHING SYSTEM, en français Système de Cache Objet Intelligent) et pas utiliser la base de données du tout. SOCS c'est un peut comme ORM, à l'exception faite que dans ORM l'objet est un pont entre la base de données et l'application alors que dans SOCS les données sont stockées dans l'objet qui décide s'il faut lire l'information depuis la base ou écrire dans la base ou rien faire :P J'écrirais un article à ce sujet quand le concept sera "suffisamment clair" dans mon esprit.



Quand je disais, "
pas utiliser la base de données du tout", je déconnais pas. Prenons l'exemple de l'association contenue/fichier associés. La "best practice" et de faire:
L'utilisateur accède au contenue -> on connecte à la base de données pour récupérer les fichiers associés -> on les incorpores dans le document
Vous pensez pas qu'il ai un problème là ? On m'a toujours dis que le chemin le plus court et le plus rapide entre deux points était un ligne droite (je sais il n'y a pas longtemps j'ai remis en cause le concept de ligne droite mais bon).
Discutons alors du au combien récurent exemple de l'article.




Un article (un ticket de blog, une page informative etc..) est le plus souvent associé avec des fichiers: images, pdf etc...Je ne discuterais pas la stupide pratique qu'on retrouve dans tout les cms qui consiste à stocker les article dans la base de données au lieu d'un fichier html statique. Toujours est-il,  dans un système qui à une structure décente, chaque article à un identifiant unique. Posez-vous la question suivante: Pourquoi connecter la base de donnée pour obtenir la localisation d'une image etc. quand on peut utilise le système "speedy gonzales" fichier de la machine ? Pourquoi stocker la description d'un fichier dans la base de données quand on peut utiliser le nom du fichier ? Le problème des espaces et des accents ? Connaissez-vous l'encodage en url ou l'encodage en base 64 etc..? (perso j'ai un faible pour l'encodage en url)

N'est-il pas plus rapide de faire:
<?php
$article = 123456;
$file_list = scandir("/imgs/article/$article_id");
 ?>
<?php foreach($file_list as $image): ?>
<img src="/imgs/article/<?=$article_id?>/<?=$image?>" alt="<?=urldecode(substr($image,0,strrpos($image,'.')))?>"/>
<?php endforeach;?>


plutôt que :
<?php
$article = 123456; 
$connection = new connection_to_db();
$sql = "SELECT file_name, file_description from file where article_id = $article";
$result = $connection->query($sql);
?>
<?php while($image = $result->fetch()): ?>
<img src="/imgs/article/<?=$article_id?>/<?=$image['file_name']?>" alt="$image['file_description']?>"/>
<?php endwhile; ?>


Je conclurai avec le titre de cet article: A-t'on encore besoin des SGBD dans les systèmes orientés web ?

 

Wednesday, October 14, 2009

sample of the opencv 2's python interface || example d'utilisation de l'interface python d'opencv 2

English:
I recently was playing with opencv and had a hard time compiling the c code samples (apparently my C/C++ knowledge is outdated) so i decided to take a look at the python samples (that i am way more familiar with). But i quickly realized that the code sample and the new interface don't match (T_T). So after hours of ready this page  and getting crazy on non-exsitent types (ndlr cvSize, cvPoint), i realize that i wasn't reading the most import part of the previous link that say that simple type such as cvSize etc.. are so simple that we can use tuple !!!
Knowing that, i was then able to rewrite the facedect.py (code at the end of the article).

Conclusion: Everything is always in the documentation, we just need to read it !

P.S. : Does anyone know if there is a code plugin for blogspot ?


Francais:
Recement je fasais mumuse avec opencv et rencontrais des difficultes a compiler le code c (visiblement mes connaissance en C/C++ sont depassees). J'ai ansi decide de me jeter sur le code python (que je connais la bien mieux). Cependant, je me suis vite rendu compte que les codes fournis et la nouvelle interface ne colle pas. Donc apres des heures a lire cette page et a m'arrache les cheveux sur des types non existant (cf. cvSize, cvPoint etc..), j'ai remarque que je louper le passage le plus important de l'article sus-cite: les type simple comme cvSize sont maintenant remplace par des tuples !
Etant maintenat au clair avec j'ai pu reecrire la source facedetect.py.

Moralite: Tout est dans la doc, faut juste la lire !

P.S. : vous savez pas s'il existe un plugin code pour blogspot ?





import sys
# i kept it this was to highlight the function from the module but in a real life application
# use form cv import *
import cv
# Global Variables
cascade = None;
storage = cv.CreateMemStorage(0);
cascade_name = "../../data/haarcascades/haarcascade_frontalface_alt.xml";
input_name = "../c/lena.jpg";

# Parameters for haar detection
# From the API:
# The default parameters (scale_factor=1.1, min_neighbors=3, flags=0) are tuned 
# for accurate yet slow object detection. For a faster operation on real video 
# images the settings are: 
# scale_factor=1.2, min_neighbors=2, flags=CV_HAAR_DO_CANNY_PRUNING,
# min_size=
min_size = (20, 20)
image_scale = 1.3
haar_scale = 1.2
min_neighbors = 2
haar_flags = 0

def detect_and_draw(img):
    gray = cv.CreateImage((img.width, img.height), 8, 1);
    small_img = cv.CreateImage((cv.Round (img.width / image_scale), cv.Round (img.height / image_scale)), 8, 1);
    cv.CvtColor(img, gray, cv.CV_BGR2GRAY);
    cv.Resize(gray, small_img, cv.CV_INTER_LINEAR);
    cv.EqualizeHist(small_img, small_img);
    if(cascade):
        faces = cv.HaarDetectObjects(small_img, cascade, storage, haar_scale, min_neighbors, 0);
        if faces:
            for (x, y, w, h), n in faces:
                print "coord (%d,%d) and height:%d width:%d" % (x * image_scale, y * image_scale, w * image_scale, h * image_scale);
        else:
            print "no face found";

if __name__ == '__main__':
    if len(sys.argv) > 1:
        if sys.argv[1].startswith("--cascade="):
            cascade_name = sys.argv[1][ len("--cascade="): ]
            if len(sys.argv) > 2:
                input_name = sys.argv[2]
        elif sys.argv[1] == "--help" or sys.argv[1] == "-h":
            print "Usage: facedetect --cascade='' [filename|camera_index]" ;
            sys.exit(-1)
        else:
            input_name = sys.argv[1]
    cascade = cv.Load(cascade_name);
    if not cascade:
        print "ERROR: Could not load classifier cascade"
        sys.exit(-1)
    image = cv.LoadImage(input_name);
    if(image):
        detect_and_draw(image);


Sunday, October 11, 2009

What if straight line doesn't exist ? || Et si les droites n'existaient pas ?

(English version coming soon)

Récemment je me suis pris des vacances et en ai profité pour faire le tour du Japon. Là vous vous dites; Quel est le rapport entre ses vacances et un concept mathématique fondamental ?

Et bien c'est très simple, j'étais sur la somptueuse plage de Shirahama sur la péninsule de Izu et regardait l'horizon. Et quel fut ma stupeur, la ligne d'horizon si chère au marins n'était pas si droite. Je me suis rendu alors compte que si on s'amusait à tracer une droite, le périple ne nous emmènerait pas aux confins de l'univers mais à notre point de départ; Et oui la Terre est ronde !

Ce qui remet en cause le côté 'infini' de la droite (outch). Et surtout que l'on viens de dessiner un cercle sur le plan yz ,à supposer que l'on trace notre « droite » sur le plan xz (deuxième outch).

Ce qui remet en cause pas mal de chose comme, par exemple les tangentes définies comme des « droites qui touchent un cercle, une courbe, etc. en un seul point ». Ainsi la tangente serait un disque qui contiendrait ce point de contact (quid de savoir où dans le disque).

Nous pouvons alors conclure qu'une droite est en réalité d'une longueur égale au diamètre du cercle dont ses points font parti, et quand à notre exemple de la tangente, ce pose également un problème de profondeur (tengant en un point certe, mais lequel ?).

Monday, September 14, 2009

extend modalbox || etendre modalbox

English:
I recently discover the js library modalbox (http://okonet.ru/projects/modalbox/) that is in my opinion a really powerful tool however i found a way to make it even more powerful!!
It started with the need to do some heavy DOM manipulation in the modalbox (ajax call, dynamic forms etc..). I quickly realized that the html content wasn't integrated in the DOM tree. That was not because of some sort misconception from this lib's author but a javascript's one. If you insert some html snippet in an element using javascript, this content is not parse and therefor not integrate into the DOM tree; ouch!
So i search and found this simple but efficient html parser in javascript. You now just need to insert this file into your code and modify modalbox code as following:

line 273: this.MBcontent.update(new Element("div",{style:"display: none"}).update(content)).down().show();

to:

this.MBcontent.update(new Element("div",{style:"display: none"}).(HTMLtoXML(content))).down().show();

Have fun !!

Francais:
J'ai recement decouvert la librairie js modalbox (http://okonet.ru/projects/modalbox/) que je trouve tres puissante. Toutefois, j'ai trouve un moyen de la rendre encore plus puissante !!! (un smiley du docteur d'enfer serait le bienvenu non ?)
Tout a commence alors que j'avais besoin de faire du gros DOM dans la modalbox et me suis vite rendu compte que ca ne marche pas. Pas du a un oubli de l'auteur mais tout simplement a un probleme dans le javascript. En effet, lorsque l'on injecte du code html via javascript, l'arbre DOM n'est pas mis a jour car javascript ne parse pas le contenu, il l'insert tel quel. Je me suis alors mis a la recherche d'un parser html et trouve ce simple mais efficace parser en javascript. 
Maintenant nous n'avons plus qu'a inserer ce fichier dans notre code et changer la ligne suivante:

ligne 273: this.MBcontent.update(new Element("div",{style:"display: none"}).update(content)).down().show();

en:

this.MBcontent.update(new Element("div",{style:"display: none"}).(HTMLtoXML(content))).down().show();

Amusez-vous bien !!

Tuesday, June 23, 2009

otowl : From relational data representation to object data representation || Du model relationel au model objet

English:

For those who recall a previous post about a project without any name, now i have a name and something to show ! I decided to call this project otowl. otowl stand in a way for "auto-owl" because the goal is to automatically convert relational data into an ontological, object representation. Yesterday, i finally successfully manage to independently form the original context, convert a boolean set of data (understand, the properties for the individuals are true or false) into a hierarchical, ontology represented by an owl/xml file. I am actually working on an online demo that will hit the web soon, keep you updated.
Stay tuned.

Francais:

Pour ceux qui se rappelleront un precedent billet concernant un projet sans nom, il en a maintenant un et utilisable ! J'ai ainsi decide de l'appeler otowl. otowl en partie signifie "auto-owl" car le but de ce projet est de propose un mecanism de convertion automatique de donnees sous forme relationnel vers un model ontologique, objet. J'ai finalement reussit hier a convertir un ensemble de donnees relationelles bouleennes (a comprendre que les proprietes d'un individu sont vraies ou fausses) vers un ensemble hierarchise, ontologique sous la forme d'un fichier owl/xml. Je travaille en ce moment sur une demo qui devrais arriver sur la toile tres prochainement.

Sunday, June 21, 2009

IE8 javascript & css quick fix || resolution rapide de probleme de javascript et css avec IE8

English:

I experienced some compatibility issue with some old js under IE8. For example, prototype.js's users, try new Element('div',{'class' : 'my_css_class'}). Yes, the style is not loading and don't throw any error. Troublesome isn't it ?

Therefor you can use  <meta content="IE=EmulateIE7" http-equiv="X-UA-Compatible" /> that will force IE8 to emulate 7 and will run accordingly.


Francais:

J'ai recement experimente quelques problemes de compatibilite entre IE8 et quelques vieux javascript. 
Par exemple, les utilisateurs de prototype.js pouront essayer new Element('div',{'class' : 'my_css_class'}). Et oui, le style ne charge pas. problematique non ?

Ansi, la directive  <meta content="IE=EmulateIE7" http-equiv="X-UA-Compatible" /> va forcer IE8 a emuler 7 et executer les commandes de la meme maniere.

Tuesday, June 9, 2009

manipulation de chaines de caractere japonaise en php | japanese string manipulation in php

*English version, go to the bottom of this post.

Francais:

Tout developeurs qui a eu la malchance de travailler au/avec le Japon s'est tres vite rendu compte que manipuler des chaines de caractere n'est aussi facile qu'qvec la langue de Moliere ou de Shakespeare. Encore plus malheureux sont les gens qui sont sur des projets php ou mes fonction mb_* ne fonctionnent pas aussi bien. Certain caracteres font 1 octet, d'autre 2 et voir meme pour certain 3. Cependant, j'ai lus (il y a maintenant un bout de temps) cet article en japonais http://phpspot.org/blog/archives/2005/11/php_17.html . L'expression reguliere presentee doit, en theorie, decouper en morepheme un texte en japonais. Autant vous dire que le linguiste qui est en moi, est en totale desaccord avec ce qu'avance son auteur. Neanmois, j'y ai vu la un interessant point de depart pour la manipulation de chaine de charactere japonaise et tout particulierement celle en SJIS. En modifiant un peu l'expression reguliere, j'ai obtenue un bon vieux tokenizer a 1 caractere des familles. Cela faisant, j'ai pu reimplementer tout les fonctions de base mais au combien pratiques comme substr, strpos, strlen etc...

English:

Every php developer who work in japan realized that mb_* function don’t work that good with SJIS encoded string. Some characters are considered as 1 byte length, or as 2 bytes and some as 3 bytes |-| ; Not really useful in the end. i recently discovered this article (in Japanese : http://phpspot.org/blog/archives/2005/11/php_17.html). The presented regEx is supposed to split a Japanese string into word. Linguistic-wise, I’m completely disagree with the results, but it was an interesting starting point for Japanese string manipulation and specially SJIS encoded ones :> . then i changed a little bit the regEx in order to obtain a one-character tokenizer. This regEx allow me afterward to re implement the basic but really useful string manipulation commands as substring, str_replace, strpos, strlen etc…

<?php

/*implementtation of the most basic string manipulation function for japanese, work the same way as the monobytes ones*/

class processJ
{
public function __construct()
{
mb_regex_encoding("SJIS");
}
public function __destruct()
{
}

//this method split a sjis encoded japanese string by character an return an array
public function charSpliter($str)
{
$token = array();
while(1)
{
     $bytes = mb_ereg("[一-龠]|[ぁ-ん]|[ァ-ヴー]|[a-zA-Z0-9]|[a-zA-Z0-9]", $str, $match);
     if ($bytes === false) {
       break;
     } else {
         $match = $match[0];
         $token[] = $match;
     }
     $pos = strpos($str, $match);
     $str = substr($str, $pos+$bytes);
}
return $token;
}
public function substrJ($str, $start, $lenght = NULL)
{
$strToken = $this->charSpliter($str);
$end = !empty($lenght) ? $lenght : count($strToken);
$substr = "";
for($i = $start; $i < $end; $i++)
{
$substr .= $strToken[$i];
}
return $substr;
}
public function strlenJ($str)
{
$strlen = $this->charSpliter($str);
return count($strlen);
}
public function strposJ($haystack, $needle)
{
$strToken = $this->charSpliter($haystack);
$needleToken = $this->charSpliter($needle);
$tokenLen = count($strToken);
$needleLen = count($needleToken);
for($i = 0; $i < $tokenLen; $i++)
{
if($strToken[$i] == $needleToken[0])
{
for($j = 0; $j < $needleLen; $j++)
{
if($needleToken[$j] !== $strToken[($i+$j)])
{
continue 2;
}
}
return $i;
}
}
}
public function str_replaceJ($search, $replace, $subject)
{
return $this->substrJ($subject,0,$this->strposJ($subject,$search)).$replace.$this->substrJ($subject,($this->strposJ($subject,$search)+$this->strlenJ($search)),$this->strlenJ($subject));
}
}

$test = new processJ(); print($test->substrJ("ようこそcyberblogへ漢字",0,4));  //> "ようこそ"
print($test->strlenJ("ようこそcyberblogへ漢字")); //> 16 
print($test->strposJ("ようこそcyberblogへ漢字", "cyber")); //> 4 
print($test->str_replaceJ("cyberblog","サイバーブログ","ようこそcyberblogへ漢字")); //> "ようこそサイバーブログへ漢字" 
?>