开源改变世界

编码风格、架构和很多小东西 #504

推推 grbl 3年前 (2023-01-30) 250次浏览
关闭
atlaste 打开了这个问题 2020 年 8 月 2 日 · 9条评论
关闭

编码风格、架构和很多小东西#504

atlaste 打开了这个问题 2020 年 8 月 2 日 · 9条评论

注释

编码风格、架构和很多小东西 #504
合作者

在过去的几周里,我花了很多时间在 grbl-esp32 代码库上。其中之一是我想自己使用 GRBL/ESP32,这意味着我还必须真正了解代码库才能实现代码更改和功能。目前,我还没有触及代码的逻辑,所以它的行为应该仍然与 devt 分支相同。

只是想分享这个,即使这仍然是一个 WIP(甚至还没有编译),并且有一些悬而未决的问题。

  • 在 vMicro 中编译。vMicro 是我所知道的用于 Arduino 项目的最受欢迎的 Arduino Visual Studio 插件……我正在使用它,因此使用它来构建代码是有意义的。
  • 文档。我为文档添加了一些 MD 文件。
  • 编码风格。我注意到代码库自从首次从 GRBL 移植以来已经有机地增长,代码库中具有不同的编码风格。对我来说,很难看到发生了什么,所以我添加了一个.clang-format文件并将其调整为我认为的主要编码风格。它并不完美,但至少它是一致的。
  • C/C++ 问题。我发现代码库中存在一些 C/C++ 问题。仅举几例:_因为全局命名空间中的前缀是保留的,而且#includeCPP 文件通常被认为是一种不好的做法。在我看到这些的地方,我消除了它们。
  • 类和文件名。帮助人们了解什么是什么的一种简单方法是将类放入同名文件中。此外,这有助于加快编译时间,因为编译器应该为每个类做更少的工作。
  • 包括。刚刚包含的大多数代码grbl.h基本上包含了所有内容。这意味着增量编译将被破坏,因为对于每个标头更改,编译器都必须重新编译很多。我更改了文件以包含那里所需的内容。
  • 命名空间。对我来说,将代码移动到它所属的位置是有意义的。因此,主轴进入 Spindles 命名空间,电机进入 Motors 命名空间等等。虽然这仍然是一个 WIP,但很难破译一切应该去哪里。
  • 常量与定义。目前,#define代码库中有大量的 也可以是类 (const/constexpr) 变量。后者的优点是您可以进行编译时检查(因为它们是强类型的)并且它们是有范围的。实际上,我通过将代码设为常量来修复一些隐式舍入错误。(就性能或内存使用而言,这无关紧要)。

正在进行的工作和未来的工作:

  • 混合 C 和 C++。旧的 GRBL 代码库是纯 C,其中混合了 C++。我也想将旧的 GRBL 代码更改为类 – 基本上这也是前缀无论如何都会发生的事情,所以我不妨推一下。这也是目前代码编译不通过的主要原因。我已经开始搬东西了,但这还需要更多的工作。
  • 设置和配置。我认为最好将编译时和运行时设置更好地分开。

我还有一些我自己无法弄清楚的悬而未决的问题:

  • 一般来说。我已经改变了很多结构;也许其中一些并不是真正的最佳选择。因此,我很好奇您的总体印象是什么。
  • 电磁笔。在我看来,电磁笔就像一种纺锤。为什么这是一个单独的文件?
  • 伺服。同样,我对 theservo_axis和 the有点困惑RcServoClass。为什么不是后者的一切?或者这仍然是一个 WIP?
  • 打印。我不太了解这些print.cpp功能,因为还有grbl_send一个似乎是更通用的变体。
  • 部分编译。我发现自己想知道能够禁用 WIFI 和 BT 等功能有什么好处。既然 ESP32 有所需的空间,为什么不简单地将其设置为运行时设置呢?在这里使用 ifdef 有什么好处吗?

