Thématiques principales

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

mardi 24 avril 2018

SOLID

Aujourd'hui avec un court article, nous allons traiter d'un acronyme. L'acronyme en question est SOLID. Il s'agit d'un acronyme traitant des 5 recommandations de base les plus importantes de la programmation orienté objet [1].

Ainsi l'acronyme signifie:

S pour Single responsibility principle, signifiant qu'une entité ne doit avoir qu'une seul préoccupation et donc ne répondre qu'à une problématique. Cela suit le principe d'analyse en décomposition permettant de dissocier chacun des éléments du système. Généralement ce principe s'applique en premier lieu aux classes (en POO) cependant il est largement admis qu'il est généralisable en l'adaptant au niveau d'abstraction considéré. Ainsi, on retrouvera la même logique sur des composants mais aussi dans les approches de programmation fonctionnelle.

O pour Open/closed principle. Ce principe est à considérer dans la continuité du principe précédent. C'est à dire que si une entité ne considère qu'un seul problème, afin de garantir cette propriété, elle ne doit pas permettre sa modification sinon, soit elle ne répond plus au problème initial soit elle répond a plus que celui ci. Par contre afin de permettre la composition et l'agrégation des fonctions, une entité doit permettre et même faciliter son extension. ainsi en POO on utilisera les mécanismes bien connu d'héritage ou d'encapsulation permettant de compléter ou d'associer des comportements aux sein d'entité dont c'est justement l'unique rôle.

L pour Liskov principle. Rarement violé ce principe impose que les sous types d'une entité doivent continuer à respecter le contrat de base de celle ci et ne pas la transformer, seulement l'étendre. Ainsi grâce à ce principe, la substitution d'une entité par l'un de ses sous types est transparent.

