MVC + Exception

Résolu/Fermé
mikis69 Messages postés 168 Date d'inscription mardi 26 novembre 2013 Statut Membre Dernière intervention 11 février 2019 - 2 mars 2014 à 13:59
mikis69 Messages postés 168 Date d'inscription mardi 26 novembre 2013 Statut Membre Dernière intervention 11 février 2019 - 2 mars 2014 à 23:44
Bonjour à tous et à toutes !

Je suis étudiants en deuxième informatique et j'apprécie vraiment le cours de java.

Je voulais savoir si certains d'entre vous ont un bon niveau dans les exceptions et le modèle vue controleur ?
Car j'ai fait un projet netbeans : à l'éxecution tout fonctionne bien mais niveau du code, j'aimerais que vous me disiez si c'est bien coder ou si j'avais pu faire autrement :)

Merci pour vos critiques et bonne journée..


LES CODES

1. LA CLASSE CLIENT

package LibrairieException;

import java.util.Objects;

public class Client {
String nom;
String prenom;
private String motPasse;
String email;
CarteBancaire carte;
Adresse facturation;

public Client() {
this.nom ="";
this.prenom ="";
this.motPasse = "";
this.email ="";
}
public Client(String nom, String prenom, String motPasse, String email, Adresse facturation) throws Exception {
if(email.trim().equals(""))throw new Exception("\nemail vide\n");
if(motPasse.trim().equals(""))throw new Exception("\nmot de passe vide\n"); // TRIM() correspond à quoi ?
this.nom = nom;
this.prenom = prenom;
this.motPasse = motPasse;
this.email = email;
this.facturation = facturation;
}

public CarteBancaire getCarte() {
return carte;
}

public void setCarte(CarteBancaire carte) {
this.carte = carte;
}

public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}

public Adresse getFacturation() {
return facturation;
}

public void setFacturation(Adresse facturation) {
this.facturation = facturation;
}

public String getMotPasse() {
return motPasse;
}

public void setMotPasse(String motPasse) {
this.motPasse = motPasse;
}

public String getNom() {
return nom;
}

public void setNom(String nom) {
this.nom = nom; }

public String getPrenom() {
return prenom;
}

public void setPrenom(String prenom) {
this.prenom = prenom;
}

@Override
public String toString() {
return "\nClient : " + "\nNom = " + nom + ", Prenom = " + prenom + ", Email = " + email;
}

@Override
public boolean equals(Object autre){ // Redefinition de la méthode equals
if(autre==null) {
return false;
}
if( !(autre instanceof Client)) {
return false;
}
Client c =(Client)autre ;
if((this.email.equals(c.email))) {
return true;
}
else {
return false;
}
}

@Override
public int hashCode() {
int hash = 3;
hash = 37 * hash + Objects.hashCode(this.email);
return hash;
}

}

2. LE MODELE

package LibrairieException;

import java.util.*;

public class LibrairieModele {
private HashSet <Client> listeClient= listeClient = new HashSet<Client>();

public LibrairieModele() {
}

public void ajoutClient(Client c) throws Exception{
if(c==null) throw new Exception("\nclient inexistant\n");
boolean ok = listeClient.add(c); // Ajoute le client c, seulement s'il n'est pas déjà présent dans la HashSet ?
if(!ok) throw new Exception("\nclient déjà existant\n");
}

public Client rechercheClient(String email, String motPasse) throws Exception{
Client recherche=null;

for(Client c :listeClient){
if(email.equals(c.getEmail())&&motPasse.equals(c.getMotPasse())) recherche = c; // Ici, on ne doit pas mettre tout les résultats dans une arraylist puisqu'il n'y a qu'un seul client avec ce mail ?
}

if(recherche!=null) return recherche;
else throw new Exception("\nClient inexistant\n");
}

public void rechercheCarteBancaire(Client c) throws Exception {
if(c.getCarte()!=null) throw new Exception("\nVous possédez déjà une carte bancaire\n"); // Si le client n'a pas encore de carte, retourne null
}

public CarteBancaire afficheCarteBancaire(Client c) throws Exception {
if(c.getCarte()!=null) return c.getCarte();
else throw new Exception("\nVous n'avez pas encore de carte bancaire\n");
}

public HashSet<Client> getClient() {
return listeClient;
}

}