我正在处理的分支可以在这里找到:https ://github.com/atlaste/Grbl_Esp32/tree/CleanupDevt/Grbl_Esp32 。再次强调,这仍然是一个 WIP,甚至还没有编译;需要做更多的工作,如果可能的话,我会继续投入时间。

编码风格、架构和很多小东西 #504
豪门571 评论了 2020 年 8 月 3 日 通过电子邮件
编码风格、架构和很多小东西 #504
所有者

@ggallant571

请在这个论坛上只接受建设性或积极的评论。

编码风格、架构和很多小东西 #504
合作者作者

只是想补充一点,这绝不是一种侮辱;相反。事实上,我很感激在创建我的 CNC 板时得到的帮助,所以我也决定做出贡献。虽然我在电子领域还是个新手,但人们确实认为我是 C++ 方面的专家级软件工程师。尽管如此,我始终觉得我的工作应该不言自明。

再次强调,这仍然是一个 WIP,我需要更多时间。

无论如何:如果巴特和米奇不欣赏我的帮助,那是我的损失,而且是我一个人的损失。在那种情况下,我们将关闭这张工单并保留它。

编码风格、架构和很多小东西 #504

@ggallant571
如果您如此自信,请将 grbl 移植到您选择的控制器,并以此方式命名。
作为用户,您或我无权批评建设性工作。尤其是,开发人员正在将宝贵的时间花在一件作品上,你我都在免费使用。您总是可以选择购买专业的数控控制器,如果您对他们的产品不满意,然后批评该公司。所以,让我们在这个论坛上以积极的方式交谈。

编码风格、架构和很多小东西 #504
豪门571 评论了 2020 年 8 月 3 日 通过电子邮件
编码风格、架构和很多小东西 #504
合作者作者

@ggallant571根据您的评论,我相信您错误地认为我介绍了类和(更一般的)C++ 代码之类的东西。我没有。GRBL_ESP32 不是 GRBL;它不断发展,已经有了用于主轴和电机的类,并使用了来自外部库的类。IMO 这是一个不错的选择,考虑到 ESP32 比 Arduino Uno 强大得多的事实,将更多的东西转移到运行时可配置在世界上都是有意义的。事实上,最近的一项功能就是spindle_select通话,这就是一个很好的例子。

显然,功能性和稳定性是数控机床的关键。绝对没有关于这个的讨论(我昨天跑了一个 800K 线刀具路径,想象一下如果它中途断了我会有什么感觉)。事实上,我相信如果我的工作做得好,在 PC 上运行“模拟”CNC 机器应该相对容易,这样可以更轻松、更快地进行测试,以确保未来版本的稳定性。但公平地说,这目前只是我的愿望清单上的东西,因为它很复杂。但是……在这样的设施出现之前,我也不认为彻底检查整个项目是明智的,尤其是逻辑。是的,

这就是为什么我从容易实现的目标开始:在不改变逻辑的情况下移动事物并添加明显的东西(缺少 ctors、虚拟析构函数、包含、命名空间、iso std 命名、样式等)。一步一步来。

编码风格、架构和很多小东西 #504

我认为这是一条值得走的路。Bart 和我已经朝着这个方向采取了一些措施,所以你肯定在一个看似合理的轨道上。我从很久以前就是一个彻头彻尾的 C 程序员,所以迁移到 C++ 引起了我一些担忧,但我最近对新设置架构的体验使我相信,如果使用得当,C++ 会非常有价值。我所说的“高雅”是指“避免使用庞大的外部框架”和“尽量不要使用太多的抽象和重载,以至于新读者无法弄清楚发生了什么”。

或许我们可以逐步进行,作为一系列 PR,一次呈现一个,并在其间进行审查,而不是使用包含一系列更改的分叉。这使得测试和审查变得更加容易,并允许一分为二来发现问题。以下是我对个别观点的评论:

在 vMicro 中编译。vMicro 是我所知道的用于 Arduino 项目的最受欢迎的 Arduino Visual Studio 插件……我正在使用它,因此使用它来构建代码是有意义的。

