Thursday, October 3, 2013

Les architectures applicatives client/serveur

Avec l'avènement des applications smartphones ainsi que celles exécutées sur le navigateur, nos applications n'ont jamais autant changé en un laps de temps aussi réduit. Les frontières entre client et serveur sont de plus en plus floues.

Dans ce contexte, je vais tenter de retracer les différentes étapes qui ont amené aux évolutions de nos applications et tenter d'entrevoir ce qu'elles pourraient dans un futur proche.

Etats des lieux

Les clients lourds


Je me souviens au début de ma carrière, ils y avaient des applications dites lourdes qui étaient déployées chez les clients.


Ces applications fonctionnent de cette manière:

Un client dit lourd sur chaque poste utilisateur qui envoie des requêtes en mode connecté sur un serveur centralisé effectuant des traitements de type appel à la bdd, connexion avec le mainframe maison etc.


Ces applications ont l'avantage de fonctionner de la même manière sur chaque client pour peu que la configuration soit identique sur chaque poste. Mais ont l'inconvénient d'avoir une lourdeur dans les déploiements de l'application qui doivent se faire sur chaque poste de chaque employé sans parler des mises à jours qui doivent se faire de la même manière.
Au niveau développement la grande majorité du code métier est géré sur le client.

Suite à la pénibilité de ce fonctionnement, de nouvelles approches de déploiement à partir du serveur apparurent.

Les clients lourds via déploiement à partir du serveur

Ici le client lourd est déployé via une interface web sur chaque poste client.

Il suffit à l'utilisateur d'aller sur une page web afin que le serveur déploie via une applet/un activeX l'application sur le poste de l'utilisateur.
Le déploiement est alors moins pénible au sein de l'entreprise.
  
Mais voilà, en parallèle les technologies web ont évolué, il est alors possible d'obtenir une application avec des fonctionnalités similaires à nos chers clients lourds. Ceci a favorisé l'abandon des applications lourdes au profit de clients légers.

Les clients légers



Un client dit léger est en fait un navigateur web capable d'interpréter des descriptions html servies par un serveur web.


La différence entre le client lourd et le client léger se situe dans le fait que le client léger a une attitude passive, c'est à dire qu'il ne s'occupe que du rendu de ce qui lui est décrit via le html envoyé par le serveur.


Bien que cette approche supprime les contraintes liées au déploiement des clients sur les postes utilisateurs, elle a aussi ses inconvénients:


  • La réactivité du client léger est de très loin derrière la réactivité d'un client lourd notamment du au manque d'un langage dynamique côté client. L'utilisateur doit effectuer une nouvelle requête pour avoir accès à une nouvelle information du serveur et attendre le rafraîchissement de la page.
  • La compatibilité entre chaque navigateur n'est pas toujours assurée, il se peut que le rendu diffère selon le navigateur
  • Le rendu ne permet pas d'avoir un contenu riche, c'est à dire des interfaces graphiques semblables à celles des clients lourds qui intègre une multitude de composants.

Les clients légers avec JS


Pour pallier au manque de réactivité, les éditeurs ont inclus le langage javascript créé par netscape (RIP) dans leurs navigateurs respectifs. Ce langage a la particularité d'être simple à implémenter comparé aux langages que l'on rencontre sur nos clients lourds tels que C/C++ ou JAVA. Ceci a permis d'avoir des interactions dynamiques plus facilement au sein du navigateur.

La compatibilité a aussi été améliorée au fil du temps notamment par l'établissement d'un consortium W3C dédié aux fonctionnalités des navigateurs regroupant la plupart des éditeurs des navigateurs.

En ce qui concerne la richesse du client il a fallu attendre l'arrivée de la vague des clients riches et du HTML 5.

 Les clients riches (Flex (RIP), Silverlight, JavaFX (RIP))




Comme le javascript, le client riche s'éxécute au sein du navigateur web, mais à une différence prête que le rendu n'est pas effectué par le navigateur mais par un éxécutable préalablement installé sur le poste client.  Les clients riches ont la particularité de proposer des composants grahiques qui n'ont rien à envier à nos vieux clients lourds. Ces clients se reposent sur des langages relativement simples.


L'inconvénient est qu'il faille préalablement installer un plugin sur le navigateur (le fameux éxécutable) ce qui ne satisfait pas toutes les sociétés et aussi le fait que l'accessibilité soit difficilement prise en compte par ces clients.

HTML 5 et AJAX