3. LE CONTROLEUR

package LibrairieException;

import static java.lang.System.exit;

public class LibrairieController {
private LibrairieVue v;
private LibrairieModele m;

public LibrairieController(LibrairieModele m, LibrairieVue v){
this.v = v;
this.m = m;
}

public void menu() {
int choix;
boolean ok;

do { // POUR LE MENU
choix = 0;
ok = false;
v.afficheMessage("\n----------------------------\n MENU \n----------------------------\n");
do { // CONTROLE EXCEPTION
v.afficheMessage("1.Ajout Client"+" 2.Ajout Carte Bancaire"+" 3.Afficher vos données clients"+" 4.Quitter : ");
try {
choix = Integer.parseInt(v.getMessage());
ok = true;
}
catch (NumberFormatException e){}
} while(choix<1||choix>4||!ok);

switch(choix){
case 1 : ajoutClient(); break;
case 2 : ajoutCarteBancaire(); break;
case 3 : afficheDonneesClient(); break;
case 4 : exit(0); break;
}

} while(choix!=4);
}

public void ajoutClient() {
v.afficheMessage("\n----------------------------\n CLIENT \n----------------------------\n");

String nom = v.getMessage("Entrez nom du client : ");
String prenom = v.getMessage("Entrez le prénom du client : ");
String mdp = v.getMessage("Entrez le mot de passe du client : ");
String email = v.getMessage("Entrez l'email du client : ");

Adresse a = creerAdresse(); // On crée l'adresse de facturation

try {
Client c = new Client(nom,prenom,mdp,email,a); // On crée le client en lui affectant son adresse
m.ajoutClient(c);
} catch(Exception e) {
v.afficheMessage(e.getMessage());
}
}

public Adresse creerAdresse() {
Adresse a;

v.afficheMessage("\n----------------------------\n ADRESSE \n----------------------------\n");

v.afficheMessage("Entrez le nom de l'adresse : ");
String nom = v.getMessage();
v.afficheMessage("Entrez le prenom de l'adresse : ");
String prenom = v.getMessage();
v.afficheMessage("Entrez le numéro de l'adresse : ");
String numero = v.getMessage();
v.afficheMessage("Entrez la rue de l'adresse : ");
String rue = v.getMessage();

a = new Adresse(nom,prenom,numero,rue);

return a;
}

public void ajoutCarteBancaire() {
// On regarde si l'identification est correcte. Si oui, on retourne le client concerné.
Client c = identification();
if(c!=null) { // OBLIGATOIRE ? CAR SI J ENLEVE CETTE CONDITION, lorsque je voudrais ajouter une carte banquaire d'un client inexistant (tapez 2 au menu), le programme affichera client inexistant + null.
// Or ici, avec la condition, il n'affiche que client inexistant, ce qui est correct !
try {
m.rechercheCarteBancaire(c); // Si la carte du client est null, ça continue, si pas exception
CarteBancaire cb = creerCarteBancaire(c); // On crée la carte
c.setCarte(cb); // On l'affecte au client concerné
} catch(Exception e) {
v.afficheMessage(e.getMessage());
}
}
}

public Client identification() {
Client c = null;

v.afficheMessage("\n----------------------------\n IDENTIFICATION \n----------------------------\n");

String email = v.getMessage("Entrez votre email : ");
String motPasse = v.getMessage("Entrez votre mot de passe : ");

try {
c = m.rechercheClient(email,motPasse);
}
catch (Exception e) {
v.afficheMessage(e.getMessage());
}

return c;
}

public CarteBancaire creerCarteBancaire(Client c) {
v.afficheMessage("\n----------------------------\n CARTE BANCAIRE \n----------------------------\n");

String type = v.getMessage("Entrez le type de votre carte : ");
String numero = v.getMessage("Entrez le numéro de votre carte : ");
String date = v.getMessage("Entrez la date de validité de votre carte : ");

CarteBancaire cb = new CarteBancaire(type,numero,date,c);

return cb;
}

public void afficheDonneesClient() {
Client c = identification(); // Si identification est correcte, on retourne le client concerné

if(c!=null) affiche(c); // Peut on faire autrement que de mettre le if(c!=null) ici ?
}

public void affiche(Client c) {
v.afficheMessage(""+c);
v.afficheMessage(""+c.getFacturation());

try {
CarteBancaire cb = m.afficheCarteBancaire(c);
v.afficheMessage(""+cb);
} catch(Exception e) {
v.afficheMessage(e.getMessage());
}
}

}

