2

J'ai deux fichiers csv A et B. A est le référentiel maître. Je dois lire ces fichiers, mapper les enregistrements de B vers A et enregistrer les enregistrements mappés dans un autre fichier. La classe à détenir des enregistrements est, disons Record. La classe pour stocker les enregistrements correspondants est, disons, RecordMatch.Conception orientée objet

class Record 
{ 
    string Id; 
    string Name; 
    string Address; 
    string City; 
    string State; 
    string Zipcode; 
} 

class RecordMatch 
{ 
    string Aid; 
    string AName; 
    string Bid; 
    string BName; 
    double NameMatchPercent; 
} 

Le scénario de cartographie va ainsi: Tout d'abord, contre chaque enregistrement de B, les dossiers de A sont filtrés à l'aide d'État, ville puis code postal. Les enregistrements de A ainsi filtrés sont ensuite comparés avec l'enregistrement de B. Cette comparaison est entre le champ de nom, et est une comparaison de meilleur appariement en utilisant un algorithme de chaîne floue. La meilleure correspondance est sélectionnée et enregistrée.

L'algorithme de correspondance de chaîne donnera un pourcentage de correspondance. Ainsi, le meilleur résultat de tous les matchs doit être sélectionné. Maintenant que j'ai essayé de mon mieux pour expliquer le scénario, j'aborderai le problème de conception. Ma conception initiale était de faire une classe Mapper, qui sera quelque chose comme ci-dessous:

class Mapper 
{ 
    List<Record> ReadFromFile(File); 
    List<Record> FilterData(FilterType); 
    void Save(List<Record>); 
    RecordMatch MatchRecord(Record A, Record B); 
} 

Mais en regardant la conception, il semble simplement être une enveloppe de classe sur certaines méthodes. Je ne vois aucun design OO dedans. J'ai également senti que Match() appartient plus à la classe Record qu'à la classe Mapper.

Mais d'un autre regard, j'ai vu la classe comme implémentant quelque chose ressemblant à un modèle de Repository.

Une autre façon de penser est de garder la classe Mapper, et il suffit de déplacer la méthode match() à la classe Record, quelque chose comme ceci:

class Mapper 
{ 
    List<Record> ReadFromFile(File); 
    List<Record> FilterData(FilterType); 
    void Save(List<Record>); 
} 

class Record 
{ 
    string id; 
    string name; 
    string address; 
    // other fields; 

    public RecordMatch Match (Record record) 
    { 
    // This record will compare the name field with that of the passed Record. 
    // It will return RecordMatch specifyin the percent of match. 
    } 
} 

Maintenant, je suis totalement confus dans ce scénario simple. Quel serait idéalement un bon design OO dans ce scénario?

Répondre

1

J'ai fait un essai. Il n'y a pas grand-chose que vous puissiez faire quand il s'agit de principes OO ou de modèles de design, sauf peut-être en utilisant la composition pour l'algorithme Matching (et peut-être la stratégie et le modèle si nécessaire). Voici ce que j'ai concocté:

class Mapper { 
     map(String fileA, String fileB, String fileC) { 
      RecordsList a = new RecordsList(fileA); 
      RecordsList b = new RecordsList(fileB); 
      MatchingRecordsList c = new MatchingRecordsList(); 

      for(Record rb : b) { 
       int highestPerc = -1; 
       MatchingRecords matchingRec; 

       for(Record ra : a) { 
        int perc; 
        rb.setMatchingAlgorithm(someAlgorithmYouVeDefined); 
        perc = rb.match(ra); 
        if(perc > highestPerc) { 
         matchingRec = new MatchingRecords(rb, ra, perc); 
        } 
       } 

       if(matchingRec != null) { 
        c.add(matchingRec); 
       } 
      } 

      c.saveToFile(fileC); 
     } 
    } 

    class MatchingAlgorithm { 
     int match(Record b, Record a) { 
      int result; 
      // do your magic 
      return result; 
     } 
    } 

    class Record { 
     String Id; 
     String Name; 
     String Address; 
     String City; 
     String State; 
     String Zipcode; 

     MatchingAlgorithm alg; 

     setMatchingAlgorithm(MatchingAlgorithm alg) { 
      this.alg = alg; 
     } 

     int match(Record r) { 
      int result; -- perc of match 
      // do the matching by making use of the algorithm 
      result = alg.match(this, r); 
      return result; 
     } 

    } 

    class RecordsList implements List<Record> { 
     RecordsList(file f) { 
      //create list by reading from csv-file) 
     } 
    } 

    class MatchingRecords { 
     Record a; 
     Record b; 
     int matchingPerc; 

     MatchingRecords(Record a, Record b, int perc) { 
      this.a = a; 
      this.b = b; 
      this.matchingPerc = perc; 
     } 
    } 

    class MatchingRecordsList { 
     add(MatchingRecords mr) { 
      //add 
     } 

     saveToFile(file x) { 
      //save to file 
     } 
    } 

