Is my application correct design - correct inheritance choice?

I have some simple scheduling of various events in my application and I used this class hierarchy:


abstract class ScheduledEvent
{
    public DateTime When{ get; set; }

    public abstract void Trigger();
}

class WhateverEvent : ScheduledEvent
{
  public override void Trigger();
}

class AnotherEvent : ScheduledEvent
{
  public override void Trigger();
}

class Scheduler
{
  public AddEvent(ScheduledEvent event)
}

      

My app works great, but I don't like the design because whenever I want to add a new event, I have to add a new descendant to the hierarchy and all the books say they prefer composition over inheritance, so I tried this approach:


interface ITriggerable
{
    void Trigger();
}

class WhateverEvent : ITriggerable
{
  public void Trigger();
}

abstract class ScheduledEvent
{
    private ITriggerable triggerable;
    public ScheduledEvent(ITriggerable t) { 
        triggerable = t; 
    }
    public DateTime When{ get; set; }

    public void Trigger() { triggerable.Trigger(); }
}

      

But the problem arose immediately. For each event type, there was a form for editing its properties as follows:


class WhateverForm : Form
{
    WhateveverForm(WhateverEvent ev) { ... }
}

      

All properties were available in this form WhateverEvent

, as well as the property When

of ScheduledEvent

. With my new hierarchy, this property is no longer available. I can of course add a link to ScheduledEvent

in WhateverEvent

, but I don't like that.

My question is, how would you create your class hierarchy and why? This may sound trivial to you, but I don't have a lot of design experience and want to do it right.

+2


source to share


4 answers


I think the old design using inheritance is perfectly fine and less complicated. You are using polymorphism the way it is supposed to be used.

My interpretation is "prefers composition over inheritance" (roughly): if you don't want polymorphic behavior, then you should use composition over inheritance.



With the ITriggerable approach, you don't solve the problem of having to write a subclass for every new event. You are just using an interface instead of a base class. It's not technically inheritance, but it's pretty much the same thing.

+1


source


I don't know which is best for you, but a good design should provide encapsulation while balancing cohesion and coupling . I wouldn't follow any rule that gets too close to composition over inheritance. There are reasons for a constructive decision.



0


source


You cannot tell with random names like this. Subclasses must follow the rule of "is": say Truck

is a subclass Vehicle

, then a Truck

must be Vehicle

.

But don't get too carried away - think about code reuse the most and don't just create a deep hierarchy because you can, only create it if it leads to simpler code, better encapsulation, and more code reuse.

0


source


Recommendations for preferring composition over inheritance concern how one should approach achieving reuse. Composition provides both the ability to reuse data and / or behavior across different class hierarchies, and the ability to override specific behavior of a type at runtime. Composition does not obviate the need to create new types for different behaviors.

Regarding the scheduling model, the approach I have used in the past has been to separate the concepts of task, schedule, schedule, and scheduling services. In my case, I needed to schedule to encapsulate more than just a fixed point in time, so it contained additional properties for specifying the repetition interval, number of repetitions, etc. I did not encapsulate the schedule in a task because tasks are not something that In particular, changing the oil is a task, but every 3 months is a schedule that can be applied to oil changes as well as other maintenance tasks. By separating the schedule from the task, it was possible to maintain a single monitor for multiple tasks that had the same schedule.

0


source







All Articles