On Github lcottereau / maintainability-slides
Maintenabilité des applications
Qu'est-ce que la maintenabilité ?
Moins de fonctionnalité
private static final long serialVersionUID = 1L;
Sessions web et cookies
/** * */ private static final long serialVersionUID = 1L;
private void setResultCode(int resultOk) { // TODO Auto-generated method stub }
//il affecte au parametre passé dans le query la valeur passée q.setParameter("username", username);
/** * $Id:$ * @author toto */ public int doSomething() { FinalUser user = new FinalUser(); user = em.find(FinalUser.class, userName); /*return newUser.getUserName();*/ return userNName; }
/* * (c) Copyright 2013 Laurent Cottereau * * This file is part of Foobar. * Foobar is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation. * You should have received a copy of the GNU General Public * License along with Foobar. * If not, see <http://www.gnu.org/licenses/>. */ /** * commentaire décrivant le comportement pour qui * ne veut pas lire le code. * TODO penser à implémenter autre chose.
Différences ?
Attention au choix framework/bibliothèque/API
/** * Copyright Sénat. */ package fr.senat.model.dosleg; import fr.senat.model.dosleg.validator.ActiviteValide; import fr.senat.model.senateurs.GroupePolitique; import fr.senat.util.Constants; import java.io.Serializable; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.OrderBy; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; import org.hibernate.annotations.Type; import static org.joda.time.DateTimeConstants.OCTOBER; import org.joda.time.LocalDate; import static org.joda.time.LocalDate.now; /** * Représente une mission de contrôle et d'évaluation du Sénat. Peut être une Mission Commune d'Information, une * commission d'enquête, un contrôle d'application d'une loi, un contrôle de commission permanente, etc... Par défaut, * le contrôle n'est à l'initiative des groupes, ni avec l'aide de la cour des comptes ou clôturé, mais il est considéré * comme avec rapport. Par ailleurs, les organismes, lois, livrables, acteurs et thèmes sont des ensembles vides. */ @Entity @ActiviteValide public class Controle implements Serializable { private static final String FOREIGN_KEY_ID = "CON_ID"; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; @Size(max = 256, message = "trop long.") @Column(name = "LIB", length = 256) @NotNull private String libelle; @Size(max = 2048, message = "trop long.") private String objet; @Pattern(regexp = Constants.URL_PATTERN, message = "pas au bon format (par exemple : http://www.senat.fr/commission/XX/missions_d_information/mission_dinformation_sur_YY.html)") private String url; @NotNull @Column(name = "INITIATIVE_GROUPES") @Type(type = "fr.senat.util.hibernate.usertype.OuiNonSmallType") private boolean initiativeDesGroupes = false; @NotNull @Column(name = "COUR_COMPTES") @Type(type = "fr.senat.util.hibernate.usertype.OuiNonSmallType") private boolean courDesComptes = false; @NotNull @Column(name = "PROGRAMME_CREATION") private int programmeCreation = Controle.getSession(now()); @Column(name = "PROGRAMME_REPORT") private Integer programmeReport; @Column(name = "DATE_CREATION") @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate") private LocalDate dateCreation; @NotNull @Type(type = "fr.senat.util.hibernate.usertype.OuiNonSmallType") private boolean cloture = false; @NotNull @Column(name = "AVEC_RAPPORT") @Type(type = "fr.senat.util.hibernate.usertype.OuiNonSmallType") private boolean avecRapport = true; @Embedded @NotNull private EcheanceControle echeance = new EcheanceControle(); @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "GRPPOL") private GroupePolitique groupePolitique; @ManyToMany @JoinTable(name = "CONTROLE_ORG", joinColumns = @JoinColumn(name = FOREIGN_KEY_ID), inverseJoinColumns = @JoinColumn(name = "ORGCOD")) private Set<Organisme> organismes = new HashSet<Organisme>(); @ManyToMany @JoinTable(name = "CONTROLE_LOI", joinColumns = @JoinColumn(name = FOREIGN_KEY_ID), inverseJoinColumns = @JoinColumn(name = "LOICOD")) private Set<Loi> lois = new HashSet<Loi>(); @OneToMany(orphanRemoval = true, cascade = CascadeType.ALL) @JoinColumn(name = FOREIGN_KEY_ID, nullable = false) private Set<LivrableControle> livrables = new HashSet<LivrableControle>(); @OneToMany(orphanRemoval = true, cascade = CascadeType.ALL) @JoinColumn(name = FOREIGN_KEY_ID, nullable = false) @OrderBy("id asc") private Set<ActeurControle> acteurs = new HashSet<ActeurControle>(); private final java.util.concurrent.AtomicReference<java.lang.Object> themes = new java.util.concurrent.AtomicReference<java.lang.Object>(); public Controle() { } public Integer getId() { return this.id; } public String getLibelle() { return this.libelle; } public String getObjet() { return this.objet; } public String getUrl() { return this.url; } public boolean isInitiativeDesGroupes() { return this.initiativeDesGroupes; } public boolean isCourDesComptes() { return this.courDesComptes; } public int getProgrammeCreation() { return this.programmeCreation; } public Integer getProgrammeReport() { return this.programmeReport; } public LocalDate getDateCreation() { return this.dateCreation; } public boolean isCloture() { return this.cloture; } public boolean isAvecRapport() { return this.avecRapport; } public EcheanceControle getEcheance() { return this.echeance; } public GroupePolitique getGroupePolitique() { return this.groupePolitique; } public Set<Organisme> getOrganismes() { return this.organismes; } public Set<Loi> getLois() { return this.lois; } public Set<LivrableControle> getLivrables() { return this.livrables; } public Set<ActeurControle> getActeurs() { return this.acteurs; } public Set<Theme> getThemes() { java.lang.Object value = this.themes.get(); if (value == null) { synchronized(this.themes) { value = this.themes.get(); if (value == null) { final Set<Theme> actualValue = Cache.getInstance().calculateThemes(); value = actualValue == null ? this.themes : actualValue; this.themes.set(value); } } } return (Set<Theme>)(value == this.themes ? null : value); } public void setId(final Integer id) { this.id = id; } public void setLibelle(final String libelle) { this.libelle = libelle; } public void setObjet(final String objet) { this.objet = objet; } public void setUrl(final String url) { this.url = url; } public void setInitiativeDesGroupes(final boolean initiativeDesGroupes) { this.initiativeDesGroupes = initiativeDesGroupes; } public void setCourDesComptes(final boolean courDesComptes) { this.courDesComptes = courDesComptes; } public void setProgrammeCreation(final int programmeCreation) { this.programmeCreation = programmeCreation; } public void setProgrammeReport(final Integer programmeReport) { this.programmeReport = programmeReport; } public void setDateCreation(final LocalDate dateCreation) { this.dateCreation = dateCreation; } public void setCloture(final boolean cloture) { this.cloture = cloture; } public void setAvecRapport(final boolean avecRapport) { this.avecRapport = avecRapport; } public void setEcheance(final EcheanceControle echeance) { this.echeance = echeance; } public void setGroupePolitique(final GroupePolitique groupePolitique) { this.groupePolitique = groupePolitique; } public void setOrganismes(final Set<Organisme> organismes) { this.organismes = organismes; } public void setLois(final Set<Loi> lois) { this.lois = lois; } public void setLivrables(final Set<LivrableControle> livrables) { this.livrables = livrables; } public void setActeurs(final Set<ActeurControle> acteurs) { this.acteurs = acteurs; } public void setThemes(final Set<Theme> themes) { this.themes = themes; } /** * Renvoie la date à prendre en compte pour le nommage du groupe politique lié à ce contrôle. TODO vérifier cette * règle de gestion avec S. Dubourg. * * @return la date à prendre en compte. */ private LocalDate getDateNommageGroupePolitique() { if (isClosed()) { return echeance.getDate(); } else { return LocalDate.now(); } } /** * Renvoie le libellé de groupe politique à la date adéquate pour ce contrôle, préfixé de l'article adéquat. Ainsi, * un contrôle en cours prendra le nom à la date du jour alors qu'un contrôle fini prendra le nom à la date * d'échéance. * * @return le libellé préfixé de l'article. <code>null</code> si le groupe politique n'est pas défini. */ public String getLibelleLongEtArticleGroupePolitique() { if (groupePolitique != null) { LocalDate d = getDateNommageGroupePolitique(); StringBuilder sb = new StringBuilder(groupePolitique.getArticle(d)); sb.append(" "); sb.append(groupePolitique.getLibelleLong(d)); return sb.toString(); } return null; } /** * Détermine si le contrôle est fini. * * @return <code>true</code> si le contrôle est fini. */ public boolean isClosed() { return echeance != null && echeance.getDate().isBefore(LocalDate.now()); } /** * Reporte d'un an le contrôle. La date de début d'activité est inchangée mais la date de report est décalée d'un an * (année suivant le démarrage si c'est le premier report) */ public void reporter() { if (canReporteControle()) { if (programmeReport == null) { programmeReport = programmeCreation + 1; } else { programmeReport++; } } } /** * Renvoie le dernier programme d'activité du contrôle. * * @return le dernier programme d'activité du contrôle. */ public int getDernierProgramme() { if (programmeReport == null) { return programmeCreation; } else { return programmeReport; } } /** * Indique si un contrôle peut être reporté. C'est le cas si l'échéance correspond à une session strictement * postérieure supérieure à la session de report actuelle. * * @return <code>true</code> si le contrôle peut être reporté. <code>false</code> sinon. */ public boolean canReporteControle() { if (echeance.getDate() != null) { return (getDernierProgramme() < echeance.getSession()); } else { return false; } } /** * Renvoie la session correspondant à une date. * * @param date la date dont on cherche la session. * @return la session, représentée par l'année de démarrage de la session (2013 pour la session 2013-2014 par * exemple). <code>null</code> si la date en paramètre est nulle. */ public static Integer getSession(LocalDate date) { if (date != null) { if (date.getMonthOfYear() < OCTOBER) { return date.getYear() - 1; } else { return date.getYear(); } } else { return null; } } /** * Renvoie l'année de fin d'activité du contrôle. * * @return l'année de fin d'activité. */ public int getFinActivite() { return getDernierProgramme() + 1; } /** * Définit la fin d'activité. Calcule le programme correspondant et définit éventuellement un report sur le * contrôle. * * @param fin l'année de fin d'activité spécifiée dans le formulaire. */ public void setFinActivite(int fin) { if (fin > getProgrammeCreation() + 1) { setProgrammeReport(fin - 1); } else { setProgrammeReport(null); } } @java.lang.Override public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof Controle)) return false; final Controle other = (Controle)o; if (!other.canEqual((java.lang.Object)this)) return false; final java.lang.Object this$id = this.getId(); final java.lang.Object other$id = other.getId(); if (this$id == null ? other$id != null : !this$id.equals(other$id)) return false; final java.lang.Object this$libelle = this.getLibelle(); final java.lang.Object other$libelle = other.getLibelle(); if (this$libelle == null ? other$libelle != null : !this$libelle.equals(other$libelle)) return false; final java.lang.Object this$objet = this.getObjet(); final java.lang.Object other$objet = other.getObjet(); if (this$objet == null ? other$objet != null : !this$objet.equals(other$objet)) return false; final java.lang.Object this$url = this.getUrl(); final java.lang.Object other$url = other.getUrl(); if (this$url == null ? other$url != null : !this$url.equals(other$url)) return false; if (this.isInitiativeDesGroupes() != other.isInitiativeDesGroupes()) return false; if (this.isCourDesComptes() != other.isCourDesComptes()) return false; if (this.getProgrammeCreation() != other.getProgrammeCreation()) return false; final java.lang.Object this$programmeReport = this.getProgrammeReport(); final java.lang.Object other$programmeReport = other.getProgrammeReport(); if (this$programmeReport == null ? other$programmeReport != null : !this$programmeReport.equals(other$programmeReport)) return false; final java.lang.Object this$dateCreation = this.getDateCreation(); final java.lang.Object other$dateCreation = other.getDateCreation(); if (this$dateCreation == null ? other$dateCreation != null : !this$dateCreation.equals(other$dateCreation)) return false; if (this.isCloture() != other.isCloture()) return false; if (this.isAvecRapport() != other.isAvecRapport()) return false; final java.lang.Object this$echeance = this.getEcheance(); final java.lang.Object other$echeance = other.getEcheance(); if (this$echeance == null ? other$echeance != null : !this$echeance.equals(other$echeance)) return false; final java.lang.Object this$groupePolitique = this.getGroupePolitique(); final java.lang.Object other$groupePolitique = other.getGroupePolitique(); if (this$groupePolitique == null ? other$groupePolitique != null : !this$groupePolitique.equals(other$groupePolitique)) return false; final java.lang.Object this$organismes = this.getOrganismes(); final java.lang.Object other$organismes = other.getOrganismes(); if (this$organismes == null ? other$organismes != null : !this$organismes.equals(other$organismes)) return false; final java.lang.Object this$lois = this.getLois(); final java.lang.Object other$lois = other.getLois(); if (this$lois == null ? other$lois != null : !this$lois.equals(other$lois)) return false; final java.lang.Object this$livrables = this.getLivrables(); final java.lang.Object other$livrables = other.getLivrables(); if (this$livrables == null ? other$livrables != null : !this$livrables.equals(other$livrables)) return false; final java.lang.Object this$acteurs = this.getActeurs(); final java.lang.Object other$acteurs = other.getActeurs(); if (this$acteurs == null ? other$acteurs != null : !this$acteurs.equals(other$acteurs)) return false; final java.lang.Object this$themes = this.getThemes(); final java.lang.Object other$themes = other.getThemes(); if (this$themes == null ? other$themes != null : !this$themes.equals(other$themes)) return false; return true; } public boolean canEqual(final java.lang.Object other) { return other instanceof Controle; } @java.lang.Override public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $id = this.getId(); result = result * PRIME + ($id == null ? 0 : $id.hashCode()); final java.lang.Object $libelle = this.getLibelle(); result = result * PRIME + ($libelle == null ? 0 : $libelle.hashCode()); final java.lang.Object $objet = this.getObjet(); result = result * PRIME + ($objet == null ? 0 : $objet.hashCode()); final java.lang.Object $url = this.getUrl(); result = result * PRIME + ($url == null ? 0 : $url.hashCode()); result = result * PRIME + (this.isInitiativeDesGroupes() ? 79 : 97); result = result * PRIME + (this.isCourDesComptes() ? 79 : 97); result = result * PRIME + this.getProgrammeCreation(); final java.lang.Object $programmeReport = this.getProgrammeReport(); result = result * PRIME + ($programmeReport == null ? 0 : $programmeReport.hashCode()); final java.lang.Object $dateCreation = this.getDateCreation(); result = result * PRIME + ($dateCreation == null ? 0 : $dateCreation.hashCode()); result = result * PRIME + (this.isCloture() ? 79 : 97); result = result * PRIME + (this.isAvecRapport() ? 79 : 97); final java.lang.Object $echeance = this.getEcheance(); result = result * PRIME + ($echeance == null ? 0 : $echeance.hashCode()); final java.lang.Object $groupePolitique = this.getGroupePolitique(); result = result * PRIME + ($groupePolitique == null ? 0 : $groupePolitique.hashCode()); final java.lang.Object $organismes = this.getOrganismes(); result = result * PRIME + ($organismes == null ? 0 : $organismes.hashCode()); final java.lang.Object $lois = this.getLois(); result = result * PRIME + ($lois == null ? 0 : $lois.hashCode()); final java.lang.Object $livrables = this.getLivrables(); result = result * PRIME + ($livrables == null ? 0 : $livrables.hashCode()); final java.lang.Object $acteurs = this.getActeurs(); result = result * PRIME + ($acteurs == null ? 0 : $acteurs.hashCode()); final java.lang.Object $themes = this.getThemes(); result = result * PRIME + ($themes == null ? 0 : $themes.hashCode()); return result; } @java.lang.Override public java.lang.String toString() { return "Controle(id=" + this.getId() + ", libelle=" + this.getLibelle() + ", objet=" + this.getObjet() + ", url=" + this.getUrl() + ", initiativeDesGroupes=" + this.isInitiativeDesGroupes() + ", courDesComptes=" + this.isCourDesComptes() + ", programmeCreation=" + this.getProgrammeCreation() + ", programmeReport=" + this.getProgrammeReport() + ", dateCreation=" + this.getDateCreation() + ", cloture=" + this.isCloture() + ", avecRapport=" + this.isAvecRapport() + ", echeance=" + this.getEcheance() + ")"; } }
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.6</version> <scope>provided</scope> </dependency>
SuperHero.builder().name("Superman").from("Krypton").alias("Clark").build();
Lister le maximum de tâches permettant de diminuer la quantité de code sur votre projet
fonctionnalités inutiles code contournant une convention code mal maîtrisé code dupliqué code inutile code à externaliser code "automatique"D'autres s'en préoccupent mieux que vous !
function(a,b,c,d){d+=c;return[d<0|a&b<< d?a=parseInt((a|b<<c).toString(d=32,b=new Date&2|1) .replace('v',''),d):a|b<<d,a,b,d]}—140byt.es
Keep It Simple, Stupid
Calendar c = new GregorianCalendar(); Calendar b = j.bd(); if (b != null && c.get(Calendar.DAY_OF_YEAR) == b.get(Calendar.DAY_OF_YEAR)) { return new BD(); }
if (joe.hasBirthday()) { BandeDessinee gift = new BandeDessinee("Lincoln"); return gift; }
when(joe.hasBirthday()).thenSend(gift);
$ git log --pretty=oneline --abbrev-commit 5b5be75 getIdClient 458ce6b corrections 59ba74e getIdClient 5292c95 corrections 851b58e merge 4020e4f Supprimer et Ajouter avec corrections c89ad42 Supprimer et Ajouter avec corrections
231195a crebas.sql représente maintenant l'état de la dernière version de la base 31c15dd #1996 - léger espace autour d'une image dans un datatable-ui e0b5cf9 suppression de l'onglet contexte (élément mis dans l'onglet détails)
Simple – Court – Facile
Point d'entrée unique
On change les mainteneurs sur les projets !
Installez le projet en local Faites une modification mineure Testez, Packagez, Diffusez Notez vos conseils d'amélioration
Note : Foo() in interface FooBase has been deprecated. Note : Foo.java uses unchecked or unsafe operations.
javac -nowarn javac -Xlint -Werror
Changer la structure sans changer le fonctionnel
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
<properties> <maven.compiler.source>1.6</maven.compiler.source> <maven.compiler.target>${maven.compiler.source}</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> (...) </properties>
Aperçu des méthodes pour externaliser : variables d'environnements, fichiers à un endroit fixe, ...
tests nécessitant une BD ?
platform-dépendant
apprentissage, mentoring, discipline, passion
dans Refactoring: Improving the Design of Existing Code