实施非日期驱动的重复

发布于 2024-10-28 14:54:28 字数 425 浏览 4 评论 0原文

我正在开发一个应用程序,当用户需要对各种设备执行预防性维护时,该应用程序实质上会提示用户。每件装备(称之为工具)都有不同的重复模式。有些将基于时间,例如每 90 天,而另一些则基于其他因素,例如使用情况。例如,某个特定工具在被签出 X 次后可能需要 PM。

所有工具都分配给个人,因此当该用户登录应用程序时,我需要显示当时需要 PM 的工具列表。当 PM 完成时,这些项目将从列表中删除,并且在其他情况下,例如日期更改或工具被重新签入婴儿床,工具将被添加。

我从设计将返回此列表的服务方法开始,并寻求一些有关我用来解析列表中的项目的方法的帮助。对于输入,我将拥有用户的标识符和当前日期。由此,我需要查询工具列表,并根据其重复模式、上次执行 PM 的时间以及自上次 PM 以来发生的事件来确定该项目是否应出现在列表中。

希望这是有道理的。我很感激任何关于我应该如何处理这个逻辑的想法和指导。

I am developing an application that essentially prompts users when they need to perform Preventative Maintenance on various pieces of equipment. Each piece of equipment (call it a tool) has a different recurrence pattern. Some will be based on time, such as every 90 days, while others are based on other factors such as usage. For example, a particular tool might need PM after it has been checked out X number of times.

All tools are assigned to an individual so when that user signs into the application I need to display a list of the tools that require PM at that time. As PM is completed, those items drop off the list and as other circumstance, such as the date changes or the tool is checked back into the crib, tools will be added.

I am starting with the design of the service method that will return this list and am looking for some help with the approach I use to resolve what items are in the list. For inputs I will have the user's identifier and the current date. From that I need to query the list of tools and determine based on their recurrance pattern, the last time PM was performed and the events that have taken place since the last PM, whether that item should appear in the list.

Hopefully that makes sense. I appreciate any thoughts and guidance on how I should approach this logic.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

鯉魚旗 2024-11-04 14:54:28

为了结束,我想我应该用我的努力结果来更新这篇文章,尽管我感谢布兰登和弗洛里安的回答,因为他们让我走上了正确的道路。

正如布兰登建议的那样,我最终得到了一个名为 IHaveRecurrence 的接口,定义如下:

public interface IHaveRecurrence
{
    DateTime? LastOccurrence { get; }
    RecurrenceType RecurrenceType { get; }
    Int32 RecurrenceValue { get; }
    Boolean IsDue();
}

我的MaintainableTool(基)类现在实现了此接口。 IsDue 方法是通过委托给 Recurrence 类来实现的:

public Boolean IsDue()
{
    return Recurrence.IsDue(this);
}

按照 Florian 的建议,Recurrence 是一个抽象基类。我有几个子类,例如 DailyRecurrence、WeeklyRecurrence 等。每个子类都对应于 RecurrenceType 枚举中的值之一,并实现适当的逻辑,以通过 IHaveRecurrence 接口根据 RecurrenceValue 和 LastOccurrence 属性确定 PM 是否到期。

Recurrence 使用内部 RecurrenceFactory 类来解析要使用哪个子类:

internal sealed class RecurrenceFactory
{
    public Recurrence GetRecurrence(RecurrenceType type)
    {
        switch (type)
        {
            case Daily: return new DailyRecurrence;
            :
        }
    }
}

Recurrence 的实现方式为:

public abstract class Recurrence : IDisposable
{
    public static Boolean IsDue(IHaveRecurrence recurringObj)
    {
        using (var recurrence = RecurrenceFactory.GetRecurrence(recurringObj.RecurrenceType))
        {
            return recurrence.GetIsDue(recurringObj);
        }
    }

    protected abstract Boolean GetIsDue(IHaveRecurrence recurringObj);
}

然后,例如,DailyRecurrence 类的实现方式为:

public sealed class DailyRecurrence : Recurrence
{
    protected override Boolean GetIsDue(IHaveRecurrence recurringObj)
    {
        if (recurringObj.LastOccurred.HasValue)
            return recurringObj.LastOccurred.AddDays(recurringObj.RecurrenceValue) <= DateTime.Now;

        return true;
    }
}

我喜欢这个模型,因为它具有高度可扩展性,封装了解析每个重复模式所需的逻辑并保持我的业务对象干净。

For the sake of closure, I thought I'd update the post with the results of my effort although I am giving credit for the answer to both Brandon and Florian for sending my on the right path.

I ended up with an interface, as Brandon suggested, called IHaveRecurrence defined as follows:

public interface IHaveRecurrence
{
    DateTime? LastOccurrence { get; }
    RecurrenceType RecurrenceType { get; }
    Int32 RecurrenceValue { get; }
    Boolean IsDue();
}

My MaintainableTool (base) class now implements this interface. The IsDue method is implemented by delegating to the Recurrence class:

public Boolean IsDue()
{
    return Recurrence.IsDue(this);
}

Recurrence is an abstract base class as suggested by Florian. I have several subclasses such as DailyRecurrence, WeeklyRecurrence, etc. Each of the subclasses corresponds to one of the values in the RecurrenceType enumeration and implements the appropriate logic to determine if PM is due based on the RecurrenceValue and LastOccurrence properties via the IHaveRecurrence interface.

Recurrence uses the internal RecurrenceFactory class to resolve which subclass to use:

