迁移到具有以下功能的记录仪Sensei

发表于2020年11月30日
作者:Alan Richardson
案例研究

迁移到具有以下功能的记录仪Sensei

发表于2020年11月30日
作者:Alan Richardson
查看资源
查看资源

迁移到具有以下功能的记录仪Sensei

这篇文章描述了创建一个配方,将System.out.println迁移到使用Java Logger。

当我在写代码时,而不是使用TDD,当我犯错误时,我有一个坏习惯,就是向System.out打印一行,我一直想让自己摆脱这个习惯。

我在写下面的代码时犯了一堆错误。

   private String getCountdownString() {
        String output = "";
        String prefix="";
        for(int countdown = 10; countdown > 0; countdown-- ){
            output = output + prefix + countdown;
            System.out.println(output);
            prefix=", ";
        }
        System.out.println(output);
        return output;
    }


最初,我写的是countdown++,循环没有完成。

而且我使用了倒计时>1,所以没有得到我想要的输出。

最后,我在代码中加入了System.out.println来帮助我调试。这次经历让我更加确信,我需要学习如何使用记录器作为我的默认方法。

研究

幸运的是,我通读了Sensei 文档,并决定使用 "入门 "指南来帮助我创建一个从System.out.println转换的配方,并鼓励我使用一个记录器。

  • java.util.logging.Logger

创建一个配方

我做的第一件事是点击println,然后alt+enter来创建一个新的配方。

系统打印 创建一个新的食谱


我创建它时有以下细节。


名称。记录器:使用记录器而不是println
描述:用logger代替println--记得停止使用System.out.println
水平。错误


而我将从匹配名称为println的方法调用开始


搜索。
  方法调用。
    名称:"println"

而预览显示了我的代码中所有的匹配。


配方设置方法调用Println


我可以看到我的代码中所有的匹配都是System.out.println,但我不相信长期以来这将是唯一的匹配。我想匹配一个我想改变的更有条件的语句。

我扩展了匹配器,以搜索在类System中命名的一个字段上的方法调用。


搜索。
  方法调用。
    名称:"println"
    "上"。
      领域。
        在。
          类。
            名称:"系统"
        名称:"外出"



如果我愿意,我可以把System的名字完全限定为java.lang.System

配方设置方法调用名称系统

修改法典以记录


接下来,我想创建 "快速修复"。

首先,我想修改记录输出的那行代码。


可用的修复方法。
- 名称:"使用记录仪"
  行动。
  - 改写。
      to: "logger.log(Level.INFO, {{{ arguments.0 }}})"



我不需要记住小胡子模板的格式。我使用GUI中的显示变量来向我显示参数,并双击它。然后GUI就填入了相应的匹配的胡子模板。



当我尝试时,我可以看到我仍然需要alt+enter来导入水平枚举。但是,如果我修改我的QuickFix,使其拥有一个完全合格的项目,那么Sensei ,就会为我添加导入,例如:

  • 它将把System.out.println(output);替换为

logger.log(Level.INFO, output)。

  • 并为该枚举添加一个导入。

输入java.util.logging.Level。

  • 如果我改写成。
logger.log(java.util.logging.Level.INFO, {{arguments.0 }}}.

而这将会起作用,但我仍然要记住首先要实例化记录器的语法。

首先对记录器进行实例化的语法


修改代码以添加记录器字段

我也可以修改我的QuickFix,为我创建这个字段。

我将首先对记录器进行编码,然后将其添加到我的配方中,这样我就不必再编码了。

Logger 2 = Logger.getLogger(SysOutTest.class.getName())。


我倾向于先写出我想看到生成的示例代码,因为这样我就可以使用IntelliJ的代码完成和语法检查来确保我的代码正确。作为一个副作用,当我编辑配方添加QuickFix行以创建该代码时,它将出现在代码预览中。

而当我写示例代码时,我想用一个不同的字段名(这里我用logger2),因为Sensei ,它很聪明,不会添加一个重复的字段,所以我必须用一个不同的名字来欺骗它。

所以我将修改配方,通过添加一个名为logger的字段来创建这段代码。

可用的修复方法。

- 名称:"使用记录仪"
  行动。
  - 改写。
      to: "logger.log(java.util.logging.Level.INFO, {{{ arguments.0 }}})"
  - addField。
      field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
        }}.class.getName())"
      目标:"parentClass"


注意,我把SysOutTest改成了一个mustache变量,这样它就能接收到我使用这个配方的任何类的名字。再说一遍,我没有记住mustache的语法,我使用GUI显示变量来找到我需要的替换。