Bart 和我现在的大部分工作都使用 platformio。它可以从命令行使用,也可以集成在 VSCode IDE 中,或者以 VSCode 集成但带有外部编辑器的混合模式使用。platformio 的编译速度比 Arduino 快得多,这可能是因为它编译单个文件,而不是执行可疑的 Arduino 技巧,将所有内容连接到一个文件中并编译整个 wad。

VSCode 的受欢迎程度似乎突飞猛进,感觉是“初级支持的 IDE”的不错选择。

我不知道 vMicro 的特点是什么——但我确实认为支持两种环境已经够难了,所以添加第三种环境似乎是额外的工作,并没有太大好处。如果 vMicro 配置与 Arduino 相当,无需额外考虑,则无需考虑。我们必须支持 Arduino,因为它很熟悉,但我们真的不太喜欢它——当“一个构建来统治他们”时,适应新手的需求可能会消失(见下文)。

文档。我为文档添加了一些 MD 文件。

文档总是非常受欢迎!单独的公关。

编码风格。我注意到代码库自从首次从 GRBL 移植以来已经有机地增长,代码库中具有不同的编码风格。对我来说,很难看清发生了什么,所以我添加了一个 .clang-format 文件并将其调整为我认为的主要编码风格。它并不完美,但至少它是一致的。

那在我们的清单上,Bart 朝那个方向采取了一些步骤,但我们没有像我们应该的那样系统地使用它。我认为这将是出色的第一步。或许你可以确保它在 VSCode/platformio 环境下运行良好(VSCode 确实支持 clang-format),然后教我们如何有效地使用它。仅更改空格的全局重新格式化将是一个很好的补丁,以及某种用于检查提交的 git 自动化。

C/C++ 问题。我发现代码库中存在一些 C/C++ 问题。仅举几例:_ 作为全局命名空间中的前缀是保留的,#include CPP 文件通常被认为是一种不好的做法。在我看到这些的地方,我消除了它们。

这将是一个很好的第二个补丁。我同意包括 CPP 是不好的。我忘记了我们为什么这样做,但这可能与 Arduino IDE 的陌生性有关。如果您能找到适用于普通 Arduino 和 platformio 的更好解决方案,那将是一个很好的第二个补丁。第三个是消除 _ 前缀。

类和文件名。帮助人们了解什么是什么的一种简单方法是将类放入同名文件中。此外,这有助于加快编译时间,因为编译器应该为每个类做更少的工作。

这听起来不错。对人类的好处是显而易见的。你能解释一下它如何帮助编译器做更少的工作吗?我没有意识到 C++ 编译器知道文件名与其内容之间的关系。

包括。大多数代码只包含 grbl.h,它基本上包含了所有内容。这意味着增量编译将被破坏,因为对于每个标头更改,编译器都必须重新编译很多。我更改了文件以包含那里所需的内容。

哇,考虑到整理出在何处使用的内容和依赖关系图的难度,您将其成功实现给我留下了深刻的印象。我通常尝试那样做,特别是构建代码,使单个文件依赖于最少数量的包含——但在一个大项目中,随着时间的推移,保持这种纯度变得困难。我非常希望看到您的解决方案。

命名空间。对我来说,将代码移动到它所属的位置是有意义的。因此,主轴进入 Spindles 命名空间,电机进入 Motors 命名空间等等。虽然这仍然是一个 WIP,但很难破译一切应该去哪里。

我不确定你在这里建议什么。我们有主轴和电机类(可能需要改进);我们还需要为这些概念命名空间吗?

常量与定义。目前,代码库中有大量#define 也可能是类(const/constexpr)变量。后者的优点是您可以进行编译时检查(因为它们是强类型的)并且它们是有范围的。实际上,我通过将代码设为常量来修复一些隐式舍入错误。(就性能或内存使用而言,这无关紧要)。

是的,绝对想这样做 – 并且还在有意义的地方使用枚举而不是#defines。很想得到你的帮助 – 但作为小的有针对性的补丁而不是一个巨大的综合。

