Language agnostic 如何考虑类的静态调用

Language agnostic 如何考虑类的静态调用,language-agnostic,refactoring,static-methods,Language Agnostic,Refactoring,Static Methods,假设我有一个名为Logger.log()的静态方法,它调用另一个静态方法CurrentUser.getName(),以获取要记录的其他信息: public static void log(text) { String[] itemsToLog = { text, todaysDate, ipAddress, CurrentUser.getName() }; 显然,这不是一个理想的情况,尤其是对于CurrentUser类中的静态数据。但是我想通过减少记录器的依赖性来开始改进它。我更希望日志记

假设我有一个名为Logger.log()的静态方法,它调用另一个静态方法CurrentUser.getName(),以获取要记录的其他信息:

public static void log(text) {
  String[] itemsToLog = { text, todaysDate, ipAddress, CurrentUser.getName() };
显然,这不是一个理想的情况,尤其是对于CurrentUser类中的静态数据。但是我想通过减少记录器的依赖性来开始改进它。我更希望日志记录器不具备用户等更高层次概念的任何知识。它只需要一个要记录的东西的列表,而不关心它们是什么

所以我想以某种方式计算出CurrentUser类。但是Logger是静态的,所以我不能只将信息传递给它的构造函数

什么样的模式可以很好地分解出这样的内容?

您有两种选择:

  • 始终将信息传递给记录器
  • 让记录器在记录器中静态维护它(或调用其他方法)
  • 如果您不希望Logger静态地维护它,也不希望每次在调用中包含附加信息(或调用),那么您可以创建另一个类来调用Logger并传递所有静态信息,然后将Logger更改为没有静态数据(或至少不调用CurrentUser)。然后调用logger的类可以在其构造函数中接受CurrentUser

    您可以将其用作未来重构的垫脚石


    如果您的语言支持扩展方法或类帮助程序,则可以将Logger更改为接受CurrentUser作为参数,然后添加仅接受日志文本的扩展方法,然后自动传递CurrentUser。这将允许您在不更改所有调用的情况下进行更改,尽管它要求扩展方法是静态的。所以你没有什么进展。

    你在这里没有很多选择。如果您不希望记录器依赖CurrentUser,则可以依赖最终用户(日志记录类)在日志记录文本中插入用户,或者创建一个子类logger,它确实了解CurrentUser,这可能会违背您的目的

    我宁愿记录器没有 了解更高层次的概念吗 像用户一样

    听起来您可能想走的方向是将日志消息的组成和格式化逻辑与日志机制分开。例如(请原谅我的C#成语):

    从那里,只需按如下方式调用记录器:

    Logger.log(new WebRequestLogEntry("Hi", CurrentUser.getName(), ipAddress).Text);
    

    在我看来,您的记录器已经维护了一些状态(例如,日期、地址、用户等)


    让log()成为对特定记录器的非静态调用,并在首次创建记录器时初始化所有相关内容(包括用户)难道没有意义吗?您可以使用一个记录器管理器来初始化并稍后获取特定的记录器,或者将记录器设置为单例(如果是这样的话)。然后,获取用户的逻辑将位于记录器管理器或记录器的工厂/getInstance()中,而不是记录器实例本身

    一个选项是创建一个新的接口ContextProvider并从中获取上下文字符串

    public interface ContextProvider{
        public List<String> getContextToLog();
    }
    ...
    public class DefaultLoggingContext implements ContextProvider{
        public List<String> getContextToLog(){
            ...
            list.Add(CurrentUser.getName());
            ...
            return list;
        }
    }
    ...
    public class Logger{
        private static ContextProvider contextProvider;
    
        public static initiliseLogger(ContextProvider defaultProvider){
            contextProvider = defaultProvider;
        }
    
        public static log(String text){
            log(text, contextProvider);
        }
    
        public static log(String text, contextProvider){
            List<String> toLog = contextProvider.getContextToLog();
            toLog.add(text);
    }
    ...
    public class ...{
        private ContextProvider loggingContext; // set by a constructor, factory method or a IOC container
    
        private onApplicationStart(){
            Logger.initiliseLogger(loggingContext)
        }
    }
    
    公共接口上下文提供程序{
    公共列表getContextToLog();
    }
    ...
    公共类DefaultLoggingContext实现ContextProvider{
    公共列表getContextToLog(){
    ...
    添加(CurrentUser.getName());
    ...
    退货清单;
    }
    }
    ...
    公共类记录器{
    私有静态ContextProvider ContextProvider;
    公共静态initiliseLogger(ContextProvider defaultProvider){
    contextProvider=defaultProvider;
    }
    公共静态日志(字符串文本){
    日志(文本、上下文提供者);
    }
    公共静态日志(字符串文本、contextProvider){
    List toLog=contextProvider.getContextToLog();
    添加(文本);
    }
    ...
    公共课{
    私有ContextProvider loggingContext;//由构造函数、工厂方法或IOC容器设置
    私有onApplicationStart(){
    Logger.initiliseLogger(loggingContext)
    }
    }
    
    您可以更进一步,使用格式化程序而不是contextProvider。格式化程序将负责获取输入字符串“文本”,并对其进行完整的格式化,包括添加任何会话、日期、时间、请求等信息。您可以查看这方面的完整实现

    另一方面,我建议将log方法改为实例方法而不是静态方法将是一个非常好的举措,您可以在一段时间内支持这两种方法,并将静态标记为不推荐使用,或者您可以找到并替换stick。我非常喜欢log4*的一个功能是基于c更改日志敏感度的能力小女孩或包裹

    public interface ContextProvider{
        public List<String> getContextToLog();
    }
    ...
    public class DefaultLoggingContext implements ContextProvider{
        public List<String> getContextToLog(){
            ...
            list.Add(CurrentUser.getName());
            ...
            return list;
        }
    }
    ...
    public class Logger{
        private static ContextProvider contextProvider;
    
        public static initiliseLogger(ContextProvider defaultProvider){
            contextProvider = defaultProvider;
        }
    
        public static log(String text){
            log(text, contextProvider);
        }
    
        public static log(String text, contextProvider){
            List<String> toLog = contextProvider.getContextToLog();
            toLog.add(text);
    }
    ...
    public class ...{
        private ContextProvider loggingContext; // set by a constructor, factory method or a IOC container
    
        private onApplicationStart(){
            Logger.initiliseLogger(loggingContext)
        }
    }