Affichage des articles dont le libellé est code. Afficher tous les articles
Affichage des articles dont le libellé est code. Afficher tous les articles

dimanche 25 janvier 2015

Vos programmes sont gangrénés par les librairies des autres

Ne pas ré-inventer la roue. Cette formule est érigée en dogme dans l'informatique.
C'est oublier un peu vite que la finalité d'une roue est de tourner... tout simplement... Tourner pour avancer.
On revient de plus en plus à la notion d'artisan développeur, mise en avant par le mouvement devops.

Ce changement repose sur  par 3  idées:

1) Les libraires mettent en danger votre système d'information.
C'est vrai qu'il est dans un premier temps plus simple et moins couteux d'utiliser des librairies et d'assembler des composants externes.
Mais, ces librairies rendent dépendant vos projets de l'évolution de ces portions de code externes.
Dans le monde opensource, une constante mise à niveau est nécessaire sous peine de fragiliser l'ensemble du code. Ce phénomène de course à l'échalote est maitrisé dans les systèmes propriétaires comme les mainframes ou le '.NET'.
L'exemple de la librairie openssl est le plus frappant. Des dispositifs ouverts sur Internet, utilisant cette librairie sont des proies faciles. En clair: une porte blindée ne sert à rien si on laisse la fenêtre de la cuisine ouverte.

2) Les nouvelles infrastructures.
Les plateformes d'accueil sur un cloud, ne permettent pas toujours d'utiliser des librairies externes. Le développeur ne dispose que d'un cadre réduit et ne peut  utiliser qu'un système de dépendance simple. Pour cela , je vous conseille la lecture de la charte des 12 facteurs (principes) à respecter pour écrire une application web prête pour le cloud.
Avec  2 règles fortes:
a) Maitrise des dépendances par l'isolation des librairies.
b) L'application doit ouvrir son port d'écoute (aurevoir apache, tomcat, bonjour node.js)

3) Dilution des connaissances.

A force d'utiliser des librairies toutes faites, les développeurs s'éloignent des fondamentaux.  Tout le monde utilise des librairies XML peu de personnes connaissent vraiment le XML et comment le parser (traduire). La manipulation du JSON est à mettre dans le même pannier. Je ne parlerai pas de la perte de connaissance du SQL due à l'usage hors de propos d'Hibernate.

Les développeurs se retrouvent au centre de la révolution numérique. Car finalement c'est eux qui détiennent la clé des futures applications de demain.
Je vous conseille la lecture du rapport de Tarik Krim (lien ici) qui rend hommage au talent des développeurs français.

En conclusion: pour comprendre la roue, il est bon parfois de la réinventer.
L'exercice s'appelle le ghetto développement, c'est à dire repartir de zéro et faire tout, tout seul.
C'est ce que fait la société spaceX pour construire ses fusées: pas de sous traitant, tout est de fabrication interne. Comme un clin d'oeil aux ingénieurs de la Nasa  et l'equipage d'Apollo XIII obligés de  réparer la capsule avec les moyens du bord.







 
 

mercredi 8 septembre 2010

Où trouver une bonne réponse technique : #stackoverflow et #web_applications

Joel Spolsky tient un blog sur le développement qui fait référence dans ce domaine.

Avec son ami Jeff Atwood ils ont lancé avec succès le site de question/réponse : stackoverflow

L'idée directrice est la suivante: quand un développeur est face à un problème comment trouver la bonne solution. Le premier réflexe est de demander à google, mais en cas de réponse multiple, comment choisir la plus pertinente ?

Ainsi le site stackoverflow est une sorte de FAQ géante où il est possible de noter la justesse des réponses.