混合 C 和 C++。旧的 GRBL 代码库是纯 C,其中混合了 C++。我也想将旧的 GRBL 代码更改为类 – 基本上这也是前缀无论如何都会发生的事情,所以我不妨推动一下。这也是目前代码编译不通过的主要原因。我已经开始搬东西了,但这还需要更多的工作。

似乎是该系列的后期补丁之一。

设置和配置。我认为最好将编译时和运行时设置更好地分开。

这是一个讨论 slack 的好话题。我的目标是完全摆脱编译时设置,使“一个构建可以控制所有设置,通过加载文本文件进行配置”。这在 AVR 上是不可行的,这就是为什么经典的 GRBL – 甚至在更大程度上是 Marlin – 拥有所有编译时设置。但考虑到 SPI FLASH 芯片的成本非常低,它应该完全适用于 32 位处理器。

设置重写受到与经典 GRBL 保持兼容性的需要的限制 – 所以发件人不会中断 – 以及当前和即将推出的 WebUI 版本。这是一个微妙的舞蹈,但我们对结果非常满意。整体代码大小大幅减少,同时增加了功能并提高了可维护性。命名空间并不完美——我认为不可能设计出一个同时对每个可能的观点或用例都是最佳的命名空间模式——但到目前为止它感觉很愉快。

我还有一些我自己无法弄清楚的悬而未决的问题:

一般来说。我已经改变了很多结构;也许其中一些并不是真正的最佳选择。因此,我很好奇您的总体印象是什么。

上面有详细介绍。总的来说,你似乎正朝着我个人喜欢的方向前进——根据我与巴特的谈话,我怀疑他大体上也有类似的感觉。

电磁笔。在我看来,电磁笔就像一种纺锤。为什么这是一个单独的文件?

应该是历史吧 主轴是 WIP。如果您可以将笔合并到 Spindle 类结构中——或合并到改进的结构中——请试一试。但是作为一个单独的补丁(或系列)来做。

伺服。同样,我对 servo_axis 和 RcServoClass 有点困惑。为什么不是后者的一切?或者这仍然是一个 WIP?

在制品

打印。我不太了解 print.cpp 函数,因为还有 grbl_send 似乎是更通用的变体。

我不知道打印功能是从哪里来的;也许是经典 GRBL 的残余。我能找到的任何地方都没有使用它们。我删除了 print.cpp 和 print.h 并且它仍然编译 – 尽管我没有尝试#defines 的所有可能组合

部分编译。我发现自己想知道能够禁用 WIFI 和 BT 等功能有什么好处。既然 ESP32 有所需的空间,为什么不简单地将其设置为运行时设置呢?在这里使用 ifdef 有什么好处吗?

那是历史性的。如前所述,我们希望所有 ifdef 都消失。WebUI 集成的许多方面与类似的 grbl 代码是冗余的,因此可以进行改进和合并。事实上,我通过新设置实现的代码大小大幅缩减主要来自 WebUI 代码的改进,用数据迭代替换了大量的复制和粘贴代码。

我正在处理的分支可以在这里找到:https ://github.com/atlaste/Grbl_Esp32/tree/CleanupDevt/Grbl_Esp32 。再次强调,这仍然是一个 WIP,甚至还没有编译;需要做更多的工作,如果可能的话,我会继续投入时间。

我们应该开始增量 PR 的过程吗?

编码风格、架构和很多小东西 #504
合作者作者

刚刚注意到我必须要求一个 slack 邀请。不确定它是如何工作的……但请发送一个到:atlaste at yahoo dot com;可能更容易沟通。

或许我们可以逐步进行,作为一系列 PR,一次呈现一个,并在其间进行审查,而不是使用包含一系列更改的分支。这使得测试和审查变得更加容易,并允许一分为二来发现问题。

通常我不会同意这一点,因为这意味着我必须重新开始……但既然你们在我的董事会上帮了我这么多,我会破例。

Bart 和我现在的大部分工作都使用 platformio。它可以从命令行使用,也可以集成在 VSCode IDE 中,或者以 VSCode 集成但带有外部编辑器的混合模式使用。platformio 的编译速度比 Arduino 快得多,这可能是因为它编译单个文件,而不是执行可疑的 Arduino 技巧,将所有内容连接到一个文件中并编译整个 wad。

