You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求D365中查找全项目模块注释代码的可运行脚本及最佳实践

查找Dynamics 365项目中注释代码的自动化方案与最佳实践

可运行的X++自动化脚本(适用于Dynamics 365 Finance and Operations)

以下脚本可遍历指定模块下的所有类,提取单行注释(//)和多行注释(/* */),并输出到本地报告文件:

class FindCommentedCode
{
    public static void main(Args _args)
    {
        // 替换为目标模块名称,例如"Sales"、"SupplyChain"
        str targetModule = "Sales";
        TreeNode moduleNode;
        TreeNodeIterator nodeIterator;
        TreeNode currentNode;
        str className;
        str codeSource;
        System.IO.StreamWriter reportWriter;
        str outputFilePath = @"C:\D365_Commented_Code_Report.txt";

        try
        {
            // 初始化报告文件
            reportWriter = new System.IO.StreamWriter(outputFilePath, false, System.Text.Encoding::UTF8);
            reportWriter.WriteLine("=== Dynamics 365 注释代码扫描报告 ===");
            reportWriter.WriteLine("扫描模块: " + targetModule);
            reportWriter.WriteLine("扫描时间: " + DateTimeUtil::toString(DateTimeUtil::utcNow(), DateTimeUtil::getUserPreferredDateTimeFormat()));
            reportWriter.WriteLine("-----------------------------------");

            // 定位目标模块的类节点
            moduleNode = TreeNode::findNode(@"\Classes\" + targetModule);
            if (!moduleNode)
            {
                reportWriter.WriteLine("错误: 未找到指定模块 " + targetModule);
                info("未找到指定模块,请检查模块名称是否正确");
                return;
            }

            // 遍历模块下所有节点
            nodeIterator = moduleNode.AOTiterator();
            currentNode = nodeIterator.next();

            while (currentNode)
            {
                // 仅处理类类型节点
                if (currentNode.treeNodeType() == TreeNodeType::Class)
                {
                    className = currentNode.AOTname();
                    reportWriter.WriteLine("\n类名称: " + className);
                    reportWriter.WriteLine("-----------------------------------");

                    // 获取类的源代码
                    codeSource = currentNode.AOTgetSource();
                    if (codeSource)
                    {
                        List codeLines = strSplit(codeSource, '\n');
                        ListEnumerator lineEnumerator = codeLines.getEnumerator();
                        int lineNumber = 0;

                        while (lineEnumerator.moveNext())
                        {
                            lineNumber++;
                            str currentLine = strTrim(lineEnumerator.current());

                            // 识别常见注释格式
                            if (strStartsWith(currentLine, "//") || strStartsWith(currentLine, "/*") || strContains(currentLine, "*/"))
                            {
                                reportWriter.WriteLine("行号 " + int2str(lineNumber) + ": " + currentLine);
                            }
                        }
                    }
                }
                currentNode = nodeIterator.next();
            }

            reportWriter.WriteLine("\n=== 扫描完成 ===");
            info("扫描完成,报告已保存至: " + outputFilePath);
        }
        catch (Exception::Error)
        {
            error("扫描出错: " + errorMessage());
        }
        finally
        {
            if (reportWriter)
            {
                reportWriter.Close();
                reportWriter.Dispose();
            }
        }
    }
}

使用说明

  1. 在Dynamics 365 F&O的AOT中新建X++类,将上述代码粘贴进去。
  2. 修改targetModule为你需要扫描的模块名称,调整outputFilePath为本地可访问的路径。
  3. 运行类的main方法,等待扫描完成后查看生成的报告文件。

注释代码管理的最佳实践

  • 定期清理冗余注释:每季度或迭代结束后,清理调试遗留的临时注释、重复代码注释,只保留对业务逻辑有解释价值的注释。
  • 统一注释规范:定义团队统一的注释风格,例如业务注释前缀// Business:、调试临时注释前缀// Debug:、待办事项前缀// TODO:,便于自动化工具识别和分类。
  • 集成到CI/CD流程:将注释扫描脚本集成到持续集成管道中,每次代码提交时自动检测新增的无效注释,避免冗余代码进入生产环境。
  • 优先重构而非注释:如果一段代码需要大量注释才能说明逻辑,优先重构代码结构(拆分方法、重命名变量),提升代码本身的可读性。
  • 区分注释用途:不要用注释替代文档,核心业务逻辑的注释应同步到项目文档中,代码内注释仅用于补充代码无法直接表达的背景信息。

内容的提问来源于stack exchange,提问作者Dhanush Rajashekar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 15:25:36