(Ce qui est écrit dans le Bloc-notes ++ donc il peut y avoir des fautes de frappe, etc, et aussi les classes proposées peuvent certainement bénéficier d'un peu plus refactoring mais je vais laisser si vous choisissez d'utiliser cette disposition.)

+0

Après avoir affiché cette question, j'ai commencé brainstorming par moi-même que je ne ai pas eu de réponse pendant quelques heures: P je suis venu avec un design tout à fait semblable à la vôtre; vous avez ajouté les pièces manquantes à mes idées. :) –

+0

Oh et moi n'étions pas prêts à bourrer un motif de design dans ça; c'était juste que j'ai vu à tort quelque chose de similaire au modèle de dépôt (lire, trouver/filtrer, enregistrer des opérations, vous voyez) dans la conception. Donc je viens de le mentionner. Mais je vois que c'était en effet quelque chose que je fabriquais; Je vais passer un peu d'argent sur « Gang Of Four » maintenant ;-) –

4

Assez étonnamment, je travaille sur un projet presque exactement comme ça en ce moment.

Réponse facile: Ok, tout d'abord, ce n'est pas la fin du monde si une méthode est dans la mauvaise classe pendant un moment! Si vous avez toutes vos classes couvertes par des tests, la vie des fonctions est importante, mais peut être changée avec fluidité comme vous, le roi de votre domaine, le juge bon.

Si vous êtes pas tester cela, eh bien, ce serait ma première suggestion. Beaucoup de gens plus intelligents que moi ont remarqué comment TDD et les tests peuvent aider à amener vos classes à la meilleure conception naturellement. Plutôt que de chercher des motifs à appliquer à un dessin, j'aime penser comme ça: quelles sont les raisons pour lesquelles chacune de vos classes doit changer?Si vous séparez ces raisons les unes des autres (ce que TDD peut vous aider à faire), alors vous commencerez à voir les modèles de conception émerger naturellement de votre code.

Voici quelques raisons de changer que je pouvais penser à quelques passes de lecture à travers votre question:

  1. Le fichier de données change le format/ajoute des colonnes
  2. Vous trouverez un algorithme meilleure correspondance, ou: " maintenant, nous voulons filtrer sur le numéro de téléphone cellulaire trop »
  3. Vous êtes invité à le faire correspondre xml/yaml/etc fichiers ainsi
  4. Vous êtes invité à enregistrer dans un nouveau format/emplacement

Ok, donc, si la mise en œuvre de tout ceux qui vous ferait besoin d'ajouter une « instruction if » quelque part, alors peut-être c'est une couture pour une mise en œuvre des sous-classes d'une interface commune.

De plus, disons que vous voulez enregistrer le fichier créé dans un nouveau lieu. C'est une raison de changer, et ne devrait pas chevaucher avec vous ayant besoin de changer votre stratégie de fusion. Si ces deux parties sont dans la même classe, cette classe a maintenant deux responsabilités, et cela viole le single responsibility principle.

Ainsi, c'est un exemple très bref, d'aller plus loin en profondeur avec une bonne conception orientée objet, consultez la SOLID principles. Vous ne pouvez pas vous tromper avec l'apprentissage de ceux-ci et en cherchant à les appliquer avec prudence tout au long de vos conceptions OO.

+1

sonne comme une bonne stratégie (sans jeu de mots ;-) – Wivani

+1

Haha, sont funs punny – Steve

+0

J'ai reçu un beau soulagement de votre réponse facile pour ne pas se soucier les choses vont mal pendant un moment ;-) Et oui, je suis en train de tester les cours; c'est peut-être pourquoi des doutes ont surgi dans mon esprit. –

Questions connexes