vMicro 也是这样做的。不过我不熟悉 platformio;会调查的。就个人而言,只要我可以使用 Visual Studio,我就很高兴(顺便说一句,这是与 VSCode 不同的产品)。我(和许多其他人)使用 vMicro 的唯一原因是因为 Arduino 支持不是开箱即用的。

文档。我为文档添加了一些 MD 文件。

文档总是非常受欢迎!单独的公关。

好的。也可能是讨论这个问题以获得总体方向的好时机。

小背景……在我的公司,我必须管理数百万个 loc 代码库。显然,我们有很多关于代码的文档。一开始很难做到的一件事是保持代码和文档同步——因为开发人员倾向于更改代码而不是搜索文档。

在某些时候,我们决定使用 MD 文件,并将它们放在与 cpp/h 文件相同的文件夹(具有相似的名称)中。虽然乍一看这可能看起来很混乱,但最大的好处是如果有关于代码的文档,它也会“在你面前”,这有助于保持代码和文档的同步。我强烈建议在这里也使用这种方法。

那在我们的清单上,Bart 朝那个方向采取了一些步骤,但我们没有像我们应该的那样系统地使用它。我认为这将是出色的第一步。或许你可以确保它在 VSCode/platformio 环境下运行良好(VSCode 确实支持 clang-format),然后教我们如何有效地使用它。

我会将其与 PR #1一起放在一张包含更多详细信息的单独票证中。
大家知道,虽然 VSCode 和 Visual Studio 都支持 clang-format,都不支持最新版本和功能。

仅更改空格的全局重新格式化将是一个很好的补丁,以及某种用于检查提交的 git 自动化。

我承认 CI 总体上是个好主意,我们在这里广泛使用它。然而,正确设置 CI 绝对是一项单独的任务,并且可能需要相当长的时间才能正确完成。我可以简要描述一下我们在公司所做的事情以提供一些想法。

CI 不应该提交;它会给开发人员带来奇怪的行为,因为你突然得到一个需要合并的新分支。所以,我们要做的是运行 clang-format,进行比较,然后检查它是否为空。但 CI 可以提供更多帮助:我们自动构建、进行静态代码分析、对所有单元测试运行代码覆盖并创建安装包。前段时间,我创建了https://github.com/atlaste/CPPCoverage,我们也将其与所有单元测试一起运行,以自动生成报告并检查一切是否仍在运行。因为我们经营一家公司,所以我们同意在主合并之间通常应该增加覆盖率(这不是强制执行的),所以随着时间的推移事情会变得更好。

这将是一个很好的第二个补丁。我同意包括 CPP 是不好的。我忘记了我们为什么这样做,但这可能与 Arduino IDE 的陌生性有关。如果您能找到适用于普通 Arduino 和 platformio 的更好解决方案,那将是一个很好的第二个补丁。

好的,让我们称之为 PR #2

第三个是消除 _ 前缀。

好的,让我们称之为 PR #3

类和文件名。帮助人们了解什么是什么的一种简单方法是将类放入同名文件中。此外,这有助于加快编译时间,因为编译器应该为每个类做更少的工作。

这听起来不错。对人类的好处是显而易见的。你能解释一下它如何帮助编译器做更少的工作吗?我没有意识到 C++ 编译器知道文件名与其内容之间的关系。

不,编译器不是。但是,如果您有一个包含所有定义的大头文件,则每次包含基类时都必须解析它(因为所有定义都在那里)。如果一个类被拆分,那么需要解析的代码量就很少了。

