mise à jour

This commit is contained in:
Yannick Francois
2020-02-17 17:03:01 +01:00
parent 952f8b99d9
commit 10796b4e52
368 changed files with 7782 additions and 0 deletions
@@ -0,0 +1,45 @@
---
layout: post
title: Marre du liste fiche de l'informatique de gestion
---
*Il y a quelque chose qui commence à être lourd dans les développements logiciel auquel je participe: lergonomie idiote. Je me demande comment enrayer cela. Voici une image du problème que je rencontre si souvent*.
En général, on écrit un logiciel pour faciliter la vie dutilisateurs. Dans mon cas, cest souvent des utilisateurs interne (je travail en *informatique de gestion*). Il y a déjà là une petite piste de reflexion: **pourquoi je traite des utilisateurs interne différement du grand public (ou utilisateur externe) ?**
Peut-être parce quon ne peut pas *imposer* une manière de travailler à monsieur tout-le-monde. Mais finalement, quand on y pense un peu, les divers services que lon utilise nous impose un peu leur vision des choses, et quand cest bien fait, cest un service qui marche, parce que la façon dont sont proposé les fonctionnalitées nous convient. Sinon, le produit disparait.
Pourquoi ne pourrait-on pas imaginer la même chose en interne ? **Pourquoi ne pas forcer lutilisation dune application par son ergonomie, son design, ses fonctionnalitées ?**
Ensuite, au moment d’écrire le logiciel, on se retrouve souvent à faire un découpage. Souvent par grand domaine: gestion utilisateur, gestion vehicule, gestion tarif, gestion calendrier... gestion, gestion... Cest bon, on a compris quon travail en informatique de gestion ! Ca m’énerve !
Et quand on pose la question: **"cest quoi la gestion dun véhicule" ?** Et bien, on a souvent la réponse suivante: "un véhicule à un nom, une immatriculation, une marque (quon va gérer dans une table à part), un type (lien dans une table à part), un prix de location (il faudra boucler avec la gestion des tarifs et des plannings), et une date de mise en service". Super, **on parle de schéma de base de donnée (relationnel) sans avoir aborder les fonctionnalitées**...
Mais creusons un peu.
"au niveau fonctionnalité, on fait quoi réèllement ?" et voilà la réponse qui tue: "on fait une tableau avec des critères de recherche/filtre, si possible avec des colonnes triable, et puis un formulaire pour la création et la mise à jour". Génial !.
Pour les autres fonctionnalitées: reprendre le paragraphe précédent et remplacer “véhicule" et quelques champs par le nouveau domaine à étudier (utilisateur, tarif). Il ny a que le calendrier éventuellement que lon va gérer autrement...
Et on arrive à quelque chose de ce genre:
![Limmonde architecture n-tier de lappli de gestion](/files/ergo.jpg)
Ya un truc qui cloche (outre le fait que je vais devoir apprendre a dessiner sur un ordinateur).
Habitué des bases de données relationnel, on se rend compte que cest juste une **image des données**, avec un quelque règles métier placé entre les deux, plutôt que de les mettre sous forme de trigger de base.
Je me demande quel est linterêt de ce genre dapplication ? Où est le plus qui fait la différence. Non parce que sinon, ya moyen de faire **de beau trigger de base**, et d**utiliser un outil de query comme [Squirrel-SQL](http://squirrel-sql.sourceforge.net/)** ou autre pour aller taper dedans. On pourrais même imaginer faire **quelques scripts sql à lavance** pour faciliter la vie des utilisateurs. Très honnêtement, je pense que lon irait plus vite en proposant cela, et **l’équipe apporterais tout autant de valeur au produit** (peut-être même plus) !
Comment faire pour empecher cela ? Comment changer les mentalités d’équipe entierement contaminé ? Je vois de mon angle de vue 2 pistes (qui ne sexclu pas dailleurs):
* NoSQL (not only SQL) ou le grand mouvement des bases non relationnelle
Dur d’être passer à coté de ce genre darticle ces dernier temps. Javoue ne pas avoir encore manipulé dans le cas dune application concrete ce genre de base, mais juste fait quelques exploration. Cela me fait penser aux bases de donnée objet raté dil y a quelque année. Enfin système de stockage dobjet voit le jour. Simple et semble-t-il efficace. Voilà peut-être un morceau de la solution pour arreter de penser les écrans sous forme de table de base de donnée relationnel.
* DDD (Domain Driven Design) approche du développement logiciel
Peut-être un peu plus confidentiel (surtout auprès des développeur français que je connais ?) mais jai limpression que ça pourrais nous faire revenir à lessentiel: la fonction dun logiciel. Et non la structure des données (qui semble être le point le plus important aujourdhui, malheureusement). Mais cest un sujet un peu trop neuf pour moi pour linstant. Si vous voulez en savoir plus, je ne peut que vous conseiller l[article wikipedia sur le Domain Driven Design](http://en.wikipedia.org/wiki/Domain-driven_design)pour commencer (la version française manque dailleurs de richesse :p): puis le [site de la communauté ddd](http://domaindrivendesign.org/).
Je ne sais pas trop a quoi ressemblerons nos appli de demain, mais jespère que celles que lon voit dans les entreprises seront plus sympa à utiliser !
@@ -0,0 +1,21 @@
---
layout: post
title: "OKAMI design: expo peinture"
---
Rien à voir avec les pieds dans le code directement: je me permet un peu de pub pour Cyrou, un ami de longue date et Monique, une artiste/designeuse.
Si vous aimez les japonaiserie je vous conseil daller faire un tour sur [Okami](http://okami.fr/).
![Les peintures rondes de Monique- Okami design](http://elsif.fr/files/painting_round.jpg)
![Un tigre de Cyrou- Okami design](http://elsif.fr/files/dessin_cyrou_tigre.jpg)
[Monique expose jusqu’à fin mars quelques peintures chez Yin](http://okami.fr/blog/fr/expo-de-peintures/), un restaurant que Cyril nous recommande.
@@ -0,0 +1,33 @@
---
layout: post
title: Git ou Mercurial lequel choisir ? Les deux mon général !
---
![Git Logo](http://elsif.fr/files/git-logo.png)
Voici le nième billet que lon peut trouver sur [Git](http://git-scm.com/) et [Mercurial](http://mercurial.selenic.com/).
On pourrais énumérer les différences entre les deux pour pouvoir choisir, mais [Why Git Is Better Than X](http://whygitisbetterthanx.com/) le fait assez bien (quoique, on peut douter de limpartialité ;-)).
On pourrais aussi choisir mercurial pour lexecutable en deux lettres (`hg`) au lieu de git qui en contient trois (`git`)...
Un petit plus pour Mercurial, en tant que client en tout cas. effectivement, grace à ce plugin [hg-git](http://hg-git.github.com/) un utilisateur de mercurial pourra partager avec des utilisateurs de Git. Je en suis pas sur que linverse existe.
Un autre point me dit que finalement on peut très bien ce servir des deux dans un même projet. Cest une discussion dans un TGV de retour de Strasbourg et le billet [MercurialSquashCommit de Martin Fowler](http://www.martinfowler.com/bliki/MercurialSquashCommit.html) qui eveil ma curiosité. Jai limpression que travailler par patch permet également dutiliser nimporte quelle DVCS, à condition bien sur que celui-ci propose une création de patch facilité. Il me semble que Git propose avec la commande [git-diff](http://www.ru.kernel.org/pub/software/scm/git/docs/git-diff.html) voir [git-format-patch](http://www.kernel.org/pub/software/scm/git/docs/git-format-patch.html) permet une gestion très interessante des patchs. Mercurial a également une gestion interessante par le biais de l[extension MQ](http://mercurial.selenic.com/wiki/MqExtension).
Mais jai besoin de faire quelque essais avant d’être persuadé (pour lun et/ou lautre). Promis, je vous en reparle quand cest fait.
Alors utiliser, Git, Mercurial ou un autre, peut importe tant que l’équipe arrive à trouver un rythme et un processus qui lui convient ;-)
![Mercurial Logo](http://elsif.fr/files/mercurial-logo1.png)
@@ -0,0 +1,152 @@
---
layout: post
title: Appel de WebServices Soap en Ruby
---
![Ruby Soap](http://elsif.fr/files/soap.jpg)
[Soap](http://fr.wikipedia.org/wiki/SOAP), on aime ou on aime pas. Je pense que Soap sur [HTTP](http://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol), cest dommage, autant utiliser le protocole http correctement et proposer des services web en [RESTful](http://fr.wikipedia.org/wiki/Representational_State_Transfer) . Comme je lai lu quelque part, cest comme “mettre une enveloppe dans une enveloppe”. Toujours est-il que ça a quand même le mérite dexister . Et nous nous sommes retrouvé à devoir faire appel à un webservice SOAP en ruby, jaimerais vous faire part de la façon dont on a réalisé cela.
Après avoir jeté un coup doeil à [soap4r](http://dev.ctor.org/soap4r) nous avons voulu regarder ce qui existait déjà, et là, surprise, soap4r est intégré à la [librairie standard de Ruby](http://ruby-doc.org/stdlib/) avec une base très riche pour lutilisation de [Soap](http://ruby-doc.org/stdlib/libdoc/soap/rdoc/index.html) et quelques outils bien pratique pour lutilisation des fichiers [WSDL](http://ruby-doc.org/stdlib/libdoc/wsdl/rdoc/index.html).
Du coup, il ne reste plus qua générer les classes qui soccuperont de lappel “soap” à laide de lobjet [WSDL2Ruby](http://ruby-doc.org/stdlib/libdoc/wsdl/rdoc/classes/WSDL/SOAP/WSDL2Ruby.html).
Pour cette génération, nous avons repris un script [wsdl2ruby.rb](http://dev.ctor.org/soap4r/browser/trunk/bin/wsdl2ruby.rb) trouvé dans les repertoires du Trac du projet soap4r (qui date un peu). En gros il ajoute quelque explication sur lutilisation de la ligne de commande permettant de générer les classes Soap, et permet denchainer lenvoie du message `run` après avoir mis en place la `location` et placé quelque options bien choisi.
### Voici *LA* méthode principale du `wsdl2ruby.rb`:
<pre>
{% highlight ruby %}
def run
@worker = WSDL::SOAP::WSDL2Ruby.new
@worker.logger = @log
location, opt = parse_opt(GetoptLong.new(*OptSet))
usage_exit unless location
@worker.location = location
if opt['quiet']
self.level = Logger::FATAL
else
self.level = Logger::INFO
end
@worker.opt.update(opt)
@worker.run
0
end
{% endhighlight %}
</pre>
En executant donc cette commande `wsdl2ruby.rb --wsdl '[l'adresse du fichier wsdl de mon service soap
qui tue]' --type client`
Il existe pas mal doption pour créer un webservice, mais ici nous voulions créer un client pour appeler un webservice soap existant.
Cette commande nous a donc générer deux fichiers: `default.rb` et `defaultDriver.rb`. Ce dernier soccuper de la connexion au service, et défini les methodes que lon peut utiliser ainsi que les paramètres qui vont bien avec. Le fichier `default` contient lui un objet par methode du service. Dans notre cas, nous avion un objet qui correspond à lappel, et un pour la réponse. Bien sur, avant dintégrer ce code généré, il faudrais faire un petit renomage, mais ça vous savez faire.
Notre service permet
### Le defaultDriver.rb généré.
<pre>
{% highlight ruby %}
require 'default.rb'
require 'soap/rpc/driver'
class Authentification &lt; ::SOAP::RPC::Driver
DefaultEndpointUrl = "http://example.com:8080/axis/services/authentification"
MappingRegistry = ::SOAP::Mapping::Registry.new
Methods = [
[ "",
"authentification",
[ ["in", "parameters", ["::SOAP::SOAPElement", "http://auth.example.com/", "authentification"], true],
["out", "parameters", ["::SOAP::SOAPElement", "http://auth.example.com/", "response"], true] ],
{ :request_style =&gt; :document, :request_use =&gt; :literal, :response_style =&gt; :document, :response_use =&gt; :literal }
]
]
def initialize(endpoint_url = nil)
endpoint_url ||= DefaultEndpointUrl
super(endpoint_url, nil)
self.mapping_registry = MappingRegistry
init_methods
end
private
def init_methods
Methods.each do |definitions|
opt = definitions.last
if opt[:request_style] == :document
add_document_operation(*definitions)
else
add_rpc_operation(*definitions)
qname = definitions[0]
name = definitions[2]
if qname.name != name and qname.name.capitalize == name.capitalize
::SOAP::Mapping.define_singleton_method(self, qname.name) do |*arg|
__send__(name, *arg)
end
end
end
end
end
end
{% endhighlight %}
</pre>
### Le fichier généré default.rb
<pre>
{% highlight ruby %}
require 'xsd/qname'
class Authentification
@@schema_type = "authentification"
@@schema_ns = "http://auth.example.com"
@@schema_qualified = "true"
@@schema_element = [["login", "SOAP::SOAPString"], ["pwd", "SOAP::SOAPString"]]
attr_accessor :login
attr_accessor :pwd
def initialize(login = nil, pwd = nil)
@login = login
@pwd = pwd
end
end
class Response
@@schema_type = "response"
@@schema_ns = "http://auth.example.com/"
@@schema_qualified = "true"
@@schema_element = [["result", "SOAP::SOAPString"]]
attr_accessor :result
def initialize(result = nil)
@result = result
end
end
{% endhighlight %}
</pre>
Du coup, il ne reste plus qua créer un nouvelle objet proxy (qui porte le nom du service et que lon retrouve dans le fichier `defaultDriver.rb`), puis denvoyer les messages qui vont bien avec les paramètres.
<pre>
{% highlight ruby %}
require 'defaultDriver'
auth_proxy = Authentification.new
response = auth_proxy.authentification(:login =&gt; 'james', :pwd =&gt; 'bond')
puts response.result
{% endhighlight %}
</pre>
Au final, ça fonctionne plutôt bien et cest en peut de temps que lon a pu mettre en place cet appel. Soap est un protocole de communication verbeux, mais il a lavantage d’être très bien intégré dans les divers langages et framework, et, dans notre cas, nous avons plusieurs technologie qui utilise ce service. On préfèrerais bien sur voir ici lutilisation dun service [rest](http://fr.wikipedia.org/wiki/Representational_State_Transfer) mais il faudrais dans ce cas que les autres technologie soit capable de lutiliser, et pour certaine techno un peu vieillissante, cest pas facile (de plus reprendre le code existant a un coût).
Je naime pas non plus le code généré pour plusieurs raison dont le manque de test. On sent aussi quavec les capacités dynamique de [Ruby](http://www.ruby-lang.org/) on pourrais ne pas générer du code, mais construire *à la volé* les appels au service soap.
@@ -0,0 +1,21 @@
---
layout: post
title: Rework, sans rien changer...
---
Après avoir refermé ce nouveau bouquin de chez [37Signals](http://37signals.com/), je suis un peu déçu. [Rework](http://37signals.com/rework/) nest, de mon point de vue, quune version amélioré de [Getting Real](http://gettingreal.37signals.com/). C’était peut-être le but, mais du coup, je nai rien appris de nouveau.
![Rework](/files/front-cover.png)
Beaucoup de chose relève du bon sens et sont courament faite dans quelques sociétés. Dautres sont moins évidente, et on voit peu dentreprise les mettre en place. Je pense notamment au fait de rester *petit*. Je vois trop de personnes pour qui la taille dune boite indique une certaine puissance, notoriété ou encore tranquillité...
Il y a par contre quelque choses avec lequel je ne suis pas daccord: le fait de travailler à domicile, avec une équipe réparti. Je pense: pour pouvoir recruter les meilleurs des meilleurs il faut accepter de recruter à travers la planête. Pour moi, le fait de travailler en équipe, dans une même pièce est beaucoup plus efficace et important que de travailler avec la crème de la crème mondiale. Mon coté vert me dit que cest pourtant bien de proner le travail à domicile... mais je préfère pouvoir discuter tout de suite avec quelquun quand jai besoin de le faire, et surtout voir quand son visage ce tord de douleur sur un bout de code, pour pouvoir lui venir en aide. Et jaime à penser que les défaut de chaque membre de l’équipe servent a rendre l’équipe plus forte.
En gros, lisez Rework plutôt que Getting Real si vous devez en choisir un. Et surtout (cest dailleur dit dans un des premiers chapitres) restez vous même !