samedi 22 décembre 2018

Quand la loi d'ATWOOD se vérifie une nouvelle fois: Javascript

La loi d'Atwood se formule de la manière suivante: toute application qui peut être écrite en JavaScript, sera finalement écrite en JavaScript
ici un lien vers un article précédent sur le sujet.

Cette loi est a nouveau vérifiée aujourd'hui et d'une façon forte.

En effet , Martin Fowler a sorti la deuxième edition de son livre incontournable :

Refactoring

Improving the Design of Existing Code

Dans la première édition ,les exemples de ce livre étaient en Java.

The book is written using Java as its principle language, but the ideas are applicable to any OO language.

Dans la nouvelle édition; les exemples sont en ..Javascript.



Now, Fowler has thoroughly updated his book to reflect modern programming techniques.


Tous les développeurs se doivent d'avoir ce livre en bonne place sur leur bureau.

refectoring, testing, refactoring, testing, GOTO début.

“Any fool can write code that a computer can understand. Good programmers write code that humans can understand.” 
—M. Fowler (1999)



dimanche 17 septembre 2017

Liens utiles sur la blockchain

Je donne ici des liens utiles pour suivre l'actualité de la blockchain.

Blockchain daily news : site en francais.

Blockchain france.

Le top 250 des entreprises de l'ecosystème blockchain.

A partir de cette liste et des mots clé j'ai généré l'image suivante:

Bitcoin : graphique sur les volumes d'échange: bitcoincharts

Visualisation de block : blockcypher

dimanche 10 septembre 2017

La blockchain: quelle révolution ?

Le concept de blockchain est présenté comme une révolution d'Internet. Son utilisation dans le domaine financier a été largement mis en avant par le développement des cryto-monnaies comme le Bitcoin ou l'Etherium.
Je prépare une présentation de 40 minutes sur le thème de la blockchain.  Le  fil conducteur la  sera construit sur les éléments de réponse à cette question: la blockchain est elle une révolution ?

Pour m'aider dans cette tache, j'ai depuis quelques mois assemblé une carte de connaissance.
Le source  de la carte (réalisée avec freeplane) est disponible sur github a cette adresse:
lemon-labs blockchain .
Merci pour votre aider à la compléter.


Ici le lien de l'illustration à télécharger pour zoomer.



mardi 13 juin 2017

Recherche de performance d'un programme python

Il est toujours intéressant de comprendre comment se décompose le temps d'exécution d'un programme. Cette démarche peut s'inscrire dans le cadre d'une recherche de la performance mais aussi dans le but d'utiliser au mieux des bonnes pratiques.

Avant tout, il est nécessaire d'avoir une mesure du temps d'exécution d'un programme. Le moyen le plus simple est d'utiliser la commande 'time'.  J'emploie cette commande avec l'option '-p' qui permet un affichage en seconde.

exemple:


time -p  python   programm1.py






Pour avoir le détail sur les fonctions qui consomment le plus en terme de temps d'exécution, il faut réaliser une opératoin de 'profilage'.  Le module cProfile est mon préféré car il s'utilise de manière externe sans modification du source et il est déjà installé. 

La commande pour l'activer est la suivante: 
python -m cProfile  -o eg.prof programme1.py 

L'option '-o'   est suivie du nom de fichier où seront stocké les statistiques.  L'option -s vient en exclusion avec l'option -oo , l'option 's' comme 'sort'  affecte un critere de tri  : exemple -s cumtime pour trier sur le temps cumulé.

 Exemple de sortie: 

       28917791 function calls (28917181 primitive calls) in 376.750 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       66    0.000    0.000    0.000    0.000 :102(release)
       59    0.000    0.000    0.000    0.000 :142(__init__)
       59    0.000    0.000    0.002    0.000 :146(__enter__)
       59    0.000    0.000    0.001    0.000 :153(__exit__)
       66    0.001    0.000    0.001    0.000 :159(_get_module_lock)


Cette sortie n'est pas toujours facile à lire aussi j'utilise une interface graphique Kcachegrind (ou qcachegring sur MacoSX) 

L'installation de qcachefrind se fait par: 
brew install qcqchegrind
Puis
brew install graphviz

Il reste à convertir un fichier cProfile au format callgrind avec la commande:
pyprof2calltree -i eg.prof -o ant2.grind