这个和上面的(PR #2 )有很多重叠,所以我将把它们结合起来。

命名空间。对我来说,将代码移动到它所属的位置是有意义的。因此,主轴进入 Spindles 命名空间,电机进入 Motors 命名空间等等。虽然这仍然是一个 WIP,但很难破译一切应该去哪里。

我不确定你在这里建议什么。我们有主轴和电机类(可能需要改进);我们还需要为这些概念命名空间吗?

让我们从这里开始,PR #4
为清楚起见,文件夹的名称通常是命名空间的名称。

我想介绍更多的概念:设置、机器、IO。让我们逐步执行此操作,看看哪些有效(哪些无效)。

常量与定义。目前,代码库中有大量#define 也可能是类(const/constexpr)变量。后者的优点是您可以进行编译时检查(因为它们是强类型的)并且它们是有范围的。实际上,我通过将代码设为常量来修复一些隐式舍入错误。(就性能或内存使用而言,这无关紧要)。

是的,绝对想这样做 – 并且还在有意义的地方使用枚举而不是#defines。很想得到你的帮助 – 但作为小的有针对性的补丁而不是一个巨大的综合。

混合 C 和 C++。旧的 GRBL 代码库是纯 C,其中混合了 C++。我也想将旧的 GRBL 代码更改为类 – 基本上这也是前缀无论如何都会发生的事情,所以我不妨推动一下。这也是目前代码编译不通过的主要原因。我已经开始搬东西了,但这还需要更多的工作。

似乎是该系列的后期补丁之一。

让我们称之为 PR #5并从简单的事情开始。Easy这里定义为:把代码放在类中,改成静态成员。这样,命名将是正确的(主要原因见下文),即使代码的行为完全相同。

设置和配置。我认为最好将编译时和运行时设置更好地分开。

这是一个讨论 slack 的好话题。

是的,我相信关于这个主题的更多讨论是个好主意。

哇,考虑到整理出在何处使用的内容和依赖关系图的难度,您将其成功实现给我留下了深刻的印象。我通常尝试那样做,特别是构建代码,使单个文件依赖于最少数量的包含——但在一个大项目中,随着时间的推移,保持这种纯度变得困难。我非常希望看到您的解决方案。

一旦代码位于正确的类和命名空间中,这实际上并不难。如果名称空间与文件夹对应,类与文件对应,您只需浏览代码并查看需要的内容。比如Planner::cycle_reinitialize()代码中使用了say,很明显Planner.h需要包含。因此,这也应该在 C 代码移至类之后完成。完成后,如果您想知道每个包含是否真的有必要,请将其删除并重新编译文件。

What remains are the #define’s of the machine/settings configuration and the platform includes. For the configuration, that’s usually an #ifndef#define, which I combined in a Config.h. I wasn’t happy with this, because it creates implicit dependencies between files but it’s still a fine first step (I think a better approach would be to use name hiding – but let’s save that for another day).

Anyways, let’s call this PR #6.

In general. I’ve changed quite a bit of the structure; perhaps some of them are not really the best choice. I’m therefore curious what your overall impression is.

Addressed above in detail. Overall, you seem to be moving in a direction that I personally like – and based on my conversations with Bart, I suspect that he feels generally similar.

听起来还不错!

电磁笔。在我看来,电磁笔就像一种纺锤。为什么这是一个单独的文件?

应该是历史吧 主轴是 WIP。如果您可以将笔合并到 Spindle 类结构中——或合并到改进的结构中——请试一试。但是作为一个单独的补丁(或系列)来做。

公关#7

伺服。同样,我对 servo_axis 和 RcServoClass 有点困惑。为什么不是后者的一切?或者这仍然是一个 WIP?

在制品

公关#8

打印。我不太了解 print.cpp 函数,因为还有 grbl_send 似乎是更通用的变体。

I don’t know where the print functions came from; perhaps a remnant from classic GRBL. They aren’t used anywhere that I can find. I removed print.cpp and print.h and it still compiled – although I have not tried every possible combination of #defines

Let’s just delete them. ESP32 <Print.h> is also included elsewhere for InputBuffer, so it just adds to the confusion.

Shall we start the process of incremental PRs?

Let me start by joining on Slack, and then I’ll start with #1 above.

编码风格、架构和很多小东西 #504
Owner

Closing….discussion moved to Slack

喜欢 (0)