Est ce que mon modèle et mon controleur gèrent bien les exceptions etc ?

1 réponse

KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
2 mars 2014 à 14:32
     public Client(String nom, String prenom, String motPasse, String email, Adresse facturation) throws Exception { 
if(email.trim().equals(""))throw new Exception("\nemail vide\n");
if(motPasse.trim().equals(""))throw new Exception("\nmot de passe vide\n"); // TRIM() correspond à quoi ?
this.nom = nom;
this.prenom = prenom;
this.motPasse = motPasse;
this.email = email;
this.facturation = facturation;
}

"TRIM() correspond à quoi ?"
C'est ton code, c'est donc à toi de le savoir, ou alors ne l'utilises pas...

En terme d'exception faire un throws Exception c'est un peu vague, il est conseillé d'utiliser des types d'exceptions aussi précis que possible.

De plus il faut savoir que les RuntimeException (et leurs classes filles) n'ont pas besoin d'être try/catché ce qui en fait une bonne exception pour éviter d'avoir des throws partout où en n'a pas réellement besoin.

Attention aussi à la gestion des paramètres qui peuvent potentiellement être null, et qui vont générer des NullPointerException si tu n'y prêtes pas attention. Il vaut donc mieux interdire le passage de null avec un IllegalArgumentException plutôt que de continuer ton code avec une valeur null qui va planter à la première méthode qui l'appellera...

Enfin, pas de \n dans un message d'exception, ça n'a pas de sens.

Remarques :

equals("")
peut se simplifier avec
isEmpty()
.
Si tu as fait un trim sur email, autant le propager sur this.email

public Client(String nom, String prenom, String motPasse, String email, Adresse facturation)
{
    if (nom==null) throw new IllegalArgumentException("nom ne doit pas être null");
    if (prenom==null) throw new IllegalArgumentException("prenom ne doit pas être null");
    if (motPasse==null) throw new IllegalArgumentException("motPasse ne doit pas être null");
    if (email==null) throw new IllegalArgumentException("email ne doit pas être null");
    if (facturation==null) throw new IllegalArgumentException("facturation ne doit pas être null");
    
    this.nom = nom;
    this.prenom = prenom;
    
    this.motPasse = motPasse.trim();
    if (this.motPasse.isEmpty()) throw new IllegalArgumentException("motPasse ne doit pas être vide");
    
    this.email = email.trim();
    if (this.email.isEmpty()) throw new IllegalArgumentException("email ne doit pas être vide");
    
    this.facturation = facturation;
    // this.carte = ???
}


Bref, pour les exceptions, c'est à revoir.

Pour le modèle MVC j'ai l'impression que tu confonds qui fait quoi.
Ta classe Client c'est le modèle, ta classe LibrairieModele c'est le contrôleur, et ta classe LibrairieController c'est la vue... Donc à revoir aussi !
2
mikis69 Messages postés 168 Date d'inscription mardi 26 novembre 2013 Statut Membre Dernière intervention 11 février 2019
2 mars 2014 à 15:03
Bonjour,

D'abord merci pour ta réponse, je regarde à ce que tu as dit.. Je tiens compte dans mes codes mais j'ai quelques questions donc..

Les exceptions ont des noms et c'est mieux de dire throw new (le nom de l'exception) plutôt que throw new Exception("..."); tout court
Genre throw new NumberFormatException("Il faut entrer un int et non un String"); ?

Après, tu m'as aussi dit que : "Si tu as fait un trim sur email, autant le propager sur this.email " ca revient à faire quoi ? A quoi sert ce passage du code ?

if (nom==null) throw new IllegalArgumentException("nom ne doit pas être null"); Comment un nom peut etre null, si ce n'est pas un objet mais juste une variable de type String ?