En parallèle des clients riches, arrivèrent le HTML 5 qui améliore grandement les capacités du navigateur avec la possibilité par exemple de fournir du multimédia, stocker des données en base de données sur le navigateur et d'obtenir des connexions persistantes via WebSocket avec le serveur. Ces connexions persistantes permettent de pallier à la problématique de connexions successives faites par les navigateurs, comme le faisait déjà nos clients lourds.





De plus, la présence d'api AJAX simplifiées permet de créer des fortes interactions avec le serveur et ce de manière dynamique réduisant la contrainte d'effectuer des rafraîchissements du navigateur  ainsi que l''intégration du code de communication avec le serveur qui est pré-mâché par les API  javascript telles que JQuery, Prototype, Scriptaculous...


Il est alors possible d'avoir des rendus similaires aux clients riches, sans toutefois devoir installer un plugin sur les postes client.

Ceci a bien évidemment contribué au déclin des clients riches.

Les tendances actuelles

RestFul



L'approche RestFull sans rentrer dans le détail, permet d'associer une ressource à une uri. C'est à dire celà se traduit souvent par créer une url par ressource. Le grand intérêt est d'avoir une approche stateless (sans état) qui améliore la scalabilité des serveurs et délègue les états applicatifs sur le client.

Le tout JS

Avec l'arrivée de nouveaux frameworks JavaScript orientés Single Page Application (applications dans la même page) facilitant le développement de la navigation côté client, il est possible de créer une grosse partie de la logique de navigation en JS, le serveur n'a alors qu'un rôle de mise à disposition des données dans un format simple pour le Javascript (souvent en JSON) via une approche RestFul

Les applications mobiles



Les applications mobiles sont à leur manière des clients riches puisqu'ils reprennent point par point ce qui a fait leur succès. 


Ces applications tournent sur des terminaux de plus en plus puissant, ce qui présage un enrichissement continue des fonctionnalités présentes dans nos applications.

En voyant toutes ces évolutions on peut se demander quelles seront les architectures de demain.

Et si demain ...


Des applications conçues pour des périphériques hétérogènes


A l'instar du smartphone qui a révolutionné l'usage de nos applications, on peut se dire que d'autres périphériques connectés vont voir le jour. Cette tendance commence déjà avec par exemple les lunettes ou bien les montres connectées.

Ces nouveaux périphériques posent plusieurs questions dans le cadre du développement de nos applications:

Pourra t'on toujours développer des applications très riches sur des périphériques exotiques et limités ?

Comment les applications des différents périphériques vont elle dialoguer ?
Où seront stocker les données ? Dans le Cloud ? Sur les périphériques ?

On peut imaginer trois types d'approche:

  • Tous ces nouveaux périphériques seront connectés au web et les données seront présentes chez les géants du web (google, microsoft, amazon etc.)

Les lunettes, le téléphone portable et la montre connectés à internet avec les données dans le cloud

  • Les périphériques seront interconnectés, les données dispersées, avec certains périphériques connectés au web.

Les lunettes se connectent au téléphone et la montre aux lunettes etc. Avec certains se connectant à internet.

  • Un seul périphérique connecté au web faisant office de serveur centralisé responsable du traitement des données.

Les lunettes et la montre se connectent sur le téléphone qui lui se charge de traiter la donnée, soit en local, soit dans le cloud.

Ceci impactera inévitablement notre vision de ce qu'est un client et un serveur.

Retour vers des clients lourds pour le web

Ne sautez pas de votre chaise en voyant le titre du paragraphe, il est intentionnellement provocateur.

Néanmoins nos clients légers/riches ont de plus en plus de points communs avec nos clients lourds:

  • Une connexion persistante (WebSocket)
  • Appel à une base de donnée
  • Affichage de toute l'application dans une seule page web (single page application)
  • Contenu multimedia


La grande différence se situe essentiellement sur la responsabilité du code métier qui est aujourd'hui principalement effectuée côté serveur, mais avec la simplification de l'utilisation du JS, il pourrait être tentant d'utiliser ce langage pour faire du traitement métier.
Si ce cap est franchi alors nos clients légers redeviendront des clients lourds.

L'avenir nous dira si l'informatique peut être comparée à l'Histoire où nous assistons à des cycles perpétuels.


Un merci à Patrice Chalcol et Patrick Guillerm d'avoir participé à la relecture de l'article.






Thursday, April 4, 2013

