jeudi 16 septembre 2010

CMMI : Méthode GQM

J'ai découvert récemmet la méthode GQM (Goal/Question/Metric) grace au site http://afoucal.free.fr/.

Cette methode propose un guide pour mettre en place des metriques dans le cadre de qualité logiciel. Elle est une réponse aux exigences CMMI (processus Mesure et Analyse).

Pour plus d'information, vous pouvez allez voir sur le cite officiel (en Anglais) : http://www.gqm.nl/

    mercredi 1 septembre 2010

    Hudson - Ant : Liste des parametres utilisables dans un script Ant

    Voila la liste des parametres utilisables dans un script Ant lancé par Hudson :

    BUILD_NUMBER Le numero du build, exemple "153"
    BUILD_ID L'id du build, exemple "2005-08-22_23-59-59" (YYYY-MM-DD_hh-mm-ss)
    JOB_NAME Nom du projet du build. C'est le nom du job configuré. C'est le nom que l'on retrouve dans la 3ème colonne du dashboard de la page principale.
    BUILD_TAG Concaténation de : hudson-${JOBNAME}-${BUILD_NUMBER}. Pratique pour mettre dans un fichier de ressource, un jar,... pour faciliter l'identification.
    EXECUTOR_NUMBER Le numéro unique de l'éxecution. (Commence à 0 et non 1)
    JAVA_HOME Le JAVA_HOME de la JDK utilisée.
    WORKSPACE Le chemin absolu du workspace.
    SVN_REVISION Pour les projets Subversion, cette variable contient le numéro de revision SVN. Si plusieurs modules SVN configurés, la variable ne sera pas positionnée.
    CVS_BRANCH Pour les projets CVS, cette variable contient le numéro de revision CVS. Si plusieurs modules CVS configurés, la variable ne sera pas positionnée.

    jeudi 15 juillet 2010

    Java - Ivy : création d'un repository local

    Voila une façon simple de créer un repository local :
    • Créer un repertoire partagé sur une machine en réseau. Exemple :  \\ma-machine\repository
    • Créer un fichier de configuration Ivy :
      <ivysettings>
          <properties file="${ivy.settings.dir}/ivysettings.properties">
          <property name="myrepository" overrite="true" value="//ma-machine/repository">
          <settings defaultresolver="chain-local">
          <resolvers>
              <chain name="chain-local">
                  <filesystem checkmodified="true" name="local">
                      <ivy pattern="${myrepository}/[module]/[revision]/ivy-[revision].xml">
                      <artifact pattern="${myrepository}/[module]/[revision]/[artifact]-[revision].[ext]">
                  </filesystem>
                  <ibiblio m2compatible="true" name="maven2">
                  <ibiblio m2compatible="true" name="jboss" root="http://repository.jboss.org/nexus/content/groups/public/">
              </ibiblio>
          </resolvers>
      </ivysettings>
    • Il suffit ensuite d'importer le fichier de configuration dans ant :
      <ivy:settings file="${basedir}/ivysettings.xml" />
    Bien sur il reste à remplir se repository...

    vendredi 11 juin 2010

    Java - Ivy : découverte

    Depuis longtemps, je gérais mes dépendances en utilisant SVN. En gros j'importais toutes mes librairies et leurs dépendances dans SVN en les taggants avec leur version. L'export se faisait via un script batch mais cela demandait la gestion des dépendances des dépendances... (Pas très pratique quand on changeait de version de lib). Le pire était pour la gestion des modules car il fallait les importer dans SVN dès qu'une modification était réalisée. De plus, SVN n'étant pas vraiment fait pour l'import de binaire, la base avait tendance à grossir.

    Dernièrement, je me suis mis à l'intégration continue (Hudson pour tout vous dire). Tout fonctionne bien avec l'utilisation de mes lib chargées dans SVN. Mais en voulant utiliser des plugins de type "tag automatique" j'ai rencontré un problème vu qu'Hudson essaye de tagger tout ce qui a été extrait de SVN donc mes Jar, ce qui pour le coup pose vraiment problème.

    En fouillant un peu, je suis tombé sur 2 solutions pour gérer mes dépendances : Maven et Ivy. Etant sous Ant, mon choix c'est porté sur Ivy.

    Les premier pas ne sont pas forcément évident. Les tutoriaux proposés se limitent aux premiers pas et la documentation, bien que complète, est plutôt faite pour des connaisseurs. Mais en persévèrent un peu et en posant quelques questions sur mon forum favori (developpez.com). On passe cette étape et là, on se rend vraiment compte de la puissance de cette outil.

    Plus besoin de se soucier des dependances, Ivy s'en occupe. Il suffit juste de lui donner quelle librairie on veut utiliser et il va chercher toutes les dépendances utiles. Par défaut, Ivy va chercher dans le repository de Maven qui est bien complet. Et pour les modules que l'on développe et que l'on partage, il suffit de se créer un repository local (dans mon cas un simple répertoire partagé, mais on peut faire beaucoup plus complet si on le souhaite) où l'on publirea nos modules. Et là encore Ivy s'occupe de ses dépendances.

    vendredi 7 mai 2010

    Agilité - Le rythme soutenable

    L'un des principes du manifeste agile est "le rythme soutenable". Mais dans nos entreprises il n'est pas toujours facile de le déterminer ni même de le garder sous la pression des managers.
    Emmanuel Chenu vient de publier un post fort intéressant à ce sujet sur son blog. Il parle du rythme de travail mais aussi du stresse apporté pour la pratique des méthodes agiles.

    C'est par ici.

    mardi 27 avril 2010

    Agilité - La chasse à la bonne méthode

    Comme beaucoup, je suis attiré par la mise en pratique des méthodes agile dans mon travail pour palier aux inconvénients rencontrés par la pratique de méthodes dites standard. Connaissant de nom Scrum et XP je me suis déjà penché dessus pour voir leur bénéfices et comment les appliquer. Mais très rapidement on découvre qu'il existe d'autres méthodes : Kanban, Lean, RUP, PUMA, FDD...
    Et la ça commence à être le bazar, les questions s'accumulent : quelle méthode choisir? Faut il en prendre qu'une ou plusieurs? Faut il faire un mixte? Prendre que ce qui nous intéresse? Prendre un coach? Suivre des formations?...

    Dans cette quête de réponses, quelques sites proposent des comparatifs qui, même s'ils ne peuvent pas tout comparer, peuvent aider :
     
    Bonne lecture.

    lundi 26 avril 2010

    Java - Swing : Exemple de base

    Tout ceux qui on un jour fait du client lourd en Java se sont pris la tête pour avoir un composant qui répond exactement à leur besoin. Les bibliothèques Java Swing et AWT propose déjà un bon nombre de composant prêt à l'emploi. Sans parler des « nouvelles » librairies tel que SwingX qui permettent d'étendre le nombre de composant prêt à l’emploi. Mais même ainsi, il n'est pas rare de vouloir un comportement diffèrent de celui qui est implémenté de base. Heureusement ces librairies ont été conçues pour être entièrement paramétrable. Mais ces modifications ne sont pas toujours évidantes à réaliser, surtout si l'on n'est pas un spécialiste dans ce domaine.

    Ce site référencie les modifications fréquemment faites avec le code java correspondant : SwingExamples.

    vendredi 23 avril 2010

    Java - JTree avec des icones spécifiques

    J'ai voulu faire un JTree affichant des icones spécifiques à chaque noeud.
    Dans mon cas, l'objet du noeud est capable de fournir sa propre icone, ce qui simplifie le code. Du coup la solution est simple : il suffit de faire un Renderer héritant de DefaultTreeCellRenderer et de redéfinir la méthode getTreeCellRendererComponent.

    Ce qui donne :
      @Override
      public Component getTreeCellRendererComponent(JTree tree,
                Object value,
                boolean sel,
                boolean expanded,
                boolean leaf, int row,
                boolean hasFocus) {
        Component component = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
        if (Filiale.class.isInstance(value)) {
          setIcon(((Filiale) value).getIcon());
        }
        return component;
      }

    Pour plus d'info : http://java.sun.com/docs/books/tutorial/uiswing/components/tree.html#display

    jeudi 22 avril 2010

    Java - Bonnes pratiques


    Je rassemble ici en ensemble de bonnes pratiques trouvées dans mes périgrinations.

    Les classes interdites

    Lors d’utilisation de classe provenant d’un SDK, il faut s’assurer qu’elles correspondent bien a nos besoins et qu’il n’y a pas plus « léger » à utiliser. Certaines classes ne sont la que pour assurer la compatibilité ascendante. On en exclura donc leur usage sauf si leur remplacent ne satisfont pas au besoin.

    Exemple de classes "interdites" :
    • Hashtable : classe synchronisée => Thread-safe mais lourde (rapport 1 à 5)
      Utiliser plutôt dans une utilisation standard : HashMap
      Si besoin d’un conteneur thread-Safe utiliser : Collections.synchronizedMap
    • Vector : classe synchronisée => Thread-safe mais lourde (rapport 1 à 5)
      Utiliser plutôt dans une utilisation standard : ArrayList
      Si besoin d’un conteneur thread-Safe utiliser : Collections.synchronizedList

    Concaténation de chaînes de caractères

    Malgré ce que l’on pense, le code suivant n’est pas mauvais ; il est même optimum :
    String s = "In memory-constrained situations" +
               ", you should pay close attention" +
               " to the" +
               " proliferation " +
               " of"+
               " strings";

    En effet, le compilateur va optimiser l’expression en la transformant en une seule chaîne. De même que ce code :
    String myValue = “Ma valeur à afficher”;
    String s = “You should pay close attention" +
             " to the" +
             " proliferation " +
             "of"+ myValue;

    Par contre celui-ci est plus coûteux car le compilateur ne sait pas l’optimiser. Et, il sera à éviter.
    String s = "In memory-constrained situations";
    s+= ", you should pay close attention";
    s+= " to the";
    s+= " proliferation ";
    s+= "of";
    s+= " strings";

    Il est possible d’utiliser un StringBuilder qui sera moins couteux et plus flexible lorsque le 1er cas ne peut être suivi :
    StringBuilder sb = new StringBuilder() ;
    Sb.add("In memory-constrained situations") ;
    Sb.add(", you should pay close attention") ;
    Sb.add(" to the") ;
    Sb.add(" proliferation ") ;
    Sb.add("of") ;
    Sb.add(" strings") ;

    Classes retournant des collections.

    Beaucoup de classe retournent des collections (List, Map,...). Ces collections doivent toujours être initialisées. S’il n’y a pas d’objet dans la collection celle-ci doit être vide mais non null.

    Les tableaux fourretouts

    Il faut éviter les tableaux fourretouts de type Object[]. Cela rend le code illisible et compliqué à utiliser (quel objet vais-je trouver dans le tableau ? Comment dois-je construire ce tableau ?) et source d’erreur vu qu’il n’y a pas de typage. Il est préférable de créer une classe « Bean » rassemblant les objets composant ce tableau.

    Exceptions

    Ne jamais ignorer une exception
    Une erreur fréquente est de mettre un bloc catch vide sans aucune instruction afin de pouvoir compiler le programme. Ceci est très dangereux. En effet, si une exception survient, elle sera passée sous silence et le programme continuera de fonctionner ce qui peut déboucher sur des bugs incompréhensibles. Le bon réflexe est de bien traiter les exceptions dans les blocs catch. Mettre un commentaire clair si c’est normal de ne rien faire.

    Reflet de l’erreur
    Les exceptions doivent refléter l’erreur levée. Trouvez la bonne granularité : une interface graphique se moque de savoir que c’est la base de données qui ne répond pas. Elle a juste besoin de savoir que le service est momentanément interrompu. Le niveau de précision (la granularité) de l’exception doit être adapté à la position du module dans une architecture en couche.

    Les exceptions génériques
    Eviter de catcher les exceptions génériques du style :
    Try {
         .....
    } catch (Exception e) {
         .....
    }

    Il est préférable de catcher exception par exception et de faire le traitement spécifique. Cela permet un débogage plus facile en cas de problème.

    De même, il est déconseillé de renvoyer une exception générique. Il est préférable de créer des exceptions par package ou d’utiliser les exceptions fournis dans le SDK, cela permet, sur une trace, de retrouver plus facilement les causes de l’exception levée.

    Les exceptions et les entrées/sorties
    En cas d’exceptions, il faut s’assurer que l’état après le catch est stable et qu’il ne reste rien d’ouvert (fichier, flux, connexion,...).
    Il faut donc utiliser le « Finally » pour libérer les ressources.

    Exemple java :
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;

    public class FluxMajuscule {

    /** Crée une nouvelle instance de FluxMajuscule */
      public FluxMajuscule() {
      }

      public void readMaj(){
        try{
          BufferedReader br=new BufferedReader(new FileReader("monFichier.txt"));
            try{
              String ligne;
              String ligneMajuscule;
              while((ligne=br.readLine())!=null){
                ligneMajuscule=ligne.toUpperCase();
                System.out.println(ligneMajuscule);
              }
            }finally{
              br.close();
            }
          }catch(IOException ex){
            ex.printStackTrace();
          }
        }
    }

    Manifest

    En Java, il est conseillé de remplir le manifeste de façon standard. Le SDK fournit des méthodes pour aller lire ce manifeste dans des packages.

    Exemple de manifest java :
    Manifest-version: 1.0
    Implementation-Version: 1.2

    Specification-Title: MaLibrary
    Specification-Version: 1.2
    Specification-Vendor: MaSociété
    Implementation-Vendor: MaSociété
    Implementation-Title: MaLibrary
    Implementation-Version: 1.2
    Build-date: 2009-09-07 19:01:52

    Thread

    Synchronisation
    La mise en place d’un processus de synchronisation est tres gourmant en ressource. Du coup avant de se lancer dans la synchronisation, on doit se poser quelques questions :
    • A-t-on vraiment besoin d’avoir une méthode synchronisée ? (Utilisation de ressource synchrone ? Ordre d’exécution important ?...)
    • Cette méthode peut-elle être utilisée en multi-thread ?

    Le mot clé « synchronized » en java permet de définir des sections critiques thread safe. Il est souvent utilisé avec la déclaration de la méthode d’une classe.

    public synchronized void theMethod() {}

    Cette écriture est équivalente à
    public void theMethod() {
      synchronized (this) {
        …
      }
    }

    Plutôt que d’utiliser la synchronisation au niveau de la méthode, il est préférable de l’utiliser uniquement sur la section de la méthode qui nécessite un accès thread safe. D’ailleurs, rien n’oblige le développeur à utiliser « this » comme objet de synchronisation. On peut par exemple utiliser un singleton si l’on souhaite synchroniser plusieurs méthodes disséminées dans plusieurs objets.
    Le principal reproche que l’on puisse faire à la technique du synchronized, c’est le manque de granularité. En effet, si un système multi thread tente de lire et de modifier une variable en même temps, le verrou sera le même pour la lecture ainsi que pour l’écriture, provoquant un goulot d’étranglement.

    Pour palier a cela, il est possible d’utiliser des verrous d’écriture et de lecture, mais le code s’en retrouve complexifié.
    Un verrou de lecture est différent d’un verrou d’écriture. Le verrou d’écriture doit attendre que les verrous de lecture soient tous levés pour être posé. Plusieurs verrous de lecture peuvent être posés en même temps alors qu’un seul verrou d’écriture ne peut être posé à un instant donné.

    mercredi 21 avril 2010

    Design Pattern Composite


    Le pattern Composite est constitué d’objets ayant le même comportement sur une profondeur variable. Cela permet d’interagir sans avoir à connaître si on parle à un objet métier ou à un groupe.

    Description du problème

    Lorsque l’on travaille avec des données sous forme d’arbre, il est souvent nécessaire de différencier les branches des feuilles pour savoir quel traitement effectuer.

    Pour illustrer le contexte, prenons un exemple :
    Nous souhaitons faire une application de dessin qui manipule des objets « graphiques » de base (carré, cercle, triangle,...). L’utilisateur lui a besoin de formes plus complexes qui seront fait à partir de formes de base ou même d’assemblage d’autres formes complexes. Il est donc nécessaire que ces formes complexes se comportent de la même façon qu’une forme simple.

    Si on utilise un arbre simple, la programmation devient compliquée car il faut parcourir entièrement cet arbre tout en différenciant les actions réalisées sur les branches et les actions réalisées sur les feuilles. Cela nécessite du code et généralement des méthodes récursives pour effectuer les opérations.

    Ce pattern répond à ce type de problème.

    Diagramme UML


    Définition de la solution

    Composant : C’est la classe abstraite pour tous les composants, y compris les Composés. Elle déclare les interfaces pour les « opérations » et définit les méthodes de manipulation des enfants.
    Feuille : Représente les « feuilles » dans la composition. Elle met en œuvre toutes les méthodes « opération ».
    Composé : Elle représente un composant composite (Pouvant avoir des enfants), elle implémente les méthodes pour la manipulation des enfants (ajout, suppression,…) ainsi que les méthodes « opérations »

    Le pattern Composite permet au client de ne pas avoir à se soucier s’il interagi avec une feuille ou une branche (Composé).

    Le composé s’occupera lui même de transmettre les demandes aux feuilles. On pourra même rajouter de l’intelligence au niveau de la branche.

    Dans notre exemple, on pourrait très bien imaginer un calcul de volume : chaque feuille calcule son volume et le composé additionne tous ces volumes.

    Le client exécute une « opération » sur un composé. Ce composé exécute un prétraitement (si besoin), parcoure tous ces fils en demandant l’exécution de la même opération, puis fait un post-traitement (si nécessaire).

    Variante

    L’élément « composant » peut être une simple interface. Mais alors il faut implémenter dans chaque feuille les méthodes pour la manipulation des fils.

    Conséquences

    L’arbre ainsi réalisé est fortement typé. Il ne peut donc pas être utilisé de façon générique mais facilite fortement le développement du « Client ».

    L’interaction entre les branches et les feuilles en est aussi simplifié; les branches ne s’occupant que de retransmettre les ordres aux feuilles sans avoir à connaître leur comportement interne.

    Ce design-paterne ne doit être utilisé que si les feuilles et les branches ont des opérations communes (déclaré dans la classe composant).

    Exemple

    mardi 20 avril 2010

    La programmation orientée objet (POO)

    La programmation orientée objet (POO) ou programmation par objet, est un paradigme de programmation informatique qui consiste en la définition et l’assemblage de briques logicielles appelées objets.

    L’objet

    Comme l’indique son nom, la composante principale de la Programmation Orientée Objet est l’objet. Un objet regroupe les données et les moyens de traitement de ces données.
    Un objet rassemble de fait deux éléments :
    • Les attributs : ce sont les variables de l’objet : ce sont eux qui ont en charge les données à gérer. Dans la plupart des langages un attribut possède un type quelconque défini au préalable : nombre, caractère, ..., ou même un type objet.
    • Les méthodes : les méthodes sont les éléments d’un objet qui servent d’interface entre les données et le programme. Ce sont en fait les procédures ou fonctions destinées à traiter les données.

    Objet et classe

    L’autre notion importante qui est inséparable de l’Objet, c’est la notion de classe. L’objet est une instance de classe, plus simplement un exemplaire d’une classe, sa représentation en mémoire. Par conséquent, on déclare comme type une classe, et on déclare des variables de ce type appelées des objets.

    Exemple de classe en Java :
    public class MaClasse{
    ....
    }

    Exemple d’objet (et donc d’instanciation) en Java :
    MaClasse monObject = new MaClasse();

    Les 3 fondamentaux de la POO

    La Programmation Orientée Objet est dirigée par 3 fondamentaux : encapsulation, héritage et polymorphisme.

    Encapsulation
    L’encapsulation permet de faire voir l’objet à l’extérieur comme une boîte noire ayant certaines propriétés (attributs et fonctions) et ayant un comportement spécifié. La manière dont ces propriétés ont été implémentées est alors cachée aux utilisateurs de la classe. L’implémentation peut être modifiée sans changer le comportement extérieur de l’objet. Cela permet donc de séparer la spécification du comportement d’un objet, de l’implémentation pratique de ces spécifications.

    Héritage
    L’héritage, permettant entre autres la réutilisabilité et l’adaptabilité des objets. Ce principe est basé sur des classes dont les "filles" héritent des caractéristiques de leur(s) "mère(s)". Chacune des classes filles peut donc posséder les mêmes caractéristiques que ses classes mères et bénéficier de caractéristiques supplémentaires à celles de ces classes mères. Bien sur, toutes les méthodes de la classe héritée (fille) peuvent être redéfinies. Chaque classe fille peut, si le programmeur n’a pas défini de limitation, devenir à son tour classe mère.

    Polymorphisme
    Cette capacité dérive directement du principe d’héritage vu précédemment. En effet, comme on le sait déjà, un objet va hériter des attributs et méthodes de ses ancêtres. Mais un objet garde toujours la capacité de pouvoir redéfinir une méthode. On voit donc apparaître ici ce concept de polymorphisme : choisir en fonction des besoins quelle méthode ancêtre appeler, et ce au cours même de l’exécution.

    Visibilité

    De par le principe de l’encapsulation, il convient de pouvoir masquer certaines données et méthodes internes les gérant, et de pouvoir laisser visibles certaines autres devant servir à la gestion publique de l’objet. C’est le principe de la visibilité.

    Attributs et méthodes publics
    Les attributs et méthodes dits publics sont accessibles par tous.

    Attributs et méthodes privés
    La visibilité privée restreint la portée d’un attribut ou d’une méthode à l’objet où il ou elle est déclaré(e).

    Attributs et méthodes protégés
    La visibilité protégée correspond à la visibilité privée excepté que tout attribut ou méthode protégé(e) est accessible dans tous les descendants (c’est à dire dans toutes les classes filles).

    Différents types de méthodes

    Voici la description de quelques méthodes particulières à la Programmation Orientée Objet.

    Constructeurs et destructeurs
    Parmi les différentes méthodes d’un objet se distinguent deux types de méthodes bien particulières et remplissant un rôle précis dans sa gestion : les constructeurs et les destructeurs.

    Constructeurs
    Comme leur nom l’indique, les constructeurs servent à construire l’objet en mémoire. Un constructeur va se charger de mettre en place les données, d’associer les méthodes avec les attributs et de créer le diagramme d’héritage de l’objet, autrement dit de mettre en place toutes les liaisons entre les ancêtres et les descendants. Il peut exister en mémoire plusieurs instances d’un même type objet, par contre seule une copie des méthodes est conservée en mémoire, de sorte que chaque instance se réfère à la même zone mémoire en ce qui concerne les méthodes. Bien entendu, les attributs sont distincts d’un objet à un autre.
    Quelques remarques concernant les constructeurs :
    • Un objet peut ne pas avoir de constructeur explicite, il est alors créer par le compilateur.
    • Certains langages (comme le Java) autorise d’avoir plusieurs constructeurs : c’est l’utilisateur qui décidera du constructeur à appeler. Comme pour toute méthode, un constructeur peut être surchargé, et donc effectuer diverses actions en plus de la construction même de l’objet. On utilise ainsi généralement les constructeurs pour initialiser les attributs de l’objet.
    • S’il n’est pas nécessaire de fournir un constructeur pour un objet statique, il devient obligatoire en cas de gestion dynamique, car le diagramme d’héritage ne peut être construit de manière correcte que lors de l’exécution, et non lors de la compilation.
    Destructeurs
    Le destructeur est le pendant du constructeur : il se charge de détruire l’instance de l’objet. La mémoire allouée pour le diagramme d’héritage est libérée. Certains compilateurs peuvent également se servir des destructeurs pour éliminer de la mémoire le code correspondant aux méthodes d’un type d’objet si plus aucune instance de cet objet ne réside en mémoire.
    Quelques remarques sur les destructeurs :
    • Tout comme pour les constructeurs, un objet peut ne pas avoir de destructeur. Une fois encore, c’est le compilateur qui se chargera de la destruction statique de l’objet.
    • Certains langages autorise d’avoir plusieurs destructeurs. Leur rôle commun reste identique, mais peut s’y ajouter la destruction de certaines variables internes pouvant différer d’un destructeur à l’autre. La plupart du temps, à un constructeur distinct est associé un destructeur distinct.
    • En cas d’utilisation dynamique, un destructeur s’impose pour détruire le diagramme créé par le constructeur.

    Méthodes et classes abstraites

    Méthodes abstraites
    Une méthode abstraite est une méthode qu’il est nécessaire de surcharger. Elle ne possède pas d’implémentation. Ainsi, si on tente d’appeler une méthode abstraite, une erreur est déclenchée. Les méthodes abstraites sont généralement utilisées lorsque l’on bâtit un squelette d’objet devant donner lieu à de multiples descendants devant tous posséder un comportement analogue.

    Classe abstraite
    On retrouve le même principe au niveau de la classe. Une classe abstraite ne peut pas être instanciée. Par contre il est possible d’y mélanger des méthodes abstraites et concrète.

    Interface
    Une interface est un cas particulier de la classe abstraite car toutes ces méthodes sont abstraites. Seule l’interface de la classe apparaît.

    Méthode et attribut statique

    Les méthodes et attributs statiques sont dites d’instance ou de classe. Un attribut statique existe dès que sa classe est chargée, en dehors et indépendamment de toute instanciation. Quelque soit le nombre d’instanciation de la classe, un attribut de classe, existe en un et un seul exemplaire.
    Une méthode statique ne doit pas manipuler, directement ou indirectement, d’attributs non statiques de sa classe.

    Pointeur interne

    Il peut se révéler indispensable pour un objet de pouvoir se référencer lui-même. Pour cela, toute instance dispose d’un pointeur interne vers elle-même. Ce pointeur peut prendre différentes appellations. En Java, c++, PHP il s’agira du pointeur "this".