I pour Interface segregation principle. Rejoignant une nouvelle fois le premier principe, celui ci nous pousse à favoriser la construction d'interfaces multiples mais individuelle plutôt qu'une interface agrégeant l'ensemble des contrats à réaliser. Ainsi la maintenabilité s'en trouve augmenté et grâce au précédent principe, une entité bien que potentiellement défaillante selon une interface peut rester fonctionnelle selon une autre (sinon toutes l'auraient été)

D pour Dependency inversion principle est la aussi la continuité du précédemment principe en considérant que les dépendances, si elles sont construite sur les entité les plus abstraites, permettent plus de souplesse dans la construction logiciel et facilite la réorganisation et la substitution en vertue du principe de Liskov. Poussé à son extrême, ce principe nous amènera alors naturellement vers les frameworks permettant l'inversion de contrôle et l'injection de dépendances

Si tout cela n'est pas encore très clair, je vous invite à lire cette petite page qui résume parfaitement SOLID dans la vie quotidienne

Références

[1] http://blog.xebia.fr/2011/07/18/les-principes-solid
[2] http://www.arolla.fr/blog/2017/02/principes-solid-vie-de-jours/

jeudi 7 décembre 2017

UML (Unified Modeling Language) : Introduction

UML (Unified Modeling Language) est un langage de modélisation graphique destiné à visualiser, analyser, spécifier, construire des logiciels orientés objets [OMG10a, OMG10b]. UML est aujourd’hui considéré comme un standard autant dans le milieu industriel qu’académique. Il propose un ensemble de diagrammes afin de couvrir l’ensemble des besoins de modélisation potentiellement nécessaires à la conception des logiciels, ce qui le rend relativement complet et générique. Ainsi, au travers des 14 types de diagrammes (figure 2.4), UML permet de modéliser les aspects statiques et dynamiques des systèmes complexes et de couvrir la plupart des phases du développement logiciel (analyse, conception, implantation, déploiement, etc.).





  • Les diagrammes des classes : permettent de visualiser l’agencement des concepts d’un système en représentant les classes, leurs rôles, leurs caractéristiques, les services qu’elles proposent, leurs relations (association, composition, etc.) et enfin leur organisation au sein de l’architecture du système logiciel. Ils permettant aussi de représenter des méta-modèles.
  • Les diagrammes de communication : décrivent des configurations types en termes d’objets collaborant. Pour cela, ils permettent de représenter d’une part la configuration d’un ensemble d’objets et d’autre part les relations dynamiques entre ces objets.
  • Les diagrammes d’états transitions : capturent le comportement des objets sous la forme d’un graphe d’états reliés par des transitions. Le franchissement des transitions se réalise à la suite de la réception d’un signal (appel de méthode, exception, etc.).
  • Les diagrammes de cas d’utilisations : permettent pour leur part d’identifier les fonctionnalités d’un système et les conditions nécessaires à leur bon fonctionnement.


Ils font apparaître les éléments fonctionnels, les acteurs et les objets en interaction. UML s’est rapidement imposé pour la conception des systèmes logiciels, pourtant ce langage comporte un certain nombre de lacunes. En effet, il est souvent reproché aux diagrammes UML de posséder une sémantique ambiguë et/ou incomplète. Dans l’évolution qu’a connu UML, cet aspect du langage est devenu un concept : le point de variation. Ainsi, ce coté semi-formel permet au concepteur d’utiliser un langage offrant plus de flexibilité afin d’être étendu vers des contextes de modélisation plus spécifiques.

UML peut être étendu par de nouveaux concepts (à l’aide de stéréotypes ou de contraintes OCL). Une extension de la notation à un domaine spécifique est appelée aussi profil. Par exemple le profil TURTLE [AD05] et le profil ACCORD/UML [GMT04] proposent des extensions des diagrammes UML dédiés à la modélisation des systèmes temps-réels.

Voila un petit aperçu d'UML dans ses grandes lignes sans forcement rentrer dans les détails des diagrammes, nous y reviendrons.

Références:

[AD05] L. Apvrille and P. De Saqui-Sannes. Turtle : a uml-based environment for the codesign of embedded systems. In Proceedings of the 8th Sophia-Antipolis MicroElectronics Forum (SAME 2005), October 2005.
[GMT04] S. Gérard, C. Mraidha, F. Terrier, and B. Baudry. A UML-based concept for high concurrency : The real-time object. Object-Oriented Real-Time Distributed Computing, IEEE International Symposium on, 0 :64–67, 2004.
[OMG10a] OMG. OMG Unified Modeling LanguageTM (OMG UML), Infrastructure Version 2.3, http ://www.omg.org/spec/UML/2.3/ , Mai 2010.
[OMG10b] OMG. OMG Unified Modeling LanguageTM (OMG UML), Superstructure Version 2.3, http ://www.omg.org/spec/UML/2.3/ , Mai 2010.

mardi 5 décembre 2017

Design pattern : Visiteur

Le pattern visiteur est, a mon sens, l'un des patterns les plus importants. Il est classé parmi les patterns comportementaux mais de par son utilisation, il est aussi un pattern structurel.

Le premier intérêt du pattern visiteur est de permettre de découpler les comportements des structures des objets surtout si les comportements ne sont pas tous définis et doivent être extensible. La logique métier est définie a coté de la structure objet stockant les données. A noter qu'en règle générale, cette démarche est a proscrire en POO... sauf, sauf, sauf dans ce cas. Oui le pattern visiteur est fait pour ça, il sépare les préoccupations.



Deuxième intérêt, s'il ne s'agissait que de découpler les aspects comportements et structures, certains avanceront que l'on peut s'en passer....  Sauf .. qu'en fait le visiteur ne vient pas qu'avec cette capacité. En effet, le visiteur a aussi pour but (du fait de son besoin de visiter son objet visitable) de permettre l'appel a d'autres visiteur en faisant le parcours de ses dépendances. Avec cette capacité, le pattern visiteur acquiert le status d'iterateur (Actif) sur un parcourt de graphe, a choisir, le visiteur offrira bien plus de souplesse que l'iterateur.

Ainsi, dans son fonctionnement, le visiteur vient avec une interface Visitable qu’implémentera son client. Cette interface définit la méthode accept prenant en paramètre nos visiteurs. Cette méthode une fois implémentée appellera la méthode visit du visiteur en se passant en paramètre afin de donner a celui-ci toutes ses capacités publiques accessibles ou privées via un peu de reflexivité.

A noter que le pattern visiteur implique cependant une contrainte que la structure a visiter soit suffisamment stable de façon a ne pas avoir une double ration de maintenance a faire dans le cas de modification sur le modèle objet.


vendredi 24 novembre 2017

Design pattern : Patron de methode

Le pattern méthode template est un pattern d’écriture. Un pattern d’écriture est une façon d’écrire un ensemble de ligne de code afin de répondre a un problème. Je rappelle qu'un pattern de conception, est une façon d'organiser les classes/objets et composants afin de répondre la aussi a des problématique standard.

Ce pattern est très couramment employé car il permet de construire dans une classe abstraite une logique d’exécution non finalisé que devront définir les classes filles

public abstract class AbstractCommand {

    protected abstract void precond();
   
protected abstract void execute();
   
protected abstract void postcond();
   
    public final void operate()
    {
        this.precond();
        this.execute();
        this.postcond();
    }
   
}


Ainsi par exemple, dans le cas de cet exemple, toutes les commandes dérivant la classe abstraite devront se conformer a définir les trois méthode precond, execute et postcond, celle-ci étant orchestrées de façon standard pour toutes les commande par la méthode operate.

Cet exemple soufre évidement d'une trivialité sans nom, et ne retranscrit pas complétement l’intérêt de ce pattern très puissant mais l'on peut facilement imaginé que dans la classe abstraite certain comportement soit inconnu et que l'on préfère déléguer aux classes filles la responsabilité de remplir les trous.

A noter que pour contraindre l'utilisation de la méthode operate, on définira les 3 méthodes abstraites a protected et la méthode operate a final.

public class MaCommande extends AbstractCommand {

    @Override
    protected void precond() {
        System.out.println("precond");
    }

    @Override
    protected void execute() {
        System.out.println("execute");
    }

    @Override
    protected void postcond() {
        System.out.println("postcond");
    }

}

mardi 14 novembre 2017

Design pattern : Observateur


Le pattern Observateur est probablement l'un des plus important. Il s'agit d'un pattern comportemental et structurel.

  • Structurel d'abord car il facilite le découplage entre composants
  • Comportemental ensuite car il permet la conception de système réactif et dynamique facilitant a propagation d'informations au travers d'un système comme dans des IHM par exemple. 
Il est d’ailleurs d’élément central au Pattern MVC et est le fondement a la nouvelle API de Java 9 que sont les Reactives Stream

Dans la version standard, le pattern observateur est constitué d'un couple Sujet/Observateur, les second étant abonné au aux premiers qui vont se charger de les notifier de leur éventuellement évolutions, les observateur auront alors la responsabilité de faire l'action sur le ou les objets dont ils auront la charge.

Ici on peut donc constater de multiple avantage:

  • le découplage d'un delta avec l'action qui pourrait en résulter
  • la capacité a réagir des la modification
  • la possibilité de modifier dynamiquement les comportement sur les changements.


Une variante intéressante est l'adjonction d'un événement lors de la notification qui mettra a jour les observateur permettant a ceux ci de d’exécuter les comportements propagés par les événements.

L'ajout des événements permet d'autant plus de découplage en établissant un référentiel d’événements porteur des comportements et structures de données que les sujets et observateur vont se transmettre.

Ceci va ainsi nous permettre de construire un système logiciel de façon décentralisé et réactif ou chaque éléments/composant disposera de sujets et d'observateurs en interactions par le système de mise a jour.

mardi 7 novembre 2017

Groovy

Initialement je souhaitais faire un article sur Gradle mais celui ci est basé sur Groovy, donc en toute logique nous allons faire un petit tour d'horizon de ce langage de script.

Groovy, dont une rapide introduction est donnée ici, est un langage de scripting basé sur Java dont il hérite les principaux concepts tels que le concept objet, le bytecode et la syntaxe. On peut même écrire en Java avec Groovy mais nous verrons qu'il existe des simplifications syntaxique comme le typage dynamique comme en Python ce qui accélère le développement et facilite le prototypage.

Les variables 


Globalement pour la définition des variables, le typage étant dynamique comme en SmallTalk, la declaration se realise par un simple:

a=12
b="toto"

Au choix il est possible (et conseillé ) d'ajouter le mot clef def afin de conserver une lisibilitée sufisante. Dans le cas ou il est necessaire de faire un typage fort, comme Groovy est basé sur Java, rien n'empeche d'ecrire:

Integer a=12
String b="toto"

A noter que je n'ai pas mis de point virgules mais qu'il est possible de les utiliser (Java toujours la...)

Les listes et dictionnaires


Pour ce qui est des listes:

def liste=[ 'toto', 12, "tata" ]
liste.each{
println (it)
}

et des dictionnaires:

def mamap=[ 'toto':12, 12:"tata", "tata":'toto' ]
println mamap['toto']
println mamap[mamap[mamap['toto']]] // pour rigoler un peu...

Bon bien sur il existe aussi les structures de contrôle et les boucles que nous avons vu juste au dessus. A noter que celle ci utilise le pointeur it comme reference a l'objet courant de l'iteration.

Les chaines et regex


Sur les chaines de caracteres on peut employer un raccourci pour faire des regex en utilisant le symbole "=~", ce qui aura pour consequence la creation d'un objet de la classe java.util.regex.Pattern:

def machaine="Groovy is groovy"
def pattern=/(G|g)roovy/
def matcher= machaine =~ pattern

println "tous les resultats"
println matcher.grep().each {
    println it
}
println "Dans le details"
println matcher[0][0]
println matcher[0][1]
println matcher[1][0]
println matcher[1][1]
Nous donnera:
tous les resultats
[Groovy, G]
[groovy, g]
[[Groovy, G], [groovy, g]]
Dans le details
Groovy
G
groovy
g

Les Classes

Etant basé sur java, il va etre possible d'utiliser le concept objet avec quelques simplifications facilitant grandement le prototypage. Prennons par exemple la classe suivante:

class MaClass
{
    String maProp
   
    def hello(quoi)
    {
    return "hello"+quoi
    }
   
   
}
def obj=new MaClass()
obj.hello "world"

Il faut savoir que par défaut les classes en groovy sont publique, les données membres privées et les méthodes publiques.

Pour créer une classe abstraite de la même façon qu'en Java il suffit de déclarer abstract avant le mot clef class et pour définir une méthode abstraite, de la même façon, il faut le déclarer avant le mot clef def.

Pour l’héritage, de nouveau comme en Java, les mots clefs extends et implements sont au rendez vous, tout comme la manière de déclarer des interfaces.

Les closures

Et faire des closures comme en JavaScript ou les lambda expression de Java8, amenant une programmation plus dynamique et réactive.

Ainsi une premiere closure que l'on peut ecrire serai:

def hello={qui ->
    print "hello" + qui;
}

hello("world")
Une closure suit donc la construction syntaxique suivante (ici sous la forme de grammaire simplifier):

CLOSURE ::= { [args->] instructions }

Conclusion

Inutile de faire des kilomètres de doc sur la syntaxe de Groovy, celle ci est simple et si vous etes un développeur Java, vous ne serez pas perdu car vous pouvez a tout instant revenir et faire confiance a vos basiques. Cependant, il ne faut pas se tromper, et finalement ne faire que du Java, car Groovy offre des simplifications pour l’écriture du code qui facilite vraiment le développement rapide. Apres toute la subtilité se trouvera peut être dans l'exploitation du code groovy at runtime....

Pour obtenir plus d'informations générales sur groovy, je vous invite a consulter le site https://www.tutorialspoint.com/groovy ou le site de torrefacteurjava qui est vraiment tres complet.

Maintenant on va pouvoir s’intéresser a Gradle.... et pourquoi pas Grails ?

Design Pattern : Chaîne de responsabilité

Le pattern chaîne de responsabilité est un pattern comportemental permettant en plus d'un découplage entre un client et son comportement de donner une logique spécifique a ce comportement selon l’état éventuel courant (du client, de l’exécution, des types de traitement possible accessible a l'instant t)