通过将Logger完全限定为java.util.logging.Logger,Sensei ,将添加导入并编写我想要的那行代码,即

Logger logger = Logger.getLogger(SysOutTest.class.getName() )。


将记录器完全限定为 java.util.logging.Logger


这个配方的一个有用之处在于,由于它只添加一次记录器字段,我可以在任何使用了`System.out.println`的现有代码上使用这个配方,并使用Sensei ,同时改变代码文件中的所有出现。


使用记录仪修复文件中的所有问题



接下来的步骤

一旦我习惯了这个,我最终会训练自己不再使用System.out.println。

我可以使用Sensei ,通过创建第二个配方来帮助我主动编写代码,这个配方可以帮助我创建一个记录器。

例如,我可以在一个没有名为logger的字段的类上进行匹配,并添加一个。

如果我创建一个水平信息的配方


名称。记录仪:添加记录仪

描述。在类中添加记录器


要在一个没有记录器字段的类上进行匹配。

搜索。
  类。
    没有。
      孩子。
        领域。
          名称:"记录器"


然后我将重新使用我们之前看到的快速修复的一部分。


可用的修复方法。

  - 名称:"添加记录仪"
    行动。
      - addField。
          field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
        }}.class.getName())"
          目标:"自我"


请注意,与第一个QuickFix相比,这里的目标不同。这里使用self,因为我们的搜索匹配了类。第一个QuickFix使用了parentClass,因为我们匹配了类本身的代码。

摘要

这代表了与使用Sensei 来帮助提高个人编程技能的关键流程之一。

  • 创建一个食谱,以帮助你立即进行 "最佳实践"。
  • 一旦你知道如何使用该最佳实践......创建一个配方,使你的工作流程更快。


---


你可以使用 "Preferences \ Plugins"(Mac)或 "Settings \ Plugins"(Windows)从IntelliJ内部安装Sensei ,然后只要搜索 "sensei secure code"。


这方面的源代码和配方可以在Secure Code Warrior GitHub账户的`sensei-blog-examples`仓库中找到,在`pojoexamples`模块中。




查看资源
查看资源

作者

艾伦-理查德森

想要更多吗?

在博客上深入了解我们最新的安全编码见解。

我们广泛的资源库旨在增强人类对安全编码技术提升的方法。

查看博客
想要更多吗?

获取关于开发者驱动的安全的最新研究

我们广泛的资源库充满了有用的资源,从白皮书到网络研讨会,让你开始使用开发者驱动的安全编码。现在就去探索它。

资源中心

迁移到具有以下功能的记录仪Sensei

发表于2020年11月30日
作者:Alan Richardson

迁移到具有以下功能的记录仪Sensei

这篇文章描述了创建一个配方,将System.out.println迁移到使用Java Logger。

当我在写代码时,而不是使用TDD,当我犯错误时,我有一个坏习惯,就是向System.out打印一行,我一直想让自己摆脱这个习惯。

我在写下面的代码时犯了一堆错误。

   private String getCountdownString() {
        String output = "";
        String prefix="";
        for(int countdown = 10; countdown > 0; countdown-- ){
            output = output + prefix + countdown;
            System.out.println(output);
            prefix=", ";
        }
        System.out.println(output);
        return output;
    }


最初,我写的是countdown++,循环没有完成。

而且我使用了倒计时>1,所以没有得到我想要的输出。

最后,我在代码中加入了System.out.println来帮助我调试。这次经历让我更加确信,我需要学习如何使用记录器作为我的默认方法。

研究

幸运的是,我通读了Sensei 文档,并决定使用 "入门 "指南来帮助我创建一个从System.out.println转换的配方,并鼓励我使用一个记录器。

  • java.util.logging.Logger

创建一个配方

我做的第一件事是点击println,然后alt+enter来创建一个新的配方。

系统打印 创建一个新的食谱


我创建它时有以下细节。


名称。记录器:使用记录器而不是println
描述:用logger代替println--记得停止使用System.out.println
水平。错误


而我将从匹配名称为println的方法调用开始


搜索。
  方法调用。
    名称:"println"

而预览显示了我的代码中所有的匹配。


配方设置方法调用Println


我可以看到我的代码中所有的匹配都是System.out.println,但我不相信长期以来这将是唯一的匹配。我想匹配一个我想改变的更有条件的语句。

我扩展了匹配器,以搜索在类System中命名的一个字段上的方法调用。


搜索。
  方法调用。
    名称:"println"
    "上"。
      领域。
        在。
          类。
            名称:"系统"
        名称:"外出"



如果我愿意,我可以把System的名字完全限定为java.lang.System

配方设置方法调用名称系统

修改法典以记录


