开发区域

先进与MATLAB软件开发

我们都有问题

我们中间谁没有问题,amirite ?让我们花点时间和承认这个事实,我认为我们总是可以更诚实和理解我们所有的独特的问题和我们所展示的各种特性。虽然我们都可以提供理解和恩典,我们所面临的一些问题可能是重要的快速解决,和一些我们也许可以选择工作的时候是正确的。

…因此它是与我们的代码。问题,错误,和其他最优结构出现在任何严重的代码库。你们中的许多人已经意识到在MATLAB代码分析器的特点做一个伟大的工作提醒你你的问题在MATLAB中直接编辑器。然而,有时问题还可以在代码库中通过一些微妙的手段,甚至包括简单未能采取行动当一个有用的编辑器是想告诉我我有一个问题在我的代码。

然而,在R2022b有巨大的改善识别和解决这些代码的编程接口问题。事实上,这个新界面本身就是一个新函数codeIssues!

这个新的API的代码分析器是一个词——强大。现在让我们了解一下如何使用这个质量构建到您的项目。从另一个看我们的标准mini-codebase质-弹。最近我们在描述的过程中也谈到这些新MATLAB构建工具。这个代码非常简单。它包括一个模拟器,一个函数返回一些设计常量(弹性系数、阻尼系数等),和一些测试。

开始这样的代码库,就叫codeIssues文件夹你想分析:

你可以看到,只有一个简单的调用codeIssues你可以很快得到所有细节的概述一个静态分析器的梦想。你可以很容易地深入分析的文件,配置,和非常方便的表的问题发现,以及任何问题,抑制通过抑制语法编辑器。如果你在MATLAB你甚至可以点击每一期马上开始在MATLAB编辑器,它可以是固定的或隐含的如果需要的话。

现在在我们的指尖,与这个美丽的API和构建工具,我们可以锁定代码更健壮的、自动化的方式。我们可以开始大约年底离开我们的构建刀架用下面的墨西哥人构建文件和一个测试任务:

函数计划= = buildplan构建文件计划(localfunctions);计划(“测试”)。依赖项=“墨西哥人”;计划。DefaultTasks =“测试”;结束函数mexTask (~)%编译墨西哥人文件墨西哥人墨西哥人/ convec.c-outdir工具箱/;结束函数testTask (~)%运行单元测试结果= runtests;disp(结果);assertSuccess(结果);结束

让我们添加一个“codeIssues”任务构建通过创建一个新的本地函数codeIssuesTask:

函数codeIssuesTask (~)%得到所有问题在工具箱中allIssues = codeIssues (“工具箱”);%断言没有错误蠕变到代码库errorIdx = allIssues.Issues。严重程度= =“错误”;错误= allIssues.Issues (errorIdx:);otherIssues = allIssues.Issues (~ errorIdx:);如果~ isempty(错误)disp (发现代码中的关键错误:“);disp(错误);其他的disp (“没有发现关键错误。”);结束%显示所有其他问题如果~ isempty (otherIssues) disp (其他问题:“)disp (otherIssues);其他的disp (“没有发现其他问题。哇,对你有好处!”)结束断言(isempty(错误));结束

这是很简单的,我们只是想找到“工具箱”文件夹下的所有问题和抛出一个断言错误如果其中任何一个的严重性“错误”。这是最快的赢得你可以申请代码库来构建质量。这个可以找到语法和其他静态错误,甚至不用写或者运行一个测试。真的是没有理由我们不能这个任务应用到每个项目。成本几乎没有,可以非常有效地发现bug。注意,我们把它作为一个默认的任务在我们构建文件:

计划。DefaultTasks = [“codeIssues”“测试”];

…和我们现在有这个开发过程集成到我们的标准检查。显示这个先放一个文件与一个错误代码,然后我们可以调用构建工具:

