Dati membri facoltativi

2

Sto creando un strong legame con una specifica XML e sto essenzialmente cercando di "appiattire" le specifiche il più possibile, in modo che non sembrino come se stessi manipolando un albero XML.

Ci sono molti elementi nelle specifiche XML che sono opzionali. Ecco un esempio forzato.

<person>
   <name>Fred</name>
   <favorite-color>Blue</favorite-color>
</person>

In questo potrebbe essere richiesto l'elemento "nome", ma l'elemento "colore preferito" potrebbe dire minOccurs = 0 in xsd rendendolo opzionale.

Ho due idee su come gestirlo, nessuna delle due sembra particolarmente elegante.

Nella versione 1 è necessario testare nullptr prima del dereferenziamento di getFavoriteColor per vedere se FavoriteColor viene utilizzato dall'oggetto Person. Questo approccio sembra un pessimo approccio perché rende incredibilmente facile bloccare il programma, soprattutto perché potrebbe essere difficile tenere traccia di quali membri sono facoltativi e quali sono richiesti. Si può finire per dover testare tutto per null tutto il tempo. Questo sembra terribile.

Nella versione 2 si può presumere che i getter non restituiranno nullptr. È necessario controllare il bool "HasFavoriteColor" per scoprire se esiste o meno FavoriteColor. Ma il compromesso è che sembra violare la regola della meno sorpresa. È possibile impostare FavoriteColor ("Blue") quindi essere sorpreso quando l'output XML non mostra Blue perché si è dimenticato di impostareHasFavoriteColor (true).

Quale di questi disegni sembra migliore, o almeno più idiomatico? C'è una soluzione migliore?

Ricerca: è simile ma non si adatta al link Questo è simile, ma ancora non sembra adattarsi Verifica della presenza di proprietà facoltative di un oggetto

Inoltre, ho scoperto che boost: opzionale esiste, ma non sembra un adattamento e non sto usando nulla tranne std e STL per il mio progetto.

(Supponiamo che "Name" e "FavoriteColor" qui sotto siano classi utente e non solo typedefs di std :: string.)

using Name = std::string;
using NamePtr = std::shared_ptr<Name>;

using FavoriteColor = std::string;
using FavoriteColorPtr = std::shared_ptr<FavoriteColor>;

/* Version 1: nullptr indicates FavoriteColor is absent,
 but Name will never be null because it is required */
class Person
{
public:
    Person()
    :myName( std::make_shared<Name>() )
    ,myFavoriteColor()
    {}

    NamePtr getName() const { return myName; }
    void setName( const NamePtr& value )
    {
        if( value )
        {
            myName = value;
        }
    }
    FavoriteColorPtr getFavoriteColor() const { return myFavoriteColor; }
    void setFavoriteColor( const FavoriteColorPtr& value ) { myFavoriteColor = value; }
private:
    NamePtr myName;
    FavoriteColorPtr myFavoriteColor;
};

/* Version 2: FavoriteColor and Name can both
 be trusted to not be null, but you have to
 check HasFavoriteColor bool to see whether
 the optional data is legit */
class Person2
{
public:
    Person2()
    :myName( std::make_shared<Name>() )
    ,myFavoriteColor( std::make_shared<FavoriteColor>() )
    {}

    NamePtr getName() const { return myName; }
    void setName( const NamePtr& value )
    {
        if( value )
        {
            myName = value;
        }
    }
    FavoriteColorPtr getFavoriteColor() const { return myFavoriteColor; }
    void setFavoriteColor( const FavoriteColorPtr& value )
    {
        if ( value )
        {
            myFavoriteColor = value;
        }
    }
    bool getHasFavoriteColor() const { return myHasFavoriteColor; }
    void setHasFavoriteColot( const bool value ) { myHasFavoriteColor = value; }
private:
    NamePtr myName;
    FavoriteColorPtr myFavoriteColor;
    bool myHasFavoriteColor;
};
    
posta Matthew James Briggs 19.03.2015 - 05:02
fonte

2 risposte

2

Entrambi i tuoi progetti hanno il problema che hanno messo l'onere di tenere traccia della validità dell'attributo favoriteColor sull'utente della classe. Il tuo secondo progetto (con getHasFavoriteColor ) ha il problema aggiuntivo di duplicare le informazioni se esiste un valore valido per favoriteColor in un modo che faciliti la creazione di incoerenze.

Dei due progetti che hai, il primo è quello più idiomatico.
Alcune altre possibilità sono:

  • Aggiungi un membro bool hasFavoriteColor() const { return myFavoriteColor != NULL; } . Rende il controllo di NULL migliore nel codice client, ma non è poi così diverso.
  • Potresti avere uno speciale oggetto "vuoto" FavoriteColor che viene restituito quando l'utente non ha un colore preferito. In questo modo non dovrai mai restituire un puntatore NULL.
risposta data 19.03.2015 - 08:42
fonte
0

Non conosco il C ++, ma spero che la mia idea ti aiuti a risolvere il tuo problema.

Crea la tua classe del modello in base al tuo file XSD .

class Person
{ 
   private string name;
   private string favoritColor;

  public Person (XmlElement person)
  {
    // parse the XML element and assign the values to appropriate element
    // if the element does not exist, don't assign the values to its equivalent element
  }

  public string GetName()
  {
     return name;
  }

  public bool HasFavoriteColor()
  {
     if (favoritColor ! = null)
     {
       return true;
     }
     return false;
  }

  public string GetFavoriteColor()
  {
    return favoritColor;
  }

}
    
risposta data 19.03.2015 - 06:28
fonte

Leggi altre domande sui tag