接下来,我想创建 "快速修复"。

首先,我想修改记录输出的那行代码。


可用的修复方法。
- 名称:"使用记录仪"
  行动。
  - 改写。
      to: "logger.log(Level.INFO, {{{ arguments.0 }}})"



我不需要记住小胡子模板的格式。我使用GUI中的显示变量来向我显示参数,并双击它。然后GUI就填入了相应的匹配的胡子模板。



当我尝试时,我可以看到我仍然需要alt+enter来导入水平枚举。但是,如果我修改我的QuickFix,使其拥有一个完全合格的项目,那么Sensei ,就会为我添加导入,例如:

  • 它将把System.out.println(output);替换为

logger.log(Level.INFO, output)。

  • 并为该枚举添加一个导入。

输入java.util.logging.Level。

  • 如果我改写成。
logger.log(java.util.logging.Level.INFO, {{arguments.0 }}}.

而这将会起作用,但我仍然要记住首先要实例化记录器的语法。

首先对记录器进行实例化的语法


修改代码以添加记录器字段

我也可以修改我的QuickFix,为我创建这个字段。

我将首先对记录器进行编码,然后将其添加到我的配方中,这样我就不必再编码了。

Logger 2 = Logger.getLogger(SysOutTest.class.getName())。


我倾向于先写出我想看到生成的示例代码,因为这样我就可以使用IntelliJ的代码完成和语法检查来确保我的代码正确。作为一个副作用,当我编辑配方添加QuickFix行以创建该代码时,它将出现在代码预览中。

而当我写示例代码时,我想用一个不同的字段名(这里我用logger2),因为Sensei ,它很聪明,不会添加一个重复的字段,所以我必须用一个不同的名字来欺骗它。

所以我将修改配方,通过添加一个名为logger的字段来创建这段代码。

可用的修复方法。

- 名称:"使用记录仪"
  行动。
  - 改写。
      to: "logger.log(java.util.logging.Level.INFO, {{{ arguments.0 }}})"
  - addField。
      field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
        }}.class.getName())"
      目标:"parentClass"


注意,我把SysOutTest改成了一个mustache变量,这样它就能接收到我使用这个配方的任何类的名字。再说一遍,我没有记住mustache的语法,我使用GUI显示变量来找到我需要的替换。

通过将Logger完全限定为java.util.logging.Logger,Sensei ,将添加导入并编写我想要的那行代码,即

Logger logger = Logger.getLogger(SysOutTest.class.getName() )。


将记录器完全限定为 java.util.logging.Logger


这个配方的一个有用之处在于,由于它只添加一次记录器字段,我可以在任何使用了`System.out.println`的现有代码上使用这个配方,并使用Sensei ,同时改变代码文件中的所有出现。


使用记录仪修复文件中的所有问题



接下来的步骤

一旦我习惯了这个,我最终会训练自己不再使用System.out.println。

我可以使用Sensei ,通过创建第二个配方来帮助我主动编写代码,这个配方可以帮助我创建一个记录器。

例如,我可以在一个没有名为logger的字段的类上进行匹配,并添加一个。

如果我创建一个水平信息的配方


名称。记录仪:添加记录仪

描述。在类中添加记录器


要在一个没有记录器字段的类上进行匹配。

搜索。
  类。
    没有。
      孩子。
        领域。
          名称:"记录器"


然后我将重新使用我们之前看到的快速修复的一部分。


可用的修复方法。

  - 名称:"添加记录仪"
    行动。
      - addField。
          field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
        }}.class.getName())"
          目标:"自我"


请注意,与第一个QuickFix相比,这里的目标不同。这里使用self,因为我们的搜索匹配了类。第一个QuickFix使用了parentClass,因为我们匹配了类本身的代码。

摘要

这代表了与使用Sensei 来帮助提高个人编程技能的关键流程之一。

  • 创建一个食谱,以帮助你立即进行 "最佳实践"。
  • 一旦你知道如何使用该最佳实践......创建一个配方,使你的工作流程更快。


---


你可以使用 "Preferences \ Plugins"(Mac)或 "Settings \ Plugins"(Windows)从IntelliJ内部安装Sensei ,然后只要搜索 "sensei secure code"。


这方面的源代码和配方可以在Secure Code Warrior GitHub账户的`sensei-blog-examples`仓库中找到,在`pojoexamples`模块中。




我们希望得到您的许可,向您发送有关我们产品和/或相关安全编码主题的信息。我们将始终以最谨慎的态度对待您的个人资料,绝不会将其出售给其他公司用于营销目的。

提交
要提交表格,请启用 "分析 "cookies。完成后,请随时再次禁用它们。