函数syntaxError disp (“忘记了关闭括号!”
拷贝文件.changes / syntaxError.m工具箱/ syntaxError.m试一试buildtool前女友disp (ex.getReport (“基本”));结束
* *开始codeIssues失败!发现关键错误代码:位置严重描述CheckID LineStart LineEnd ColumnStart ColumnEnd FullFilename售予________ ______________________________________________________________________________累积_____ ___________ _________”_______________________________________________________________________________________________ syntaxError。m“错误”“(可能错过关闭),造成无效语法行结束。”EOLPAR 3 3 5 5 "/Users/acampbel/Library/CloudStorage/OneDrive-MathWorks/repos/msd_blog2/toolbox/syntaxError.m" Other Issues: Location Severity Description CheckID LineStart LineEnd ColumnStart ColumnEnd FullFilename __________________________ ________ _____________________________________________ _______ _________ _______ ___________ _________ __________________________________________________________________________________________________________ "springMassDamperDesign.m" warning "Value assigned to variable might be unused." NASGU 4 4 3 3 "/Users/acampbel/Library/CloudStorage/OneDrive-MathWorks/repos/msd_blog2/toolbox/springMassDamperDesign.m" "springMassDamperDesign.m" warning "Value assigned to variable might be unused." NASGU 6 6 3 3 "/Users/acampbel/Library/CloudStorage/OneDrive-MathWorks/repos/msd_blog2/toolbox/springMassDamperDesign.m" ## ----------------------------------------------------------------------------- ## Error using assert ## Assertion failed. ## ## Error in buildfile>codeIssuesTask (line 67) ## assert(isempty(errors)); ## ----------------------------------------------------------------------------- ** Failed codeIssues Error using buildtool Build failed.

构建工具所做的参与我们的开发过程停下来当它看到我们有一些重要的语法错误地址。

让我们删除双层错误我们可以看到“codeIssues”任务成功完成。当我们这样做我们也成功地执行其他“墨西哥人”和“测试”任务来完成整个工作流程。

删除工具箱/ syntaxError.mbuildtool
* *开始codeIssues没有发现关键错误。其他问题:位置严重描述CheckID LineStart LineEnd ColumnStart ColumnEnd FullFilename __________________________ ________ _____________________________________________累积_____ ___________ _________”__________________________________________________________________________________________________________ springMassDamperDesign。m“警告”值分配给变量可能是未使用的。”NASGU 4 4 3 3 "/Users/acampbel/Library/CloudStorage/OneDrive-MathWorks/repos/msd_blog2/toolbox/springMassDamperDesign.m" "springMassDamperDesign.m" warning "Value assigned to variable might be unused." NASGU 6 6 3 3 "/Users/acampbel/Library/CloudStorage/OneDrive-MathWorks/repos/msd_blog2/toolbox/springMassDamperDesign.m" ** Finished codeIssues ** Starting mex Building with 'Xcode with Clang'. MEX completed successfully. ** Finished mex ** Starting test Setting up ProjectFixture Done setting up ProjectFixture: Project 'msd' is already loaded. Set up is not required. __________ Running convecTest . Done convecTest __________ Running designTest ... Done designTest __________ Tearing down ProjectFixture Done tearing down ProjectFixture: Teardown is not required. __________ 1×4 TestResult array with properties: Name Passed Failed Incomplete Duration Details Totals: 4 Passed, 0 Failed, 0 Incomplete. 0.22349 seconds testing time. ** Finished test

最后一件事

现在我们有你们都设置好和舒适的保护静态分析给你。然而,尽管我们失败在静态分析错误,我仍然不舒服是多么容易继续添加构造我的代码,导致静态分析警告,通常指向程序中的实际问题。我们也可以建立在警告如果我们想失败,但是我并不想从这个想法的开始。

很清楚的是,我们希望这个保护full-on-bonafide错误,这几乎都是错误的。我们遇到一个问题但当一个代码库已经有库存的警告。是奇妙的经历,库存和修复所有的警告。事实上,新的代码分析工具使得在很多情况下非常容易!然而,你可能不是现在。你的代码库可能很大,你可能想要或需要投入更多的时间到这个活动。所以我们的第一个裂纹在这个失败的构建只与一个“错误”问题严重。

然而,如果你知道我你知道我喜欢偷偷的最后一件事。如果我们接受了我们所有的代码库中当前警告,但想锁定我们的代码库,这样避免引入新的警告吗?对我来说,这听起来像是一个好主意。我们可以降低我们的警告,防止流入新的警告,可以删除现有的警告随着时间的推移,通过与代码库进行交互。我们如何做呢?我们可以利用codeIssues编程API的力量!

我们可以通过捕获和保存现有警告基线的已知问题。MATLAB表,这些问题是一个很好的表示保存在一个*。csv或*。xlsx文件。保存在这个格式使他们很容易调整,打开MATLAB之外,甚至删除问题已经解决。

为此,我们只需要做出一些调整问题表。我们需要覆盖位置变量的相对路径文件,删除FullFilename数据类型变量,使快速调整,以便好CSV。相对文件名调整很重要,因为我们希望能够比较这些结果在不同的机器和环境的完整路径可能不同。这种环境包括个人的桌面工程师以及不同在CI系统建立代理商。

这个函数如下:

函数茶= preprocessIssues(茶)%的问题表通过一些小的调整有助于基线%覆盖与相对路径位置字段,并去除绝对路径basePath =字符串(pwd) + filesep;茶。位置= erase(theTable.FullFilename, basePath); theTable.Properties.VariableNames{“位置”}=“RelativeFilename”;茶。FullFilename = [];%将严重程度分类,序列化字符串茶。=严重程度分类(theTable.Severity);结束

…现在我们可以使用此函数创建一个新的任务构建文件中生成一个新的基准:

函数captureWarningsBaselineTask (~)%捕获当前codeIssues警告并创建一个基线csv文件allIssues = codeIssues (“工具箱”);warningIdx = allIssues.Issues。严重程度= =“警告”;警告= allIssues.Issues (warningIdx:);警告= preprocessIssues(警告);如果~ isempty(警告)disp (“拯救一个新的“”knownIssues。csv基线文件”(警告)+ +高度“代码警告”)writetable(警告,“knownIssues.csv”);其他的disp (“没有创建一个基线警告”)结束结束

让我们做它!

buildtoolcaptureWarningsBaseline
* * captureWarningsBaseline保存一个新的“knownIssues开始。csv“基线文件2 * *完成captureWarningsBaseline代码警告

我现在看到csv文件。我们可以留意一下:

类型knownIssues.csv
RelativeFilename、严重性、描述、CheckID LineStart, LineEnd, ColumnStart, ColumnEnd工具箱/ springMassDamperDesign。米、警告值分配给变量可能是未使用的。NASGU 4、4、3、3工具箱/ springMassDamperDesign。m、警告值分配给变量可能闲置,NASGU、6、6、3 3

美丽。在这种情况下,我们只有两个小警告,我不想考虑。然而,现在我们可以调整“codeIssues”任务来阻止我引入新的东西:

函数codeIssuesTask (~)%得到所有问题在工具箱中allIssues = codeIssues (“工具箱”);%断言没有错误蠕变到代码库errorIdx = allIssues.Issues。严重程度= =“错误”;错误= allIssues.Issues (errorIdx:);otherIssues = allIssues.Issues (~ errorIdx:);如果~ isempty(错误)disp (“失败!发现关键错误代码:“);disp(错误);其他的disp (“没有发现关键错误。”);结束%基线负荷已知的警告newWarnings = [];如果isfile (“knownIssues.csv”)otherIssues = preprocessIssues (otherIssues);%加载基线文件选择= detectImportOptions (“knownIssues.csv”);类型= varfun (@class otherIssues,“OutputFormat”,“细胞”);选择。VariableTypes =类型;knownIssues = readtable (“knownIssues.csv”、选择);%的新警告减去基线的已知问题otherIssues = setdiff (otherIssues knownIssues);newWarningIdx = otherIssues。严重程度= =“警告”;newWarnings = otherIssues (newWarningIdx:);如果~ isempty (newWarnings) disp (“失败!在代码中找到了新的警告:“);disp (newWarnings);其他的disp (“没有发现新的警告。”);结束otherIssues = [knownIssues;otherIssues (~ newWarningIdx:)];结束%显示所有其他问题如果~ isempty (otherIssues) disp (其他问题:“)disp (otherIssues);其他的disp (“没有发现其他问题。哇,对你有好处!”)结束断言(isempty(错误));断言(isempty (newWarnings));结束

现在加载问题和一个setdiff忽略那些已知和捕捉基线CSV文件。这样,至少从现在起我不会引入任何新的警告代码库。它只能从这里得到更好的。同样,如果我改变一些文件,现有的预警,有一个体面的机会,我构建工具将我大喊大叫,因为现有的警告略有不同。例如它可能是在一个不同的线由于在文件所做的更改。

如果发生这种情况,太棒了!让我清理或抑制的警告而我有文件打开和修改。这是一个特征不是一个错误。最糟糕的情况,我总能捕捉到一个新的基线,如果我真的不能立即调查它,但是我喜欢这种方法帮我清洁我的代码通过这个过程。

这看起来像什么呢?让我们添加一个文件到代码库的新警告:

函数codeWarning anUnusedVariable =“未使用”;

…并调用构建:

拷贝文件.changes / codeWarning.m工具箱/ codeWarning.m试一试buildtool前女友disp (ex.getReport (“基本”));结束删除工具箱/ codeWarning.m
* *开始codeIssues没有发现关键错误。失败了!在代码中找到了新的警告:RelativeFilename严重性描述CheckID LineStart LineEnd ColumnStart ColumnEnd _______________________ ________ _____________________________________________累积_____ ___________”工具箱/ codeWarning上面。m“警告”值分配给变量可能是未使用的。”NASGU 3 3 1 16 Other Issues: RelativeFilename Severity Description CheckID LineStart LineEnd ColumnStart ColumnEnd __________________________________ ________ _____________________________________________ _______ _________ _______ ___________ _________ "toolbox/springMassDamperDesign.m" warning "Value assigned to variable might be unused." NASGU 4 4 3 3 "toolbox/springMassDamperDesign.m" warning "Value assigned to variable might be unused." NASGU 6 6 3 3 ## ----------------------------------------------------------------------------- ## Error using assert ## Assertion failed. ## ## Error in buildfile>codeIssuesTask (line 68) ## assert(isempty(newWarnings)); ## ----------------------------------------------------------------------------- ** Failed codeIssues Error using buildtool Build failed.

爱它!我现在保护自己。我可以利用这个标准工具箱开发过程确保随着时间的推移,我的代码只会变得更好,不是更糟。你也可以想象调整这个失败或以其他方式通知当警告远离已知问题,这样我们有一些压力,有助于确保锁定的手抓得越来越紧随着时间的推移。供参考,这是今天讨论的最终构建文件用于此工作流:

函数计划= = buildplan构建文件计划(localfunctions);计划(“测试”)。依赖项=“墨西哥人”;计划。DefaultTasks = [“codeIssues”“测试”];结束函数mexTask (~)%编译墨西哥人文件墨西哥人墨西哥人/ convec.c-outdir工具箱/;结束函数testTask (~)%运行单元测试结果= runtests;disp(结果);assertSuccess(结果);结束函数codeIssuesTask (~)%得到所有问题在工具箱中allIssues = codeIssues (“工具箱”);%断言没有错误蠕变到代码库errorIdx = allIssues.Issues。严重程度= =“错误”;错误= allIssues.Issues (errorIdx:);otherIssues = allIssues.Issues (~ errorIdx:);如果~ isempty(错误)disp (“失败!发现关键错误代码:“);disp(错误);其他的disp (“没有发现关键错误。”);结束%基线负荷已知的警告newWarnings = [];如果isfile (“knownIssues.csv”)otherIssues = preprocessIssues (otherIssues);选择= detectImportOptions (“knownIssues.csv”);类型= varfun (@class otherIssues,“OutputFormat”,“细胞”);选择。VariableTypes =类型;knownIssues = readtable (“knownIssues.csv”、选择);otherIssues = setdiff (otherIssues knownIssues);newWarningIdx = otherIssues。严重程度= =“警告”;newWarnings = otherIssues (newWarningIdx:);如果~ isempty (newWarnings) disp (“失败!在代码中找到了新的警告:“);disp (newWarnings);其他的disp (“没有发现新的警告。”);结束otherIssues = [knownIssues;otherIssues (~ newWarningIdx:)];结束%显示所有其他问题如果~ isempty (otherIssues) disp (其他问题:“)disp (otherIssues);其他的disp (“没有发现其他问题。哇,对你有好处!”)结束断言(isempty(错误));断言(isempty (newWarnings));结束函数captureWarningsBaselineTask (~)%捕获当前codeIssues警告并创建一个基线csv文件allIssues = codeIssues (“工具箱”);warningIdx = allIssues.Issues。严重程度= =“警告”;警告= allIssues.Issues (warningIdx:);警告= preprocessIssues(警告);如果~ isempty(警告)disp (“拯救一个新的“”knownIssues。csv基线文件”(警告)+ +高度“代码警告”)writetable(警告,“knownIssues.csv”);其他的disp (“没有创建一个基线警告”)结束结束函数茶= preprocessIssues(茶)%的问题表通过一些小的调整有助于基线%覆盖与相对路径位置字段,并去除绝对路径basePath =字符串(pwd) + filesep;茶。位置= erase(theTable.FullFilename, basePath); theTable.Properties.VariableNames{“位置”}=“RelativeFilename”;茶。FullFilename = [];%将严重程度分类,序列化字符串茶。=严重程度分类(theTable.Severity);结束

你有它,有一个干净的API MATLAB代码分析和标准方法包括使用构建工具的开发过程。我几乎能感觉到质量越来越高!

人,有这么多的博客在未来。有更多的讨论在我们如何利用新的和改进工具为你的MATLAB开发清洁的构建和测试管道项目。另外,我所以兴奋的一些很了不起的进展我们将很快能够分享。扣,我们会讨论高质量测试和自动化的发展在这个博客。留下您的见解、工具和工作流使用MATLAB作为您开发专业项目。




发表与MATLAB®R2022b

|

评论

留下你的评论,请点击在这里MathWorks账户登录或创建一个新的。