internal sealed class RecurrenceFactory
{
    public Recurrence GetRecurrence(RecurrenceType type)
    {
        switch (type)
        {
            case Daily: return new DailyRecurrence;
            :
        }
    }
}

And Recurrence is implemented as:

public abstract class Recurrence : IDisposable
{
    public static Boolean IsDue(IHaveRecurrence recurringObj)
    {
        using (var recurrence = RecurrenceFactory.GetRecurrence(recurringObj.RecurrenceType))
        {
            return recurrence.GetIsDue(recurringObj);
        }
    }

    protected abstract Boolean GetIsDue(IHaveRecurrence recurringObj);
}

Then, for instance, the DailyRecurrence class is implemented as:

public sealed class DailyRecurrence : Recurrence
{
    protected override Boolean GetIsDue(IHaveRecurrence recurringObj)
    {
        if (recurringObj.LastOccurred.HasValue)
            return recurringObj.LastOccurred.AddDays(recurringObj.RecurrenceValue) <= DateTime.Now;

        return true;
    }
}

I like this model as it is highly extensible, encapsulates the logic required to resolve each recurrence pattern and keeps my business object clean.

剑心龙吟 2024-11-04 14:54:28

在我看来,每个工具都有自己的逻辑来确定是否需要 PM。因此,我将定义一个带有几个枚举的 IEquipment 接口,如下所示:

public enum RecurrenceType
{
    //Values
}

public enum RecurrenceFrequency
{
    //Values
}

public interface IEquipment
{
    bool IsPMRequired();

    RecurrenceType RecurrenceType { get; }
    RecurrenceFrequency RecurrenceFrequency { get; }
    //You may want to choose something other than object, or eliminate this property
    object RecurrenceValue { get; set; } 
}

然后每种类型的设备都将实现该接口,并且可以实现确定是否需要 PM 的逻辑:

public class Tractor : IEquipment
{
    public bool IsPMRequired()
    {
        //Implement logic here specific to a Tractor
        throw new NotImplementedException();
    }

    public RecurrenceType RecurrenceType
    {
        get { throw new NotImplementedException(); }
    }

    public RecurrenceFrequency RecurrenceFrequency
    {
        get { throw new NotImplementedException(); }
    }

    public object RecurrenceValue
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            throw new NotImplementedException();
        }
    }
}

然后使用这些对象的逻辑将是类似于:

List<IEquipment> equipment = new List<IEquipment>();
//Populate equipment
List<IEquipment> display = equipment.Where(e => e.IsPMRequired()).ToList();
//Display the equipment that needs PM

为设备设置一个基类,在其中放置通用方法/属性定义也可能是有意义的。

It sounds to me like each Tool is going to have it's own logic for determining whether PM is required or not. So I would define an IEquipment interface with a couple enums, something like this:

public enum RecurrenceType
{
    //Values
}

public enum RecurrenceFrequency
{
    //Values
}

public interface IEquipment
{
    bool IsPMRequired();

    RecurrenceType RecurrenceType { get; }
    RecurrenceFrequency RecurrenceFrequency { get; }
    //You may want to choose something other than object, or eliminate this property
    object RecurrenceValue { get; set; } 
}

Then each type of equipment would implement the interface, and the logic to determine whether or not PM is required could be implemented:

public class Tractor : IEquipment
{
    public bool IsPMRequired()
    {
        //Implement logic here specific to a Tractor
        throw new NotImplementedException();
    }

    public RecurrenceType RecurrenceType
    {
        get { throw new NotImplementedException(); }
    }

    public RecurrenceFrequency RecurrenceFrequency
    {
        get { throw new NotImplementedException(); }
    }

    public object RecurrenceValue
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            throw new NotImplementedException();
        }
    }
}

Then your logic to use these objects would be something like:

List<IEquipment> equipment = new List<IEquipment>();
//Populate equipment
List<IEquipment> display = equipment.Where(e => e.IsPMRequired()).ToList();
//Display the equipment that needs PM

It might also make sense to have a base class for Equipment where you put common method/property definitions.

一腔孤↑勇 2024-11-04 14:54:28

我将定义一个抽象类 Recurrence,如下所示:

abstract class Recurrence
{
      public abstract bool IsDue(DateTime dateAndTime);
}

现在将 Recurrence 设置为 Equipment 的属性。

abstract class Equipment
{
      protected abstract Recurrence PMRecurrence
      {
            get;
      }

      public bool IsPMDue(DateTime dateAndTime)
      {
             return PMRecurrence.IsDue(dateAndTime);
      }
 }

然后,您可以定义适当的循环子类,如 TimeRecurrence、UsageRecurrence,并将它们的实例分配给适当的设备子类,如锤子、拖拉机,并根据需要实现它们。这应该提供灵活性和可维护性的良好平衡。

祝你好运,似乎是一项具有挑战性的任务!

I would define an abstract class Recurrence that looks like this:

abstract class Recurrence
{
      public abstract bool IsDue(DateTime dateAndTime);
}

Now make Recurrence a property of Equipment.

abstract class Equipment
{
      protected abstract Recurrence PMRecurrence
      {
            get;
      }

      public bool IsPMDue(DateTime dateAndTime)
      {
             return PMRecurrence.IsDue(dateAndTime);
      }
 }

Then you could define appropriate subclasses of Recurrence like TimeRecurrence, UsageRecurrence and assign instances of them to appropriate subclasses of Equipment like Hammer, Tractor and implement them as needed. This should provide a good balance of flexibility and maintainability.

Good luck, seems like a challenging task!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文