Aussi, tu me dis que je confond.. Que client = le modèle, le modèle le controleur, le controleur la vue..
Qu'est ce que tu met toi par exemple dans la modèle ? Parce que moi l'on m'a dit que le modèle est ce qui gère les données.. La vue affiche mais ne peut pas controler..

Merci de tes réponses et bonne journée !
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
2 mars 2014 à 15:30
Les exceptions ont des noms et c'est mieux de dire throw new (le nom de l'exception) plutôt que throw new Exception("..."); tout court
Ce n'est pas une question de nom, mais une question de sens donné à l'excpetion.
Toutes les exceptions générées à cause d'un mauvais argument au passage d'une méthode devraient être IllegalArgumentException, comme c'est le cas ici pour ton constructeur.
Si tu mets juste Exception, c'est trop vague, car c'est la classe mère de toutes les exceptions, on sait qu'il y a un problème mais on ne sait pas lequel.

Pour ton exemple throw new NumberFormatException("Il faut entrer un int et non un String");
En en réalité si la cause du problème c'est que l'on a entré un String au lieu d'un entier, c'est plutôt un IllegalArgumentException, le NumberFormatException est plutôt lié à une erreur de type on voulait bien avoir un String comme paramètre, mais il devait représenté un entier et on a pas réussi à le convertir.

En réalité il est tout à fait possible d'avoir les deux cas de figures avec une méthode qui renvoie les deux types d'exceptions selon le déroulement de la méthode. Cela permet ensuite d'avoir un try/catch assez fin, en faisant le filtrage soit sur IllegalArgumentException, soit sur NumberFormatException , soit les deux, pour distinguer les différents cas d'erreurs possibles.
Mais si tu renvois toujours Exception, on ne peut pas faire la distinction, c'est donc inutilisable.

"Si tu as fait un trim sur email, autant le propager sur this.email " ca revient à faire quoi ? A quoi sert ce passage du code ?
trim permet d'enlever les espaces au début et à la fin de la chaîne de caractères, par exemple
"  toto  ".trim()
donne
"toto"
. Ce que tu fais c'est donc enlever les espaces inutiles pour regarder si le résultat est vide (c'est à dire qu'il n'y avait que des espaces). Moi ce que je dis c'est que si tu as déjà enlevé les espaces pour regarder si c'était vide, autant conserver la chaîne de caractères sans les espaces (
"toto"
) alors qu'avec ton code tu aurais conservé
"  toto  "
...

if (nom==null) throw new IllegalArgumentException("nom ne doit pas être null"); Comment un nom peut etre null, si ce n'est pas un objet mais juste une variable de type String ?
Il suffit de faire ça :
Client client = new Client(null, null, null, null, null);

Pour l'instant tu manipules principalement des données lues au clavier, mais ça c'est dans ta vue. Au niveau de ton modèle tu n'en sais rien. Si tu réutilises ton modèle pour pouvoir être utilisé depuis une base de données par exemple, tu peux rapidement te retrouver avec des NULL.
Il vaut donc mieux les détecter comme interdit, plutôt que de les autoriser, et que ça fasse planter le premier appel de méthode sur l'attribut. Par exemple motPasse.trim() avec motPasse==null ça va provoquer un NullPointerException. Or un IllegalArgumentException maîtrisé a plus de sens qu'un NullPointerException généré automatiquement.

tu me dis que je confond.. Que client = le modèle, le modèle le controleur, le controleur la vue.
Le modèle gère les données. Ici les données c'est tes classes Client, Adresse, CarteBancaire...
Le contrôleur manipule les données. Ce sont donc les méthodes d'ajout de client, de recherche...
La vue c'est l'interface utilisateur, c'est à dire les méthodes affiche, menu, etc.

Ce n'est pas du tout ce que tu as fait...
0
mikis69 Messages postés 168 Date d'inscription mardi 26 novembre 2013 Statut Membre Dernière intervention 11 février 2019
2 mars 2014 à 16:54
Merci pour tes remarques..

