mercredi 19 février 2020

Do split one class hierarchy into several or not?

For now we have a .NET application which leans on the standard .NET XML serialization/deserialization mechanism. The example is simplified but the meaning is the same.

public abstract class Shape
{
    [XmlAttribute("id")]
    public string Id { get; set; }
    [XmlAttribute("level")]
    public int Level { get; set; }

    public abstract void Draw();
    public abstract void Clear();
    public abstract void Scale(double scale);
}

[XmlType("Circle")]
public class Circle : Shape
{
    public double Radius { get; set; }

    public override void Draw() {}

    public override void Clear() {}

    public override void Scale(double scale) {}
}

[XmlType("Rectangle")]
public class Rectangle: Shape
{
    public double Height { get; set; }
    public double Width { get; set; }

    public override void Draw() {}

    public override void Clear() {}

    public override void Scale(double scale) {}
}

public class Picture
{
    public double Scale { get; set; }
    [XmlArrayAttribute("Shapes")]
    public Collection<Shape> Shapes { get; set; }

    public void Setup()
    {
        foreach (Shape shape in Shapes)
        {
            shape.Draw();
        }

        foreach (Shape shape in Shapes)
        {
            shape.Scale(Scale);
        }
    }

    public void Cleanup()
    {
        foreach (Shape shape in Shapes)
        {
            shape.Clear();
        }
    }

    public static Picture FromXml(XmlReader xmlReader)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(Picture));
        return serializer.Deserialize(xmlReader) as Picture;
    }
}

And for example the input XML file will look like:

<Picture>
    <Scale>0.9</Scale>
    <Shapes>
        <Circle id="1">
            <Radius>1.5</Radius>
        </Circle>
        <Circle id="2">
            <Radius>3</Radius>
        </Circle>
        <Rectangle id="3">
            <Height>300</Height>
            <Width>300</Width>
        </Rectangle>
    </Shapes>
</Picture>

But model classes contain a logic and seems that it breaks a single responsibility principle. And therefore we don't know does it make sense to split that logic into several classes or not?

If yes, then how? Because once we read the XML file, all objects are accessible only as Shape objects and therefore we will have to explicitly cast the object either before passing if to the handler class or inside that method, for example:

public abstract class Drawer
{
    public abstract void Draw(Shape shape);
}

public class CircleDrawer : Drawer
{
    public override void Draw(Shape shape){
    {
        Circle circle = shape as Circle;
        if (circle == null)
        {
            throw new ArgumentException("Passed object is not of type Circle");
        }
    }
}

If that issue is known, please just redirect me to that resource.

Thank you in advance.

Aucun commentaire:

Enregistrer un commentaire