首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >防止多个开关语句

防止多个开关语句
EN

Stack Overflow用户
提问于 2020-01-30 17:13:16
回答 3查看 92关注 0票数 0

我目前正在为我的Web编写一个自定义日志记录方法,用户可以在这里购买商品。此日志方法将记录用户在遵循购买过程时所采取的所有步骤,以便支持稍后可以跟踪这些步骤。有多个步骤,如:

  • 创建订单
  • 更新订单
  • 购买一件物品
  • 接收状态
  • 等等。

此方法将返回一个“事件”对象,其中所有必要的日志信息都组合在一起,例如LogLevel、Message、UserId等,并将其写入数据库。

在我到达这一点之前,我必须创建非常有用的日志消息。该消息基于这两个枚举(解释稍微简化了一点):

  1. ActionName -在我的过程中的哪个步骤是这个日志事件
  2. ActionOrigin -是从我的前端或后端系统记录的日志事件.

它还基于一个对象,其中提供了必要的日志值,例如order id。

日志事件方法定义的日志类是一个作用域注入类,因此我可以在代码中的每个关键位置记录事件。

我想到的第一件事是创建一个switch语句,并根据正确的情况创建消息。但这将结合2个开关语句,很快就会看起来一团糟。

我做了一些研究,发现了策略模式。我不确定这能不能帮上忙?还有其他的想法或例子吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-01-30 19:46:16

每当您正在处理对象模型并发现自己正在编写大量的switch语句时,这通常意味着您将类特定的逻辑放在了错误的位置。你应该把它和类本身放在一起,而不是使用它的类。

换句话说,记录器不应该知道如何记录每一种类型的事件。那将是一场维护噩梦。相反,它应该知道如何记录一个公共对象(例如字符串),并且每个事件本身都应该知道如何通过记录器知道的通用方法来创建该公共对象。这是它唯一需要知道的事。

下面是一个简单的例子。在本例中,记录器接受任何类型的LoggableEvent,并调用其Serialize()方法来确定如何将其添加到公共日志中。事件本身负责了解如何序列化自身。

代码语言:javascript
运行
复制
abstract class LoggableEventBase
{
    public string ActionName { get; }

    public string ActionOrigin { get; }

    public LoggableEventBase(string actionName, string actionOrigin)
    {
        ActionName = actionName;
        ActionOrigin = actionOrigin;
    }

    public virtual string Serialize()
    {
        return string.Format("{0} {1}", ActionName, ActionOrigin);
    }
}

class CreateOrderEvent : LoggableEventBase
{
    protected readonly List<Item> _items;
    protected readonly int _orderId;

    public CreateOrderEvent(string origin, int orderID, List<Item> items) : base("CreateOrder", origin)
    {
        _orderId = orderID;
        _items = items;
    }

    public override string Serialize()
    {
        return base.Serialize() + string.Format(" {0} {1}", _orderId, string.Join(",", _items.Select(item => item.SKU)));
    }
}

现在,实际的日志记录逻辑相当简单--没有switch语句或任何其他需要知道事件是什么的语句:

代码语言:javascript
运行
复制
class Logger : ILogger
{
    public void Log(LoggableEventBase eventToLog)
    {
        Write(eventToLog.Serialize());
    }

    protected virtual void Write(string message)
    {
        //Write the message to a log file
    }
}

要添加其他事件类型,只需定义新类(并覆盖Serialize())。您不必返回并修改Logger类。这比现有的解决方案更符合开闭原理

票数 2
EN

Stack Overflow用户

发布于 2020-01-30 19:15:50

这是一个设计模式问题。您可能需要阅读您正在使用的语言/框架所使用的不同模式。看起来,您似乎在试图避免将日志写成一行。一种方法是以常量定义不同消息的格式,并使用字符串内插(或简单的级联)来使用log()方法构建消息。

示例(我将尽力编写正确的C#,请编辑任何错误或不足):

代码语言:javascript
运行
复制
class Logger {
    // If you want personalized messages for different actions or origins, define their template constants and create different methods for building them. 
    public const string ORDER_PROGRESS_MSG_TMPL = "Action:{0}, Origin:{1}, OrderId:{3}";
    void log_order_progress(string actionName, sting actionOrigin, string orderId){
        Console.WriteLine(
            ORDER_PROGRESS_MSG_TMPL, actionName, actionOrigin, orderId
        );
    }
}

代码语言:javascript
运行
复制
class Order {
    ...
    void create(int orederId){
        Logger.log_order_progress(ActionEnum.CREATING, OriginEnum.BACK_END, orderId)
        // Do some stuff here to create order
        Logger.log_order_progress(ActionEnum.UPDATING, OriginEnum.BACK_END, orderId)
        // etc
    }
}

这是的一种方式,您可以通过在它们自己的类中拥有模板来更多地模块化它。此外,您还可以创建(或者更好地说:使用现有的日志框架)来区分日志记录的级别(调试、信息、错误),就像@San深处Sharma描述的那样。

票数 1
EN

Stack Overflow用户

发布于 2020-01-30 18:25:15

您可以在Logger类中创建多个方法,每个方法用于特定场景。这些方法可以是:

  • info() =用于记录某些信息。
  • debug() =用于调试。
  • error () =用于记录错误事件。

假设您希望记录购买项目的事件,并且当用户确实购买操作时,您可以将信息传递给logger.info()方法。如果遇到错误,或者某个操作或条件未得到满足,则可以将数据传递给方法error(),这将在您的情况下记录错误。对于消息: 1. 操作名-您可以传递用户操作调用的方法名或路由路径。2. Action -提供诸如用户名、完整路径、操作类型等详细信息。您还可以维护诸如“时间戳”和一些“唯一标识符”这样的字段,以便更好地记录事件。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59991161

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档