Recettes de chiffrages de projet informatique

 Le chiffrage d'un projet en informatique se révèle souvent être une tâche ardue que ce soit dans la définition des besoins ou dans l'évaluation du temps de réalisation. Ceci a pour conséquence que le chiffrage se base souvent sur des paramètres assez subjectifs.

Dans cette idée, je me suis amusé à imaginer quelques techniques permettant de faire du chiffrage. Toutes ressemblances a des faits réels n'est que pure coïncidence ;).

Le compteligne

Cette technique prend en compte le nombre de ligne et la structure du document fournis par le client.

Etapes:
  1. Découper le projet à chiffrer en tâches très macros. Le découpage revient souvent à reprendre les paragraphes de l'expression de besoin du client c.a.d 1 tâche égale 1 paragraphe ou 1 chapitre.
  2. Prendre le nombre de ligne de chaque tâche et le multiplier par un autre coeff en fonction de ce que vous avez compris de la tâche à réaliser. Plus la tâche vous parait incompréhensible, plus le coeff doit augmenter.  
  3. Ainsi vous obtenez un certain nombre de jours/homme. 
  4. Adapter le chiffrage en fonction des remords suscités par ce dernier.


Exemple: Une expression de besoin faisant 3 chapitres

1er chapitre: 3 lignes
 Compréhension du chapitre: je n'ai rien compris => 3
2e chapitre: 5 lignes
Compréhension du chapitre: ca me paraît clair => 2
3e chapitre: 10 lignes
Compréhension du chapitre: J'ai tout compris =>1

Nombre de jour/homme = 3 x 3 + 5 x 2 + 10 x 1 = 29 jrs/homme
Nombre de jour/homme après remords = 24 jrs/homme

 Le comptemot (compteligne police proof)


Cette technique est une variante du compteligne mais a l'avantage de ne pas être sensible à la police. En effet le nombre de mot est pris en compte à la place du nombre de ligne.

Le mathétique


Cette technique est réservée aux psychopathes des mathématiques et aux fanas de préjugés.

Etapes:
  1. Découper méticuleusement chaque besoin afin d'en faire des tâches très micros de l'ordre d'1j/h.
  2. Avoir au préalable calculé la productivité de chacun de ses devs après une longue observation, en déduire des données en fonction de préjugés: Temps effectif devant le poste, temps passé à surfer sur le net, âge des développeurs, nombre de dev en couple, nombre de femmes etc. 
  3. Prendre le résultat de ces calculs et le corréler aux tâches à réaliser.
  4. Savourer le chiffrage obtenu avec un rire sadique.
Exemple:
Découpage du projet en 1101 micro-tâches d'1j/h. Dans l'équipe, il y a trois devs, deux hommes et 1 femme.
Un homme est marié, ce qui fait de lui un dev avec des obligations => 75 % de dev,
L'autre est célibataire à tendance nolife et à l'avantage d'être barbu => 120 % de dev,
La femme a un beau physique => 50% de dev car pour ce type de chifffreur, elle n'est qu'un demi développeur.

Résultat: 1101 * 125 / 100 * 80/100 * 150/100 = 1651.5 j/h
Résultat en prenant en compte les jours de maladies potentiels: 1651.5 * 110 % = 1816.65 j/h

Le coffreur


Cette technique est réservé aux chiffreurs codeurs et très simple à réaliser. A adapter selon le langage préféré du geek.

Etapes:
  1. Découpage des tâches aléatoire.
  2. En fonction de la compléxité ressentie, choisir un nombre de jour max.
  3. Coder un algo du genre  Math.random() * nombre de j/h max.
  4. Obtenez votre résultat.

Le lancé de dés


Cette technique est équivalente au coffreur mais à l'avantage d'être utilisable par n'importe qui sachant lancer des dés.

Etapes:
  1. Découpage des tâches aléatoire.
  2. En fonction de la compléxité ressentie, changer le nombre de dés.
  3. Lancer les dés.
  4. Obtenez votre résultat.

Le souk ou marchandage de tapis


Cette technique consiste à ne pas prendre en considération le besoin, mais uniquement à marchander avec le client.

Etapes:
  1. Tenter de connaître la fourchette attendue par le client
  2. Si la fourchette est connue, alors rendre un chiffre aléatoire contenu dans la fourchette.
  3. Si la fourchette n'est pas connue, alors présenter plusieurs chiffrages successivement au client en prenant soin de temporiser avant chaque présentation. Si le client dit "c'est trop cher" alors rendre un chiffrage inférieur . Si le client dit "vous avez surement oublié quelque chose" alors gonfler le chiffrage. Réitérer jusqu'à ce que le client dise "Ok".
  4. Le chiffrage est prêt.

