dimanche 31 janvier 2010

Cours de Biostatistique (V)

Cette partie du cours est relative aux test d'hypothèses T de Student qui s'appliquent aux variables quantitatives.
Dans cette partie vous verrez comment poser une hypothèse sur le comportement d'une population et comment tenter de l'invalider au moyen des données de l'échantillon. La philosophie est simple : Si on rejette l'hypothèse alors l'échantillon permet de démontrer l'invalidité de l'hypothèse, si on ne la rejette pas, nous n'avons pas assez d'information dan sl'échantillon pour prouver qu'elle est fausse. Dans ce cas de figure il est assez difficile de conclure de manière définitive.

Les bases de statistiques touchent à leur fin, il restera encore le test du Khi Carré à documenter.

Les Tests d'hypothèses (I)
Les Tests d'hypothèses (II)

vendredi 22 janvier 2010

L'architecture

Donner une définition claire de l'architecture logiciel est chose parfois peu aisée car le sujet englobe une grande partie du processus de développement.

Dans ce billet, pour clarifier les choses, je vais considérer que l'architecture englobe :

- le design
- l'interaction des composants (organisation des composants)
- l'infrastructure (l'hébergement des composants)

Ces différents éléments qui sont, en réalité, des vues sur le système informatique peuvent se résumer au diagramme suivant:











Ce diagramme nous indique comment percevoir notre système informatique (le système informatique se compose en général d'un logiciel et d'une plateforme physique ou logique permettant de le faire fonctionner).
La vue la plus importante, celle qui dirige et qui induit le système, est la vue de cas d'utilisation.
Les cas d'utilisation représentent les fonctionalités que le système va offrir aux utilisateurs. A chaque cas d'utilisation correspondent différents scénarios : un scénario principal décrivant la fonctionalité attendue, des scénarios alternatifs prenant place lorsqu'une erreur se produit ou qu'une donnée est manquante.

Les quatre vues suivantes ne font qu'implémenter concrètement les spécifications qui ont été définies dans la vue de cas d'utilisation.

La vue logique décrit comment sera organisé le code, comment seront regroupées les fonctions qui réaliseront les cas d'utilisation. Ces fonctions appartiendront à des classes qui pourront collaborer entre elles en vue des réaliser les cas d'utilisation définis. Cette vue est parfois la seule visible pour des petits systèmes d'information.

La vue de processus décrit comment vont fonctionner et comment seront synchroniser les threads ou les processus réalisant des opérations en parallèle. Si le logiciel utilise des services, il génère des threads chaque fois qu'il doit gérer de nouvelles connections, ...

La vue de réalisation (collaboration) décrit comment les composants interagiront ensemble et où ils seront stockés. Ceci peut être représenté par un diagramme de composants. Les noeuds qui contiennent ces composants seront également décris. Cette vue est très utile dans les systèmes distribués.

La vue de déploiement décrit comment le système informatique sera organisé, déployé. Cette vue peut ressembler au diagramme de composant sauf que, ici, l'accent sera mis sur l'agencement du réseau et des serveurs (noeuds).

Les gros systèmes seront généralement décrits par ces quatre vues, les plus petits systèmes se contenteront généralement de la vue logique.


Les types d'architectures logiciels:


Les types d'architecture vont indiquer comment les composants d'un logiciel vont se répartir. On distingue en général des composant utiles à l'affichage, au traitement et au stockage. Une architecture relativement courante dans les systèmes d"information est l'architecture dite
Client/Serveur.
Un logiciel client installé sur un poste de travail accède aux données stockées sur un serveur de base de données. Cette architecture permet de partager facilement des informations entre différents utilisateurs répartis sur des postes différents. En général, cette architecture se limite au réseau physique de l'entreprise. Si les postes de travail sont relativement évolués, les programmes clients pourront aussi effectuer des traitements locaux sur les données. Ceci permet de répartir la charge de travail entre le serveur et les clients.

