【问题标题】:How to document code with variants? (JavaDoc for ifs)如何用变体记录代码? (ifs 的 JavaDoc)
【发布时间】:2015-02-03 16:48:38
【问题描述】:

tl;dr 是否有用于ifs 的 JavaDoc?

简介

我正在为多个客户编写企业应用程序。 99% 的代码库是共享的,但时不时会有这样的变体:

if (user.hasModule(REPORTS)) { 
  ...conditional code... 
}

我现在想为用户记录所有这些变体。从文档中应该清楚如果我打开例如会发生什么。模块REPORTS。我相信这个文档应该以 JavaDoc 的方式编写——这意味着它应该尽可能接近条件代码。它可能看起来像这样:

/** Enables the cool report. */
if (user.hasModule(REPORTS)) { 
  ...conditional code... 
}

或者这个:

@Doc(text="Enables the cool report.")
if (user.hasModule(REPORTS)) { 
  ...conditional code... 
}

或者这样:

if (user.hasModule(REPORTS, "Enables the cool report.")) { 
  ...conditional code... 
}

结果基本上是每个模块的 cmets 列表。

Module    | Comments
----------+--------------------
REPORTS   | Enables the cool report.
REPORTS   | Allows exporting the reports.
IMPORT    | Allows importing the data.

问题

如何从代码中收集所有文档cmets?我正在考虑几种方法:

源码提取

这将需要一个解析器来遍历源代码,找到所有这些条件并获取对(模块、注释)。但是,它必须与编译器挂钩,以避免出现奇怪的格式问题(长行中间的换行符等)。

动态提取

在运行时调用user.hasModule() 时,它会记录其实际参数,然后使用此日志来构建文档。因此,例如在 beta 测试期间,收集文档,然后将其构建到最终版本中。缺点很明显:如果系统的某个部分未被访问,则不会记录在案。

字节码提取

为了避免乱七八糟的源代码,可以直接获取编译后的字节码,用ASM 之类的东西对其进行分析,然后找到所有调用user.hasModule() 的地方。这是我最喜欢的版本,但是卡住了 以及在调用invoke_static 时如何确定VM 堆栈顶部的实际值是多少。必须有一个更简单的方法:)

总结

有这方面的工具吗?我错过了一种简单的方法吗?我在尝试记录这些情况时是否完全被误导了?谢谢!

【问题讨论】:

  • 我不明白你想要做什么。您想为其他开发人员记录 if 内部发生的事情吗?或者您想在运行时为用户生成文档,具体取决于启用的模块?这对我来说听起来有点奇怪。
  • 后者 - 用户文档。
  • 那么 Javadoc 不是您的首选工具。它用于记录代码,而不是供用户阅读。这是一种技术性的方式。
  • JavaDoc 也绝对不能记录像 ifs 这样的代码结构,所以我要寻找的不是 JavaDoc,而是具有类似精神的东西。
  • 我仍然不明白您为什么要为用户记录代码结构。他对代码中发生的事情不感兴趣,他想知道软件是如何工作的。

标签: java javadoc


【解决方案1】:

我认为您的代码中缺少一个概念。

您的模块看起来很像安全,每次使用看起来很像权限

如果您要以这种方式对事物进行建模,您可以将有关每个模块的用途/权限的知识集中到一个位置。这样就不需要通过静态分析来扫描代码了。

下面的方案使用 Java 类型系统来确保您不能在没有首先为该模块创建新权限的情况下为该模块添加 if 语句。

使用一点 java 循环遍历枚举值,可以很容易地从此代码生成权限和描述的完整列表。

public interface User {
 public <T extends Module<T>> boolean hasPermission(Module<T> module, Permission<T> usage);
 }

public interface Permission<T extends Module<T>> {
  String describe();
}

enum Reports implements Module<Reports> {
  REPORTS
}

enum ReportsPermissions implements Permission<Reports> {
   ENABLE_COOL_REPORT("Enables the cools reports"),
   ALLOWS_EXPORTING_THE_REPORTS("Allow exports the cools reports");

   private final String description;

    ReportsPermissions(String description) {
      this.description = description;
    }

    @Override
    public String describe() {
      return description;
     } 
  }

  enum ImportPermissions implements Permission<Import> {
    ALLOWS_IMPORTING("Allows importing the data.");
    etc
  }

这很可能是矫枉过正 - 一个简单的枚举没有所有的自我输入废话可能就足够了。

if user.hasPermission(Permissions.Export)

【讨论】:

  • 这正是模块定义现在的工作方式。我称它为 modules,因为还有 permissions,是的,问题也与它们有关。
  • 然而,我们正在尝试记录所有的 if - 假设有 100 个 if 使用每个枚举值!
  • 我的意思是,每个“如果”都必须与一些可观察的功能相关。您应该创建一个该功能的模型 - 目前模块概念没有捕捉到这一点,您需要更深入。
  • 所以你基本上有一个所有 if 的枚举?
  • 实际上,可能它不会是 1:1,因为可观察的功能可能需要在多个位置进行分支,但是可以创建 if 语句试图实现的模型并记录它。
【解决方案2】:

我会将user.hasModule(REPORTS)==true 时执行的代码放入aspect。然后用 JavaDoc 记录方面。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-25
    • 2010-12-13
    • 2022-08-22
    • 2020-10-13
    • 2010-11-06
    • 1970-01-01
    • 2011-06-11
    相关资源
    最近更新 更多