(copie d'écran du site)



L'auteur à lancé récemment un site analogue pour les applications web (lien ici).
Les sujets ouverts concernent facebook, youtube, google, google-aps etc.






Ces sites sont très utiles, le dernier né propose une charte graphique originale :



ou encore

mardi 29 juin 2010

Ecriture d'un module pour le serveur #http #nginx

redstar2
J'ai développé un petit module de test pour le fameux serveur HTTP NGINX.

Ce module ne sert qu'a jouer avec la configuration et les librairies du serveur,
d'où son nom : nginxsandbox.

Le code C du module est disponible dans lemon-labs de github.

J'ai aussi écrit un shell permettant d'automatiser la compilation et le test d'un module Nginx : monmake.sh

make clean
./configure --with-debug --with-http_stub_status_module --add-module=/usr/local/nginxsandbox/
make
make install
cp /root/nginx.conf /usr/local/nginx/conf/
kill `cat /usr/local/nginx/logs/nginx.pid`
sleep 3
/usr/local/nginx/sbin/nginx > /usr/local/nginx/logs/error.log




Ce script est à installé dans le répertoire des sources du serveur.

Il suffit ensuite de créer un répertoire abritant votre module en dehors de cette arborescence.

Le script commence par faire le ménage dans le répertoire de compilation, puis lance le programme de configuration avec les bonnes options. Pour ma part,j'ai donc ajouté le module nginx status et le mien.
Après le make install, je recopie une sauvegarde de mon fichier de conf dans le répertoire de conf du daemon nginx.

Enfin, je coupe le serveur et je le relance.

Faire pointe pointer le browser sur localhost/sandbox doit donner :
(clic pour agrandir)



Le fichier de conf est modifié de la sorte :


location /nginx_sandbox {
sandbox on;
}





La lecture du "guide d'emiller" est le point de départ à l'écriture d'un module.
Ainsi paré de la ceinture de Batman, l'aventure peut commencer.

mercredi 18 novembre 2009

Crible d' Eratosthène en Erlang (nombres premiers)



Sur le wiki du langage GO de Google, se trouvait un exemple de proggramme qui utilisait le crible d' Eratosthène pour générer la liste des nombres premiers.

Cet exemple utilisait un chainage de filtre, le nombre à tester est injecté dans le premier filtre de la chaine. Chaque filtre teste le reste de la division de ce nombre par un nombre premier déjà trouvé. En cas d'échec, le filtre envoie le nombre à tester au filtre suivant ainsi de suite jusqu'au dernier filtre.

A la fin de ce dernier filtre, et en cas d'échec, le nombre est qualifié de premier et devient le filtre suivant en étant ajouté en bout de chaine.

La réalisation en GO commence par la création d'une fonction générateur.
Sous cette forme:

09 // Send the sequence 2, 3, 4, ... to channel 'ch'.
10 func generate(ch chan int) {
11 for i := 2; ; i++ {
12 ch <- i // Send 'i' to channel 'ch'. 13 } 14 }


Et ici une version plus élaborée:

10 func generate() chan int {
11 ch := make(chan int);
12 go func(){
13 for i := 2; ; i++ {
14 ch <- i 15 } 16 }(); 17 return ch; 18 }

En Erlang , le programme occupe plus de ligne. Il est de bonnes pratiques de scinder les programmes en composants de supervision et composants de traitement. J'ai aussi réalisé deux versions de la même fonction.
  • generator_async/3 : Cette fonction envoie en flot continu la série de nombre.
  • generator_sync/3 : Cette version n'envoie un nombre que sur demande du superviseur

Le superviseur lance le processus 'generateur' et va communiquer avec lui par un canal , comme en GO. En Erlang ou en Haskell ,les boucles for,while n'existent pas vraiment elles sont remplacées par des appels récursifs.


Le module principal superviseur:

-module (crible).
-export ([main/0,main2/0]).
loop2(Pid) ->
receive
ok -> ok;
Number -> io:format(" ~w~n",[Number]),
Pid ! next,
loop2(Pid)
end.
loop() ->
receive
ok -> ok;
Number -> io:format(" ~w~n",[Number]),
loop()

end.




main()->
_Pid =spawn(prime,generator_async,[self(),0,60000]),
loop(),
ok.
main2()->
Pid =spawn(prime,generator_sync,[self(),0,60000]),
Pid ! next ,
loop2(Pid).


Le module qui génère la suite des nombres:


-module (prime).
-export ([generator_async/3,generator_sync/3]).

generator_async(Canal,Compteur,Maximum) when Compteur == Maximum -> Canal ! ok;
generator_async(Canal,Compteur,Maximum) ->
Cpt= Compteur +1,
Canal ! Cpt,
generator_async(Canal,Cpt,Maximum).

generator_sync(Canal,Compteur,Compteur) -> Canal ! ok;
generator_sync(Canal,Compteur,Maximum) ->
Cpt= Compteur +1,
receive
next -> Canal ! Cpt ,
generator_sync(Canal,Compteur+1,Maximum)
end




J'ai utilisé ici une 'garde' dans la déclaration de fonction


generator_async(Canal,Compteur,Maximum) when Compteur == Maximum -> Canal ! ok;


C'est une condition de reconnaissance de la fonction.

Cette variante fait la même chose :

generator_sync(Canal,Compteur,Compteur) -> Canal ! ok;


Ici la variable Compteur est branchée avec le deuxième parametre d'appel de la fonction. Puis une autrre affectation de la variable Compteur est tentée avec le 3eme parametre. Si les deux valeurs sont égales le motif sera reconnu, sinon on passe à la forme d'appel suivante.

Ce système est basé sur le fait qu'il n'est pas possible de modifier le contenu d'une variable dans les langages fonctionnels.
ex : A=1 puis A=3 ou A=A+1

Pour debugger le programme en Erlang , il faut le compiler avec l'option :
erlc +debug_info

Puis lancer le shell Erlang (erl )

Sur le prompt lancer le debugger graphique par

debugger:start().


Choisir par le menu module, la liste des programmes à debugger.
Grace à ce système, il est possible de voir le contenu de messages ou l'état des variables.

Copie d'écran du debugger Erlang


Conclusion : La fonction qui utilise des echanges synchrones entre le superviseur et le composant générateur est 3 fois plus rapide que l'asynchrone.

Il est possible d'utiliser une seule ligne pour générer des séries de nombre par le système des listes "comprehensions". Ces listes injectent des données un peu à la manière de notre générateur.
Cela donnerait un ligne comme ca:

[ListePremier || Nombre <- Lists:seq(2,99999), is_prime_number(Nombre)].

Pour voir le post dans son contexte original http://germanlinux.blogspot.com/2009/11/crible-d-eratosthene-en-erlang-nombres.html

vendredi 6 novembre 2009

Projet SQUALE : mesurer la qualité du code


Toutes les entités qui développent du code sont confrontées à deux enjeux:

a) Planifier et respecter les délais de mise en œuvre des projets informatiques. Ce n'est pas rien , moins de 30% des projets arrivent à terme en respectant les 3 'C' : Contenu , calendrier, coût. Et plus de 25 % des projets sont purement et simplement abandonnés.

B) Développer du code de qualité. Les mentalités ont évoluées, et maintenant il est admis par tous qu'un code de bonne qualité est un des facteurs de réussite d'un projet.

Il existe des méthodes pour mesurer la qualité d'un code, encore faut il un tableau de bord permettant d'agréger les résultats. C'est le but du projet opensource 'SQUALE' (Software QUALity Enhanceme) .
Le portail squale permet de mesurer 6 facteurs :
  • capacité fonctionnelle
  • architecture
  • évolutivité
  • maintenabilité
  • réutilisabilité
  • fiabilité



Avec un niveau de détail très fin :






Le projet squale utilise trois composants: Une base de données pour stocker les informations collectées. Un serveur web pour le portail et enfin une série d'utilitaires (squalix)
pour mesures la qualité du code.








































Le projet propose des modèles définissant la notion de qualité du code ((ISO-9126,GQM, McCall) Mais il est possible d'enrichir le produit avec des modules tiers . Squale supporte nativement le JAVA mais peut traiter aussi les langages COBOL , C, PHP, .NET.
Squale est avant tout une plateforme d'intégration où viennent se brancher les modules tiers à partir du moment où ils respectent le modèle de données du produit.

Enfin squale met à disposition des fonctions d'audit de code avec notamment la possibilité de suivre dans le temps l'évolution des résultats d'audit.

En conclusion : pourvu qu'il ne fouille pas dans mon code..

vendredi 30 octobre 2009

Rails: contourner un problème par l'utilisation de la méthode send.


Dans le cadre d'utilisation d'association de type 'belongs_to' avec clés étrangères absentes.


Comment par simple baquette magique remplacer une dizaine de blocs identiques par un petit bloc de 4 lignes ?














Voici l'exposé du problème :j'ai une table principale Projet qui utilise plusieurs clés étrangères pour afficher des libellés .

class Projet < ActiveRecord::Base
belongs_to :moe
belongs_to :moa
belongs_to :domaine
belongs_to :techno
belongs_to :filiere
belongs_to :didev
belongs_to :diprod


Parfois, la clé étrangère n'est pas renseignée et cela provoque une erreur dans l'affichage de l'objet principal. Ce cas arrive pour ma part, principalement dans deux situations:


  • En phase de développement: je n'ai pas encore finalisé les écrans permettant de rattacher la table principale avec ses tables associées (à faire sous forme de liste déroulantes)
  • Par choix fonctionnel, la valeur ne doit etre servie. Dans ce cas, il est toujours possible d'ajouter une entrée factice dans la table (non satisfaisant)
La solution 'brute' consiste à tester avant d'afficher la validité de la clé étrangère , et de répéter ce test tout le long de la vue.
Dans l'illustration suivante, je montre comment factoriser son code :
(cliquez sur l'image pour agrandir)


L'astuce consiste à remplacer l'appel d'une méthode par l'envoi d'un message à la methode 'send' de l'objet.

Dans cet exemple, j'appelle une fonction avec trois paramètres:
L'objet (projet)
Le nom de la classe decrivant les libellés (nom de la table au singulier)
L'attribut à afficher
Je procède à un appel imbriqué de méthode.





Ces trois formes d'appel produisent le même résultat :
  • mon_projet.methode
  • mon_projet.send('methode')
  • mon_projet.send(:methode)
Dans le cas présent, en raison de l'utilisation d'une clé étrangère je suis obligé de passer par une syntaxe imbriquée:
mon_projet.send('objet_libelle').send('attribut_a_afficher')

Et en bonus, comment afficher une liste déroulante à partir d'un table libellé ?

Par une simple ligne :
<%= select(:projet, "domaine_id", Domaine.find(:all).collect {|p| [ p.libelle, p.id ] }, :include_blank => true) %>

Good hacking!

mercredi 28 octobre 2009

Les modèles gros contre les maigres


Le titre est racoleur comme cette illustration que j'ai volontairement floutée.
(L'originale est disponible sur google image)

Rails est un framework MVC : modele/view/controleur

La philosophie de Rails est aussi dans la re-factorisation du code, de manière à éviter d'avoir des gros contrôleurs. Ce défaut est source de toutes les difficultés : maintenance , réutilisation du code et évolution de l'application.


J'illustre mon propos par un exemple de projet qui gère un portefeuille applicatif. Ces applications sont de différentes technologies ,et on doit pouvoir filtre les applications sur leur type de technologie :









Dans une première version , jamais mis en dur dans le contrôleur les options de filtre possible.

Après modifications , j'arrive à :
Un modèle plus 'gros':


Ce modèle contient toute la logique de sélection (Select SQL)
Il ne faut pas hésiter à faire des méthodes 'find' taillées sur mesure.











Le contrôleur:


Le contrôleur est allégé pour ne contenir que la partie 'métier' du traitement. Dans cette solution , non seulement les tests 'en dur' ont disparus mais en plus l'ajout d'une nouvelle catégorie ne nécessitera aucune modification de code.








La vue est elle aussi simplifiée:

D'une manière générale, il faut éviter de mettre trop de traitement dans les vues. Cela rend l'application, très difficile à maintenir et le code inséré dans les vues est assez contraignant à écrire.












Où se trouve alors tout le traitement qui génère l'affichage de la console de bouton radio ? . Car malheureusement, il faut bien qu'a un moment donné une méthode prenne en charge :
a) Afficher toutes les options
b) Pré-selection de l'option 'cochée'.
Cette méthode va etre placée dans les 'helpers' de l'application qui prendra cette forme:


Je n'ai pas forcement le bon style d'écriture du code. Ici on fabrique le HTML utile pour les boutons radio.
Cette méthode n'est possible que parce ma liste des options était contenue dans une table.






En résumé : toujours re-factoriser son code : DRY : don't Repeat Yourself ou Duplication is Evil . Dans mon exemple la logique de la gestion des options est dans le helper et que dans lui. Le resultat donne un système qui evoluera sans modification à apporter au code.
En conclusion je me pose la question suivante : Pourquoi doit on re-factoriser dans les langages proceduraux et ne pas le faire dans les langages fonctionnels ?.