L'architecture 3 Thiers
Cette architecture est souvent utilisée par les applications Internet (application de eCommerce, de data-capture, ...). Dans ce type d'application, le client est un browser Internet qui permet des traitements relativements légers. Le client accède à un web-serveur qui lui renvoie des pages HTML (HyperText Markup Language) générées dynamiquement. Cette génération dynamique se fait en général par des extensions du web-serveur. Il peut s'agir de DLL, DSO, script CGI(remarquez que PHP par exemple fonctionne sur base d'une DSO).
L'avantage de cette architecture est de s'ouvrir au monde. En effet, il sera possible d'accéder aux données en dehors du réseau local puisque les accès se feront à travers Internet. Toutefois, si on laisse les extensions sur le web-serveur, on arrive très vite au problème de montée en charge. Que se passe-t-il si trop d'utilisateurs se connectent sur le serveur et que le CPU ou la mémoire s'effondre ? Le système deviendra inutilisable. Nous arrivons donc à un problème crucial qui est la "scalabilité" (déjà évoqué dans un précédent billet) c'est-à-dire la faculté de pouvoir fonctionner quel que soit le nombre d'utilisateurs connectés en même temps.

Les architectures distribuées.
Les architectures distribuées utilisent des composants (EJB, COM, COM+, assembly .Net, ...) pouvant s'éxécuter sur un serveur d'application. Ces composants seront sollicités par les extensions du web-serveur. L'avantage de cette approche est que certains composants pourront fonctionner sur un serveur d'application alors que d'autres fonctionneront sur un autre. Ceci permet de répartir la charge et ceci a pu voir le jour grâce à des technologies comme CORBA ou DCOM qui permettait d'invoquer des méthodes de composants à travers le réseau.
Par la suite, DCOM a été remplacé par COM+ qui a lui même évolué en .Net.
D'une manière générale, l'invocation des composants et l'organisation de ceux-ci se fait sur un même réseau local.

Les architectures de services.
L'architecture de service qui a vu le jour dans le début des années 2000 outrepasse la capacité d'utiliser des composants organisés sur un réseau local mais permet d'utiliser des services n'importe où sur Internet.
Un exemple simple serait la possibilité pour le système informatique d'une agence de voyage de communiquer avec le système de réservation d'une compagnie aérienne. Les deux infrastructures sont totalements séparées mais, grâce à l'architecture de service, il serait possible à l'agence de voyage de réaliser automatiquement la réservation du billet d'avion. Cela peut se réaliser au moyen des Web-Services qui sont des composants distribués à travers l'Internet.

mardi 19 janvier 2010

Cours de biostatistique (IV)

Cette partie du cours est consacrée à la fin des distributions de probabilité et à l'inférence statistique.

L'inférence statistique va utiliser l'échantillon et les probabilités pour tenter de prédire le comportement d'une population dont serait extrait l'échantillon.
L'échantillon représente donc un ensemble de données empiriques (provenant des mesures expérimentales).
La population est un modèle théorique décrit par une distribution de probabilité.
Nous distinguerons deux parties importantes dans l'inférence statistique:
  • L'estimation: va nous permettre à partir des données de l'échantillon de définir un intervalle de confiance sur les paramètres de la distribution théorique.
  • Les tests d'hypothèse: nous allons considérer une hypothèse sur la population et tenter d'utiliser l'échantillon pour la démolir.
Dans les cours présentés, nous introduirons brièvement la philosophie du test d'hypothèse.

Inférence statistique (I)
Inférence statistique (II)

lundi 18 janvier 2010

Qualités d’un logiciel

Validité : faculté dont dispose le logiciel de faire ce qu’il doit. Cela s’obtient par l’utilisation d’une bonne méthodologie.

L’intégrité : faculté d’un logiciel à maintenir la justesse de ses données en toutes circonstances, protéger ses accès et ses données d’accès non autorisés. Cela s’obtient par l’utilisation de techniques appropriées (OS capable de gérer les accès mémoire d’une application à l’autre) et d’une bonne méthodologie (utilisation de l’encapsulation provenant de la POO).

La fiabilité : faculté d’un logiciel à gérer ses erreurs correctement. Cela s’obtient par l’utilisation d’une bonne méthodologie de coding, comme, par exemple, l’utilisation et la gestion des exceptions.

La scalabilité : faculté de pouvoir monter en charge, sans devoir modifier le code programme, en changeant simplement l’organisation du logiciel (le scinder sur différents serveurs pour répartir la charge). Ceci s’obtient par un design intelligent.

La reusabilité : faculté de ne pas devoir réinventer la roue à chaque fois que l’on veut ajouter des fonctionnalités mais, au contraire, pouvoir s’appuyer sur une fondation consistante. Ceci s’obtient par un design et une méthodologie corrects.

La maintenabilité : capacité à maintenir sans se noyer ou se faire dépasser par la complexité de celui-ci. C’est avant tout un problème de design et de documentation.

L’extensibilité : capacité d’ajouter de nouvelles fonctionnalités au logiciel. Ceci s’obtient en utilisant un design tenant en compte la reusabilité.

Les performances : faculté de répondre dans des délais raisonnables. Ceci s’obtient par un coding approprié (algorithmes optimisés).

L’interopérabilité : faculté de s'intégrer avec d'autres applications logicielles. On utilise une architecture composant pour achever cet objectif.

La plupart de ces notions de qualité sont dépendantes les unes des autres. Exemple : un logiciel peu fiable peut très bien, à un moment ou à un autre, écrire de mauvaises données au mauvais endroit et avoir un impact sur l’intégrité du logiciel.

Un logiciel basé sur un design de réusabilité pourra facilement être étendu. De plus, ces extensions basées sur des composants ou classes existantes auront un impact positif sur la fiabilité et l’intégritié. La réusabilité facilitera aussi la maintenabilité du logiciel, puisqu’une erreur corrigée à un endroit se répercutera partout. Au final , plus votre logiciel évoluera, plus ses bases se solidifieront.

La scalabilité et les performances, même si elles sont des notions différentes, sont aussi très liées. Avoir des performances extraordinaires qui vont s’effondrer dès que dix utilisateurs vont se connecter n’est pas très intéressant. Avoir une architecture permettant la connexion de millions d’utilisateurs mais mettant dix minutes à produire un résultat qu’il y ait un ou un millions d’utilisateurs n’est pas acceptable non plus.
Toute la finesse consiste à trouver un équilibre, un compromis entre scalabilité et performances.

Ces différents objectifs de qualité, classés ici suivant mon ordre d’importance doivent être traduit par le processus de qualité, qui est lui-même formalisé sous forme de Procedures d’Operation Standard (POS ou SOP en anglais).

L'un des fondements de la qualité est aussi la traçabilité. Son rôle est d'identifier lors de problème où se trouve celui-ci. Ceci semble très bâteau mais, en pratique, c'est parfois très difficile de démêler les faits, en particulier s'il y a un manque de transparence... La traçabilité assure cette transparence.

Il serait intéressant de définir des indicateurs (sorte de KPI) permettant de mesurer ces concepts de qualité.

mardi 12 janvier 2010

Probabilités


Petit exercice de probabilité, bien énervant, comme la plupart des exercices de probabilités ;-)