(avec -i pour le fichier en entrée, l'option -o pour le fichier en sortie )


Le travail d'optimisation peut commencer en tenant compte de deux axes: 
Le temps d exécution d'une méthode (en seconde ou en %) et le nombre d'appel à cette fonction




Dans cet exemple la fonction recherche_conditionC3 est appelée 26524 fois et représente un coût de 85%.

La fonction avant optimisation est comme ceci :

def recherche_conditionC3(self, cle,date):
    resultat = 'KO'
    ligne=[]
    for item in self.tableC3:
       if item[0] == cle:
        if date >= item[1]:
            ligne = item
            resultat = 'OK'
       if item[0] > cle:
         break
    return(resultat,ligne)

Il est possible de remplacer une recherche systématique par un pattern de memoization: c'est à dire un type de cache.
....
  clecache = cle + date.strftime('%m-%d-%Y')
    if clecache in C3taux.dictC3taux:
      #pdb.set_trace()
      return('OK',C3taux.dictC3taux[clecache])
sinon : continuer dans la méthode.


Avec comme résultat: un cout de moins de 1% 




Après une série d'optimisation,  de 260 secondes on tombe à 80 secondes. 

Ces techniques n'empêchent pas d'avoir une réflexion préalable sur une conception capable d'encaisser des montées en charge.

L'outil qcachegrind propose des vues  sur les arbres d'appel des méthodes


dimanche 27 novembre 2016

Pour bien commencer avec un Raspberry

Pour quelques dizaines d'euros, il est possible d'avoir à sa disposition un veritable ordinateur.
Cette ordinateur autorise la réalisation de projets divers.


Voici quelques conseils:

Choisir  pour commencer un kit complet

Ces kits sont livrés avec un SD carte déjà configurée. Elles sont proposées avec plusieurs systèmes d'exploitation (carte noob) .


Ces kits sont mis en route en quelques minutes.

Le wifi intégré: comment configurer une clé WEP sur la RASBIAN .

Les réseaux wifi sont sécurisés avec des mécanismes  de robustesse  différents. 
Les anciens réseau sont sécurisés avec le protocole WEP, les nouveaux réseaux utilisent WPA qui est plus robuste.
La distribution RASBIAN dérivée de la DEBIAN propose un outil de configuration di wifi qui ne reconnait pas le protocole WEP.  Pour contourner cette limitation, il sera nécessaire de modifier le fichier /etc/network/interfaces en complétant les parametres: 
 wireless-essid mybox
 wireless-key XXXX

Installation de docker. 

le système de conteneur docker a été porté sur Raspberry : 
Pour cela suivre les indications du site Hypriot.com.
Exemple ci-dessus du lancement d' HelloWorld sous docker dans une console (en fond le bureau du Raspberry)
 $docker run  hypriot/armhf-hello-world:latest


Utilisation d'une console USB/SERIAL


On trouve sur Internet des cables USB/SERIAL qui permettent de prendre en main le raspberry via son ordinateur. Cela permet de pouvoir configurer son raspberry sans écran ou clavier.

Après installation du driver COM  sur MacosX et branchement du cordon , il suffit de lancer la commande  dans le terminal :  screen /dev/cu.usbserial 115200 


Installation d'un serveur FTP

Le serveur pure-ftp fonctionne parfaitement sur mon raspberry. 

Installation de nodeJS

Un simple apt-get install nodejs , installera tout le necessaire pour exécuter du javascript en mode serveur.
pi@raspberrypi:~ $ nodejs -v
v0.10.29


Pour terminer : la rasbian est livré avec 2 versions de python installées: python 2.7  et python 3.4

De quoi passer des bons moments.


samedi 9 avril 2016

La loi de Jeff ATWOOD sur le #javascript se vérifie tous les jours

Jeff Atwood est une légende du développement, co-fondateur du site stackoverflow
Il rédige régulièrement des billets sur son blog : coding horror.


Dans un de ses articles il énonce sa loi :  toute application qui peut être écrite en JavaScript, sera finalement écrite en JavaScript. Ou formulée autrement : tout programme quelque soit son langage d'écriture finira par être porté en javascript.

C'est un corollaire au principe du langage 'faible' de Tim Berners-Lee. Dans cette publication , le créateur du WEB énonce la règle du langage faible : Il recommander ne pas utiliser un langage puissant pour diffuser de l'information.
Un langage qui encapsule et protège les données ferme la porte à la réutilisation des algorithmes et des données.

La loi d'ATWOOD dresse le constat que le javascript est devenue le langage universel du WEB. Un navigateur et du javascript peuvent remplacer n'importe quelle application. Il est même possible de se passer de serveur ou d'internet. article :JavaScript:The Lingua Franca of the Web

Et c'est vrai qu'il est plaisant pour un ancien comme moi de retrouver dans son navigateur les jeux qui ont jalonnés mes débuts: exemple prince de perse dans son navigateur ou encore l'éternel DOOM.




Cette loi a encore été vérifiée lors du hackathon « codeimpot » où un projet a fait tourner la calculette impots dans un navigateur par  une traduction en javascript du langage M.
Tous les projets ont utilisés AngularJS pour l'affichage.


Il est même possible grace au javascript de transformer son navigateur en serveur web.
Ce  module    installe un serveur web nodeJS dans votre navigateur qui peut a son tour répondre à des requêtes HTTP.


En conclusion : autant écrire les applications directement en javascript afin d'éviter d'avoir à les traduire plus tard.

mardi 22 décembre 2015

Petit exercice pour bien comprendre la programmation en javascript


Connaitre la syntaxe du javascript est une chose mais en saisir les subtilités (asynchrone, callback, programmation fonctionnelle)  en est une autre.


L'exercice suivant est synthèse de ce qu'il faut comprendre de la programmation asynchrone.

Prenons l'exemple d'une boucle 'for'


for (var a = 0 ;a < 5 ; a++)
 { console.log("valeur de a sync:" , a); }

L'affichage donnera

valeur de a sync: 0
valeur de a sync: 1
valeur de a sync: 2
valeur de a sync: 3
valeur de a sync: 4

Pas de surprise , ici toutes instructions sont synchrones

Si on introduit la notion d'asynchronisme par le biais d'une temporisation:
(avec une délais de 100 ms et 1 ms)

for (var a = 0 ;a < 5 ; a++)
 { setTimeout(function(){ console.log("valeur de a async 100:" , a);}, 100); }

for (var a = 0 ;a < 5 ; a++) { setTimeout(function()
 { console.log("valeur de a async 1:" , a);}, 1); }

Le résultat sera cette fois plus étonnant:
(extrait)
valeur de a async 1: 5
valeur de a async 1: 5
valeur de a async 1: 5
valeur de a async 1: 5
valeur de a async 1: 5
valeur de a async 100: 5
valeur de a async 100: 5
valeur de a async 100: 5
valeur de a async 100: 5
valeur de a async 100: 5

Deux phénomènes:  un normal (a) et un moins intuitif (b).
a) Les lignes relative à la temporisation la plus faible se présentent en premieres alors qu'elles sont les dernières invoquées.
C'est le principe de l'asynchronisme: Le système n'attend pas le retour de l'instruction (appel de fonction)  pour passer à la suivante.

