2 votes

Dois-je créer une classe distincte pour cela ?

Mon projet contient un grand nombre de classes, dont plusieurs peuvent être décrites par des fichiers XML. Ne vous inquiétez pas, ce n'est pas la logique ou l'implémentation en XML. Il s'agit d'un jeu, et un exemple serait qu'une tuile de jeu peut être définie en XML, le fichier image, les images d'animation, etc.

Je vais finir par avoir un tas de fonctions qui ressemblent à ceci :

public static Foo FromXml(ref XmlTextReader reader) { ... }

La question est la suivante : ces fonctions doivent-elles être contenues dans leur propre classe correspondante, par exemple la fonction ci-dessus serait Foo.FromXml. Ou dois-je créer une classe séparée pour lire des choses à partir de fichiers ? Il semble y avoir deux lignes directrices générales qui s'affrontent ici :

  1. Une classe doit tout savoir sur une seule chose : elle-même.
  2. Une classe ne devrait avoir qu'une seule raison de changer.

Tout d'abord, je ne comprends pas vraiment la deuxième, car le terme "raison" est assez vague. La première ligne directrice suggère de placer chaque lecteur dans la classe correspondante. La seconde dit de faire une classe dédiée à la lecture des fichiers xml. Mais les avantages et les inconvénients sont discutables. D'une part, chaque classe peut contenir son propre lecteur, ce qui évite de référencer une douzaine de classes. D'autre part, chaque classe devrait inclure System.Xml, et si je change mon format xml, les choses pourraient changer dans plusieurs fichiers (mais je ne pense pas que ce soit trop grave).

Je sais que la règle la plus importante est "utilisez votre cerveau" et qu'il n'existe pas de solution "correcte", mais seulement une bonne solution qui fonctionne. Alors, qu'est-ce qui, selon vous, serait plus lisible ou, mieux encore, plus facile à maintenir ?

edit : pour clarifier, les classes peuvent être totalement indépendantes. Puisqu'il s'agit d'un jeu, l'une peut être la classe d'animation des sprites, l'une peut définir le comportement des ennemis, l'une peut définir la disposition ou les propriétés de la carte. L'héritage n'a donc rien à voir avec cela.

2voto

Christopher Bruce Points 329

Les fonctions FromXml(...) sont-elles identiques ? Si c'est le cas, je les mettrais dans une bibliothèque commune, car cela facilitera grandement leur maintenance, étant donné qu'il n'y aura pas de duplication du code. Le code devrait également être soigné

SomeObject o = (SomeObject)Foo.FromXml(reader);

EDITAR: Ou, éventuellement, créer une classe abstraite de base qui ne possède que les fonctions FromXml / ToXml, puis faire en sorte que toutes les classes qui veulent utiliser ces fonctions héritent de la classe abstraite.

1voto

Misha Lavrov Points 105

Il est difficile d'avoir une méthode statique de classe de base pour toutes les classes qui en héritent et de maintenir un polymorphisme adéquat. Vous pourriez cependant supprimer le caractère statique de la méthode et avoir une méthode InitializeFromXml qui vous permettrait essentiellement de remplir votre classe à partir du xml. Bien que je n'apprécie pas les méthodes d'initialisation publiques, cette méthode tend à être meilleure pour le polymorphisme.

Voici un exemple. C'est un peu trop pour un petit objet comme celui-ci (et j'utilise rarement la sérialisation xml, mais je le charge dans un document xml et j'en retire ce dont j'ai besoin pour les affectations de désérialisation), mais lorsque les choses s'étendent, sont héritées, et généralement plus complexes, cela vous permet de réutiliser beaucoup plus :

public class CustomObject {
    public string AValue { get; set; }
    public bool BValue { get; set; }
    protected IXmlConfiguration Config = new CustomObjectConfig( );

    public virtual string ToXml( ) {
        return Config.ToXml( this );
    }

    public virtual void InitializeFromXml( string xml ) {
        Config.FromXml( xml );
        AValue = ((CustomObjectConfig)Config).A;
        BValue = ((CustomObjectConfig)Config).B;
    }
}

public interface IXmlConfiguration {
    void FromXml( string xml );
    string ToXml( object instance );
}

[XmlRoot( "CustomObject" )]
public class CustomObjectConfig : IXmlConfiguration {
    [XmlElement( "AValue" )]
    public string A { get; set; }
    [XmlAttribute( "bvalue" )]
    public bool B { get; set; }

    public void FromXml( string xml ) {
        byte[] bytes = Encoding.UTF8.GetBytes( xml );
        using ( MemoryStream ms = new MemoryStream( bytes ) ) {
            XmlSerializer xs = new XmlSerializer( typeof( CustomObjectConfig ) );
            CustomObjectConfig cfg = (CustomObjectConfig)xs.Deserialize( ms );
            A = cfg.A;
            B = cfg.B;
        }            
    }

    public string ToXml( object instance ) {
        string xml = null;
        if ( instance is CustomObject ) {
            CustomObject val = (CustomObject)instance;
            A = val.AValue;
            B = val.BValue;
            using ( MemoryStream ms = new MemoryStream( ) ) {
                XmlSerializer xs = new XmlSerializer( typeof( CustomObjectConfig ) );
                xs.Serialize( ms, this );
                ms.Seek( 0, 0 );
                byte[] bytes = ms.ToArray( );
                xml = Encoding.UTF8.GetString( bytes );
            }
        }
        return xml;
    }
}

La raison pour laquelle je préfère cette approche à la création d'objets sérialisables xml est la suivante

  1. La sérialisation xml exige généralement que vous structuriez votre classe d'une seule façon, et vous utiliserez généralement cette d'une autre manière.
  2. c'est un peu plus facile que d'avoir d'énormes piles d'attributs xml include (peut être appelé différemment) partout, ce qui permettrait la sérialisation polymorphe des objets dérivés dérivés.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X