Une étude auprès des associations de refuge pour animaux nous apprend qu'environ 60% de chiens mâles sont adoptés.

Une autre étude sur les chiens nous apprend qu'environ 70% de chiens mâles pèsent plus de 30kg contre 25% de chiens femelles pesant plus de 30kg.

Si Madame Durand décide d'adopter un chien de plus de 30kg pour son mari, quelle est la probabilité qu'elle adopte un chien mâle ?

Si l'on examine les données, on peut déduire les évènements suivants :

M : Adopter un chien mâle
>=30 : L'animal pèse plus de 30 kg

D'où les probabilités suivantes :

P(M)=0.60 (par l'énnoncé)
D'où P(nonMale)=0.40

a) P(>30kg!Male)=P(>30kg et Male)/P(Male)=0.70
b) P(>30kg et Male)=0.70*0.60 =0.42
c) P(>30kg!nonMale)=P(>30kg et nonMale)/P(nonMale)=0.25
d) P(>30 et nonMale)=0.40*0.25=0.10

Ces assertions nous permettent de créer la table de contigence ici produite (la dernière étant la bonne).

La différence entre le "et" et la probabilité conditionnelle "!" (normalement c'est un pipe, mais ça ne passe pas sur blogger ;) ) est assez énervante, je dois le reconnaître. Le "et" se réfère à l'ensemble des cas possibles c'est-à-dire dans ce cas de figure:
"la probabilité que j'adopte un chien mâle de plus de 30kg parmi tous les chiens adoptables possibles". C'est toujours cette probabilité que l'on retrouve dans la table de contigence et cette probabilité vaut bien sûr 42%.

Or, dans l'ennoncé, on nous demande un chien de plus de 30kg, qui soit un mâle, ce qui signifie que le critère >30kg est fixé, ce qui revient à écrire P(Male!>30kg)=P(Male et 30 kg)/P(>30kg)

P(>30kg)=0.52 (par le tableau)
P(Male!>30kg)=0.42/0.52=80.8%.
Madame Durand aura donc 80.8% de chances de rapporter un chien mâle à son mari.

mercredi 6 janvier 2010

Cours de biostatitistique (III)

Ces notes de cours sont consacrées au calcul des probabilités. En effet, l'intérêt de réaliser des mesures sur un échantillon de données est d'inférer (extrapoler) ces données à une population qui n'est pas toujours connue. Afin de réaliser cette inférence à une population, les statisticiens utilisent un outil mathématique : les probabilités. Grâce à celle-ci, il sera possible de prédire les propriétés d'une population ou encore de donner une marge d'erreur sur les données provenant d'un échantillon par rapport à ce que l'on pourrait mesurer dans la population.

Les notes proposées ici contiennent les règles de calcul de probabilités et de distribution de probabilité.

Le calcul des probabilités
Distributions de probabiltiés

mardi 5 janvier 2010

Delphi Prism 2010

Delphi Prism est le nouveau joujou annoncé par Embarcadero pour developer dans l’environnement .NET et Mono.

L’avantage Mono est bien sûr la possibilité d’utiliser le framework .Net sous Linux ainsi que Mac OS. Encore une fois, le framework n’est jamais le dernier et les outils tels que MonoDevelop sont probablement moins performants que Visual Studio. Mais bon, c’est gratuit donc…
(ref : http://blog.developer.mindtouch.com/2009/08/10/monodevelop-and-visual-studio-2008/)

Cette version de Delphi distribuée par Embarcadero peut s’intégrer dans le CodeGear RAD Studio mais aussi dans le MS Visual Studio.
Ce que Embarcadero ne nous dit pas clairement, c’est que cette nouvelle mouture annonce la mort de Delphi .NET et, dans la foulée, la mort de la VCL.NET. En effet, Delphi Prism est un produit qui n’est ni développé par CodeGear, ni par Embarcadero mais par la société RemObjects qui est elle-même un partenaire de Microsoft Visual.

La mort de la VCL.NET était relativement prévisible, puisque reconstruire un framework .Net au dessus du framework original n’était probablement pas une bonne idée puisque, d’une part, la compatibilité avec l’ancienne VCL n’existait pas et qu'il fallait réécrire malgré tout le code et, d’autre part, pourquoi la copie à l’originale si c’est pour se lancer dans une réécriture autant prendre le framework .NET natif et même choisir le langage écrit pour ce framework, c’est-à-dire C#.
D’ailleurs, certains professionnels de Delphi déconseillaient fortement l’utilisation de cette VCL.NET.

C’est peut-être une bonne nouvelle pour les programmeurs Delphi (et pour l’avenir de Delphi) de savoir que, désormais, on peut coder du Delphi grâce à Visual Studio. Toutefois, pourquoi s’amuser avec Delphi alors que C# est un langage complètement façonné pour cette plateforme…

(source : http://www.e-naxos.com/Blog/post/2009/03/09/Delphi-Prism-la-seconde-mort-de-Delphi.aspx#auteur)

lundi 4 janvier 2010

Scalability & Optimisation

A tort ou à raison, la “scalabilité” d’une architecture est souvent associée aux performances de cette même architecture.

Par achitecture j’entends le design de l'application, la technologie et l’infrastructure utilisée.

En ce qui me concerne je définis la scalabilité comme l’aptitude à supporter un plus grand nombre d’utilisateurs avec des temps de réponses comparables. Bien sûr, on peut y voir un lien directe avec les performances mais pas uniquement.

Je défini les performances d’une application comme étant fonction du hardware utilisé (CPU, RAM, contrôleur disque), l’infrastructure (bande passante du réseau, configuration des routers, switch, …), optimisation du code.
Certes en utilisant au mieux nos ressources nous pourrons avoir des performances rapides, mais qui risqueront de décroître rapidement, si la charge (nombre de requête) augmente rapidement.

L’idée d’une architecture "scalable" ou extensible est de fournir une application qui aura des temps de réponses plus ou moins constants en fonction de la charge.

Une image que j’aime évoquer est celle de la formule 1 et du tracteur. Une formule 1 pourra atteindre de vitesse de pointe phénoménale, mais elle ne pourra plus rouler si vous lui attachez une charge trop conséquente. Le tracteur fonctionne à l’opposé, il ne roulera pas vite mais pourra tirer pratiquement n’importe quelle charge.

Pour « scaler » en général on utilise une infrastructure qui permet d’adjoindre de nouveaux serveurs en cas de besoin. Cette faculté doit être prévue par le design, la technologie et l’infrastructure de votre application.
D’aucun pourrait dire qu’adjoindre des serveurs est idiot puisqu’il suffit d’upgrader le matériel (mettre un meilleur cpu et plus de ram). D’une part les upgrade matériels ne sont pas infini, la motherboard ne peut pas accepter un nombre illimité de processeurs ou de barettes de RAM. D’autre part si un processus mange 100% de votre temps CPU sur le processeur, il pénalisera d’office le reste des utilisateurs. Sur des serveurs différents, ce problème est moins grave, un serveur bloqué ne bloquera pas forcément les autres.

La question à se poser lors du design est simple:
Que se passe-t-il si j’ajoute un nouveau serveur ?
Si le design initiale ne marche pas il faut tenter de déterminer pourquoi.

L’un des problèmes fondamentaux est la réplication des sessions utilisateurs d’un serveur vers un autre (concevoir une architecture statefull). Heureusement, il existe des techniques pour solutionner ce genre de problèmes.

Conclusion

Existe-t-il des meilleurs outils de développements (meilleures technologies) pour être scalable ou pas ?
Ma réponse serait non, car la scalabilité est avant tout un problème de design, si vous avez mal conçu votre architecture, quelque soit le langage utilisé, votre application ne pourra pas être étendue facilement.
D’un autre côté si la scalabilité n’est pas forcément liée à l’optimisation, ce n’est pas pour autant que l’on peut programmer n’importe comment sans rien n’optimiser. Si le but est de conserver un temps de réponse constant quelque soit le nombre d’utilisateurs, ce temps de réponse doit tout de même être acceptable !