Ainsi un Client va déléguer à un objet la responsabilité d’exécuter une action qui sera elle-même déléguée une fois réalisée a un autre objet qui poursuivra l'action en question.

Par exemple, on peut imaginer un besoin lié a la gestion de données vis a vis d'une base consistant a récupérer des données, les traiter, pour les réinjecter mis à jour dans la base.

La chaîne de responsabilité va permettre de modéliser ce processus voir de faciliter son évolution

En Groovy cela donnera un code pas optimiser similaire a celui ci:

abstract class Responsable
{
    Responsable suivant
   
    abstract def traitementReq()
}

class Client
{
    Responsable responsable=new RecuperationData();
   
    def mettreAjourData()
    {
        responsable.traitementReq();
    }
}

class RecuperationData extends Responsable
{
    def traitementReq()
    {
        println "recup"
        suivant=new TraiterData();
        suivant.traitementReq();
    }
}

class TraiterData extends Responsable
{
    def traitementReq()
    {
        println "traitement"
        suivant=new SauverData();
        suivant.traitementReq();
    }
}

class SauverData extends Responsable
{
    def traitementReq()
    {
        println "sauvegarde"
    }
}

def client=new Client();
client.mettreAjourData();
En Java 8 avec les lambda expression, on trouvera rapidement des écritures permettant de simplifier grandement l’implémentation de ce pattern. Ainsi, on résumera donc le pattern chaîne de responsabilité par le diagramme de classe suivant:



A noter que rien ne précise comment passer au suivant, ici dans l'exemple on l'instancie a la volée, mais les objets peuvent être fourni via une factory.