b) La valeur du compteur est bloqué à 5. 
Dans la cause se niche toute la subtilité d'un système asynchrone: l'appel de la fonction  embarquée dans le timer se fera avec le contexte du moment de l'exécution. A la sortie de la boucle 'for' la valeur de 'a' est 5 et donc les 5 appels de fonction déclenchées par le timer se feront avec un même contexte 'a=5'  

Comment obtenir une sortie conforme à nos  attentes : en utilisant les closures (fermetures).
Une closure permet de conserver le contexte au moment de l'appel de la fonction.

exemple ici :

for (var a = 0 ;a < 5 ; a++)  { 
  setTimeout(function(){ 
    var i = a;
    console.log("valeur de a async 100  avec param :" , i);}, 100);    
}

La variable 'a' est bien déclaré au niveau du 'FOR' et appelée dans le corps d'une fonction imbriquée dans la boucle. Mais le résultat n'est pas probant:

valeur de a async 100  avec param : 5
valeur de a async 100  avec param : 5
valeur de a async 100  avec param : 5
valeur de a async 100  avec param : 5
valeur de a async 100  avec param : 5

Pourquoi ? :  Pour 2 raisons :

a) Les 5 closures partagent le même contexte donc il 'est normal d'avoir 5 fois la même valeur.
b) La fonction est littéralement appelée après la boucle 'for' : il est trop tard, le contexte a été perdu.

La solution: appeler la closure dans le 'for' et avec les 5 contextes 
Pour cela le programme est modifié comme ceci:

for (var a = 0 ;a < 5 ; a++)
 { setTimeout(function(a){ 
   console.log("j appelle le constructeur de fonction avec",a);
   return function () { 
                       var i = a;
                        console.log("valeur de a async 1000 avec closure :" , i);}
    }(a), 1000);
 }
En plus de la closure, on ajout un constructeur de fonction.
Dans le 'for' , on passe en paremètre au timer , non pas une fonction à executer mais une fonction qui retourne une fonction à exécuter. C'est le point fort de ce type de langage de considérer les fonctions comme des données (entier, chaine etc) .

Pour que le contexte soit conservé en l'état pour les 5 itération, la fonction de construction est appelée immédiatement par l'utilisation des  doubles parenthèses et d'un paramètre  à la fin de sa définition " }(a), 1000);".

Le résultat est maintenant correct 

j appelle le constructeur de fonction avec 0
j appelle le constructeur de fonction avec 1
j appelle le constructeur de fonction avec 2
j appelle le constructeur de fonction avec 3
j appelle le constructeur de fonction avec 4
valeur de a async 1000  avec closure : 0
valeur de a async 1000  avec closure : 1
valeur de a async 1000  avec closure : 2
valeur de a async 1000  avec closure : 3

valeur de a async 1000  avec closure : 4

Ce mécanisme est couramment utilisé par jquery, c'est la base d'une programmation correcte en javascript.

Pour aller plus loin :  La magie des closures.