Je voulais savoir en plus, est ce qu'il existe un moyen pour afficher les différents messages d'exceptions ?
Du genre :
if (nom==null) throw new IllegalArgumentException("nom ne doit pas être null");
if (prenom==null) throw new IllegalArgumentException("prenom ne doit pas être null");
if (motPasse==null) throw new IllegalArgumentException("motPasse ne doit pas être null");
if (email==null) throw new IllegalArgumentException("email ne doit pas être null");
if (facturation==null) throw new IllegalArgumentException("facturation ne doit pas être null");

Si le nom est null, ceci apparait nom ne doit pas être null
Si c'est le prenom, ceci apparait prenom ne doit pas etre null

Mais si c'est le nom, prenom, motPasse qui sont null, seulement ce message apparait : nom ne doit pas etre null

Comment faire pour que les trois messages s'affichent ? nom ne doit pas etre null, prenom ne doit pas etre null, motPasse ne doit pas etre null

Faut il créer des exceptions personnalisées ? Du style : nomException, prenomException ?
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
2 mars 2014 à 17:28
Oui tu pourrais faire une exception personnalisée du genre :

public class DataModelException extends IllegalArgumentException
{
    private static final long serialVersionUID = 1; // for serialization

    private final Map<String,String> wrongDatas;
    
    public DataModelException(Map<String,String> wrongDatas, String message)
    {
        super(message);
        this.wrongDatas = wrongDatas;
    }
    
    public DataModelException(Map<String,String> wrongDatas, String message, Throwable cause)
    {
        super(message,cause);
        this.wrongDatas = wrongDatas;
    }
    
    public DataModelException(Map<String,String> wrongDatas, Throwable cause)
    {
        super(cause);
        this.wrongDatas = wrongDatas;
    }
    
    public Map<String,String> getWrongDatas()
    {
        return Collections.unmodifiableMap(wrongDatas);
    }
    
    @Override
    public String toString()
    {
        return String.format("%s %s",super.toString(),String.valueOf(wrongDatas));
    }
}

Par exemple :

public Client(String nom, String prenom, String motPasse, String email, Adresse facturation) throws DataModelException
{
   Map<String,String> wrongDatas = new TreeMap<String,String>();
       
   if (nom==null)
       wrongDatas.put("nom", "is null");
   else
       this.nom=nom;
   
   if (prenom==null)
       wrongDatas.put("prenom", "is null");
   else
       this.prenom=prenom;

   if (motPasse==null)
       wrongDatas.put("motPasse","is null");
   else
   {
       this.motPasse = motPasse.trim();
       if (this.motPasse.isEmpty())
           wrongDatas.put("motPasse","is empty");
   }

   if (email==null)
       wrongDatas.put("email","is null");
   else
   {
       this.email = email.trim();
       if (this.email.isEmpty())
           wrongDatas.put("email","is empty");
   }
   
   if (facturation==null)
       wrongDatas.put("facturation", "is null");
   else
       this.facturation=facturation;
   
   if (!wrongDatas.isEmpty())
       throw new DataModelException(wrongDatas,"can't initialize Client");
}

new Client(null, null, "", "", null);
// Exception in thread "main" DataModelException: can't initialize Client {email=is empty, facturation=is null, motPasse=is empty, nom=is null, prenom=is null}

Cependant cette gestion d'exception je la mettrais plutôt côté vue, au moment de remplir un formulaire par exemple. Mais côté modèle je considère comme acquis que les vérifications d'usages ont déjà été faites côté vue, et que le passage de mauvais paramètres dans le modèle relève de l'erreur de codage.
0
mikis69 Messages postés 168 Date d'inscription mardi 26 novembre 2013 Statut Membre Dernière intervention 11 février 2019
2 mars 2014 à 17:43
Ok pour les codes, j'ai bien compris la façon de faire, c'est cool !

Mais pour ton explication c'est moins.. claire je vais dire

Toi tu mettrais quoi côté vue ? ce que l'on met dans la classe client ? Ainsi d'abord on vérifie à l'aide de la vue ? (Mais la vue ne permet pas de faire des controles et donc pas de conditions dans une vue n'est ce pas ?)

Je ne comprend pas encore trop bien le concept de MVC apparemment :(
0