Si vous avez d'autres idées, n'hésitez pas à m'en faire part.


Tuesday, February 7, 2012

camel create routes dynamically

Apache camel, create routes dynamically

Create camel routes dynamically

In this entry we'll create a camel route dynamically.
The route uses the camel-mail component that permits to connect to pop/imap/smtp mailboxs.

Dependencies

We use the version 2.9.0 of camel.

maven

  <dependency>
   <groupId>org.apache.camel</groupId>
   <artifactId>camel-core</artifactId>
   <version>2.9.0</version>
  </dependency>
  <dependency>
   <groupId>org.apache.camel</groupId>
   <artifactId>camel-mail</artifactId>
   <version>2.9.0</version>
  </dependency>

ivy

 <dependency org="org.apache.camel" name="camel-core" rev="2.9.0"/>
 <dependency org="org.apache.camel" name="camel-mail" rev="2.9.0"/>

RouteBuilder

In order to create a new Route it is necessary to create a class that extends RouteBuilder.
After you have to implement the method configure() that permits to configure your route.

Example for an imap email route

 public class MailRouteBuilder extends RouteBuilder {
 
  private String login;
  private String password;
  private String host;

  public MailRouteBuilder(String login,String password,String host){
   this.login=login;
   this.password=password;
   this.host=host;
  }


  @Override
  public void configure() throws Exception {
   fromUri=String.format("imap://%s?username=%s&password=%s",host,login,password);
   from(fromUri).to("mock:myMock");
  }
 }


If you use a processor, don't forget to assign an id to the bean inside the camel spring context ex:

 from(fromUri).processRef("imapProcessor").to("mock:myMock");
 
 <bean id="imapProcessor" class="myPackage.MyProcessor" />

Ok, now we have a builder for the new route in a very easy way.
Now it is necessary to create a new spring bean that implements CamelContextAware.
If you use spring and annotation you can configure in a very easy way with the @Service annotation:

 @Service
 public class CamelRouteManager implements CamelContextAware { ...
  

If you don't use the annotation, so you have to edit the camel spring context:

 <bean id="camelRouteManager" class="myPackage.CamelRouteManager" />

The implementation of CamelContextAware need to implement the getter/setter for the camel context. It means you have to provide a camelContext field.

 protected CamelContext camelContext;

 public CamelContext getCamelContext() {
  return camelContext;
 }

 public void setCamelContext(CamelContext camelContext) {
  this.camelContext = camelContext;

 }

Now we can create a method named addMailRoute that creates a new imap route:

 public void addMailRoute(String login,String password,String host){
  MailRouteBuilder mailRouteBuilder=new MailRouteBuilder(login,password,host);
  this.camelContext.addRoutes(mailRouteBuilder); 
 }

If all is ok the route should start automatically.
Ok, but if I want to remove, stop or suspend a route, how can I do ?
Very easy, you have just to use:

camelContext.removeRoute(String routeId)
camelContext.stopRoute(String routeId)
camelContext.suspendRoute(String routeId)
Take care, for remove a route it is necessary to stop it before.

Ok, how can I retrieve the id of the route created dynamically ?

Just have to retrieve the routeDefinition object, go back in the MailRouteBuilder class:

 private RouteDefinition routeDefinition;

 
 @Override
 public void configure() throws Exception {
  fromUri=String.format("imap://%s?username=%s&password=%s",host,login,password);
  routeDefinition=from(fromUri).to("mock:myMock");
 }

 public RouteDefinition getRouteDefinition() {
  return routeDefinition;
 }

 

Now retrieve the routeDefinition object and extract the id in the CamelRouteManager class:

 public String addMailRoute(String login,String password,String host){
  MailRouteBuilder mailRouteBuilder=new MailRouteBuilder(login,password,host);
  this.camelContext.addRoutes(mailRouteBuilder);
  return mailRouteBuilder.getRouteDefinition().getId(); 
 }

It is also possible to create several routes in one shot. You can adapt the code to have a list of routeDefinition instead of a simple String

Now all is done, you can enjoy all your created routes.

In a future article, we'll see how we can persist these routes.

Reference

apache camel official site

Bayes algorithm with apache mahout