Rework, sans rien changer...
Après avoir refermé ce nouveau bouquin de chez 37Signals, je suis un peu déçu. Rework n'est, de mon point de vue, qu'une version amélioré de Getting Real. C'étais peut-être le but, mais du coup, je n'ai rien appris de nouveau.

Beaucoup de chose relève du bon sens et sont courament faite dans quelques sociétés. D'autres sont moins évidente, et on voit peu d'entreprise les mettre en place. Je pense notamment au fait de rester petit. Je vois trop de personnes pour qui la taille d'une boite indique une certaine puissance, notoriété ou encore tranquillité...
Il y a par contre quelque choses avec lequel je ne suis pas d'accord: 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 c'est pourtant bien de proner le travail à domicile... mais je préfère pouvoir discuter tout de suite avec quelqu'un quand j'ai 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 j'aime à 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 (c'est d'ailleur dit dans un des premiers chapitres) restez vous même !
Appel de WebServices Soap en Ruby

Soap, on aime ou on aime pas. Je pense que Soap sur HTTP, c'est dommage, autant utiliser le protocole http correctement et proposer des services web en RESTful. Comme je l'ai lu quelque part, c'est comme "mettre une enveloppe dans une enveloppe". Toujours est-il que ça a quand même le mérite d'exister. Et nous nous sommes retrouvé à devoir faire appel à un webservice SOAP en ruby, j'aimerais vous faire part de la façon dont on a réalisé cela.
Après avoir jeté un coup d'oeil à soap4r nous avons voulu regarder ce qui existait déjà, et là, surprise, soap4r est intégré à la librairie standard de Ruby avec une base très riche pour l'utilisation de Soap et quelques outils bien pratique pour l'utilisation des fichiers WSDL.
Du coup, il ne reste plus qu'a générer les classes qui s'occuperont de l'appel "soap" à l'aide de l'objet WSDL2Ruby.
Pour cette génération, nous avons repris un script wsdl2ruby.rb trouvé dans les repertoires du Trac du projet soap4r (qui date un peu). En gros il ajoute quelque explication sur l'utilisation de la ligne de commande permettant de générer les classes Soap, et permet d'enchainer l'envoie 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: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
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 d'option 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 s'occuper de la connexion au service, et défini les methodes que l'on 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 à l'appel, et un pour la réponse. Bien sur, avant d'inté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é.
require 'default.rb' require 'soap/rpc/driver' class Authentification < ::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 => :document, :request_use => :literal, :response_style => :document, :response_use => :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 endLe fichier généré default.rb
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
Du coup, il ne reste plus qu'a créer un nouvelle objet proxy (qui porte le nom du service et que l'on retrouve dans le fichierdefaultDriver.rb), puis d'envoyer les messages qui vont bien avec les paramètres.
require 'defaultDriver' auth_proxy = Authentification.new response = auth_proxy.authentification(:login => 'james', :pwd => 'bond') puts response.result
Au final, ça fonctionne plutôt bien et c'est en peut de temps que l'on a pu mettre en place cet appel. Soap est un protocole de communication verbeux, mais il a l'avantage 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 l'utilisation d'un service rest mais il faudrais dans ce cas que les autres technologie soit capable de l'utiliser, et pour certaine techno un peu vieillissante, c'est pas facile (de plus reprendre le code existant a un coût).
Je n'aime pas non plus le code généré pour plusieurs raison dont le manque de test. On sent aussi qu'avec les capacités dynamique de Ruby on pourrais ne pas générer du code, mais construire à la volé les appels au service soap.
Git ou Mercurial lequel choisir ? Les deux mon général !

Voici le nième billet que l'on peut trouver sur Git et Mercurial.
On pourrais énumérer les différences entre les deux pour pouvoir choisir, mais Why Git Is Better Than X le fait assez bien (quoique, on peut douter de l'impartialité ;-)).
On pourrais aussi choisir mercurial pour l'executable 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 un utilisateur de mercurial pourra partager avec des utilisateurs de Git. Je en suis pas sur que l'inverse existe.
Un autre point me dit que finalement on peut très bien ce servir des deux dans un même projet. C'est une discussion dans un TGV de retour de Strasbourg et le billet MercurialSquashCommit de Martin Fowler qui eveil ma curiosité. J'ai l'impression que travailler par patch permet également d'utiliser n'importe 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 voir git-format-patch permet une gestion très interessante des patchs. Mercurial a également une gestion interessante par le biais de l'extension MQ.
Mais j'ai besoin de faire quelque essais avant d'être persuadé (pour l'un et/ou l'autre). Promis, je vous en reparle quand c'est fait.
Alors utiliser, Git, Mercurial ou un autre, peut importe tant que l'équipe arrive à trouver un rythme et un processus qui lui convient ;-)

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 d'aller faire un tour sur Okami.


Monique expose jusqu'à fin mars quelques peintures chez Yin, un restaurant que Cyril nous recommande.
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: l'ergonomie 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 d'utilisateurs. Dans mon cas, c'est 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 qu'on 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 l'on utilise nous impose un peu leur vision des choses, et quand c'est bien fait, c'est 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 l'utilisation d'une 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... C'est bon, on a compris qu'on travail en informatique de gestion ! Ca m'énerve !
Et quand on pose la question: "c'est quoi la gestion d'un véhicule" ? Et bien, on a souvent la réponse suivante: "un véhicule à un nom, une immatriculation, une marque (qu'on 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 n'y a que le calendrier éventuellement que l'on va gérer autrement...
Et on arrive à quelque chose de ce genre:

Y'a 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 c'est 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 l'interêt de ce genre d'application ? Où est le plus qui fait la différence. Non parce que sinon, y'a moyen de faire de beau trigger de base, et d'utiliser un outil de query comme Squirrel-SQL ou autre pour aller taper dedans. On pourrais même imaginer faire quelques scripts sql à l'avance pour faciliter la vie des utilisateurs. Très honnêtement, je pense que l'on 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 s'exclu pas d'ailleurs):
- NoSQL (not only SQL) ou le grand mouvement des bases non relationnelle
Dur d'être passer à coté de ce genre d'article ces dernier temps. J'avoue ne pas avoir encore manipulé dans le cas d'une application concrete ce genre de base, mais juste fait quelques exploration. Cela me fait penser aux bases de donnée objet raté d'il y a quelque année. Enfin système de stockage d'objet 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 j'ai l'impression que ça pourrais nous faire revenir à l'essentiel: la fonction d'un logiciel. Et non la structure des données (qui semble être le point le plus important aujourd'hui, malheureusement). Mais c'est un sujet un peu trop neuf pour moi pour l'instant. Si vous voulez en savoir plus, je ne peut que vous conseiller l'article wikipedia sur le Domain Driven Designpour commencer (la version française manque d'ailleurs de richesse :p): puis le site de la communauté ddd.
Je ne sais pas trop a quoi ressemblerons nos appli de demain, mais j'espère que celles que l'on voit dans les entreprises seront plus sympa à utiliser !