<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Dmitry Zhifarsky</title>
    <description>The latest articles on Forem by Dmitry Zhifarsky (@incendial).</description>
    <link>https://forem.com/incendial</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F638905%2Fc354a6b6-4a43-471c-91fe-e9049f13e26a.jpg</url>
      <title>Forem: Dmitry Zhifarsky</title>
      <link>https://forem.com/incendial</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/incendial"/>
    <language>en</language>
    <item>
      <title>Finding Unused Files With Dart Code Metrics</title>
      <dc:creator>Dmitry Zhifarsky</dc:creator>
      <pubDate>Sat, 12 Jun 2021 09:11:32 +0000</pubDate>
      <link>https://forem.com/incendial/finding-unused-files-with-dart-code-metrics-445h</link>
      <guid>https://forem.com/incendial/finding-unused-files-with-dart-code-metrics-445h</guid>
      <description>&lt;p&gt;In our &lt;a href="https://dev.to/incendial/improving-code-quality-with-dart-code-metrics-31dn"&gt;previous article&lt;/a&gt;, we announced &lt;a href="https://github.com/dart-code-checker/dart-code-metrics"&gt;Dart Code Metrics&lt;/a&gt;, a static code analysis tool. Initially, its task was to collect and represent code metrics, as well as provide additional rules for the analyzer with a more flexible configuration. However, we decided to push it to the next level.&lt;/p&gt;

&lt;p&gt;In this article, we’ll go over one of the first commands, &lt;code&gt;check-unused-files&lt;/code&gt;, to search for unused Dart files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart run dart_code_metrics:metrics check-unused-files lib

&lt;span class="c"&gt;# or for a Flutter package&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;flutter pub run dart_code_metrics:metrics check-unused-files lib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full command description:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Check unused &lt;span class="k"&gt;*&lt;/span&gt;.dart files.

Usage: metrics check-unused-files &lt;span class="o"&gt;[&lt;/span&gt;arguments] &amp;lt;directories&amp;gt;
&lt;span class="nt"&gt;-h&lt;/span&gt;, &lt;span class="nt"&gt;--help&lt;/span&gt;                                        Print this usage information.


&lt;span class="nt"&gt;-r&lt;/span&gt;, &lt;span class="nt"&gt;--reporter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;console&amp;gt;                          The format of the output of the analysis.
                                                  &lt;span class="o"&gt;[&lt;/span&gt;console &lt;span class="o"&gt;(&lt;/span&gt;default&lt;span class="o"&gt;)&lt;/span&gt;, json]


    &lt;span class="nt"&gt;--root-folder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;./&amp;gt;                            Root folder.
    &lt;span class="nt"&gt;--exclude&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;&lt;span class="o"&gt;{&lt;/span&gt;/&lt;span class="k"&gt;**&lt;/span&gt;.g.dart,/&lt;span class="k"&gt;**&lt;/span&gt;.template.dart&lt;span class="o"&gt;}&amp;gt;&lt;/span&gt;    File paths &lt;span class="k"&gt;in &lt;/span&gt;Glob syntax to be excluded.
                                                  &lt;span class="o"&gt;(&lt;/span&gt;defaults to &lt;span class="s2"&gt;"{/**.g.dart,/**.template.dart}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When will you need to search for unused files?&lt;/p&gt;

&lt;p&gt;Two scenarios come to mind right away:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;When you need to do a step-by-step refactoring on a large codebase with moving files and it's difficult to know if all the files are being used correctly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Code generation, which creates extra files, is popular in Dart. Sometimes it can be difficult to know if these files are no longer in use.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  So what’s under the hood?
&lt;/h2&gt;

&lt;p&gt;The search for unused files starts with listing the files within the passed (sub)directories. Then we check the list of imports, exports, and part-directives in each file. If the imported/exported file belongs to this package, then it’s marked accordingly: “in use.” Files with exports or the main function are separately marked as entry points and “in use.”&lt;/p&gt;

&lt;p&gt;After that, unused files are displayed in the following format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Unused file: &amp;lt;path_to_file&amp;gt;
   ...
Unused file: &amp;lt;path_to_file&amp;gt;

Total unused files - N
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's take a project with the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; lib/
   src/
     entry_point.dart
     first_file.dart
     second_file.dart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And with file content like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;entry_point.dart&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'first_file.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="c1"&gt;// some code&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;first_file.dart&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SomeClass&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="c1"&gt;// some code&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;second_file.dart&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'first_file.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SomeOtherClass&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="c1"&gt;// some code&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can call the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart run dart_code_metrics:metrics check-unused-files lib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the first step, the algorithm will determine that there are only three files in the project and will scan them first. After &lt;strong&gt;entry_point.dart&lt;/strong&gt; is scanned, &lt;strong&gt;first_file.dart&lt;/strong&gt; is marked as “in use” because it’s imported into &lt;strong&gt;entry_point.dart&lt;/strong&gt;. This will mark &lt;strong&gt;entry_point.dart&lt;/strong&gt; as “in use” since it declares the main function. Next, the algorithm will check &lt;strong&gt;first_file.dart&lt;/strong&gt;, which has no directives, and then &lt;strong&gt;second_file.dart&lt;/strong&gt;. Since &lt;strong&gt;second_file.dart&lt;/strong&gt; doesn’t import any of the previous files, it’ll be marked as unused.&lt;/p&gt;

&lt;p&gt;We can exclude second_file.dart from the results by passing the &lt;code&gt;--exclude&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart run dart_code_metrics:metrics check-unused-files lib &lt;span class="nt"&gt;--exclude&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;”lib/&lt;span class="k"&gt;**&lt;/span&gt;/second_file.dart”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, the command will output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;No unused files found!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command is available during the installation of the pre-release version, 4.0.0-dev.4.&lt;/p&gt;

&lt;p&gt;Why did we decide to make a separate command, not add a search for used files to the existing call, and not provide support for the analyzer plugin? Because finding unused files seems to be an infrequent feature, while constantly checking is definitely overhead.&lt;/p&gt;

&lt;p&gt;The previous call to code analyzer is now also available via the &lt;code&gt;analyze&lt;/code&gt; command. If you used to call CLI with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart run dart_code_mertics:metrics lib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’ll now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart run dart_code_mertics:metrics analyze lib.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In version 4.0, we have support for &lt;code&gt;dart run dart_code_mertics:metrics lib&lt;/code&gt;. It’ll work at least up to version 5.0, so no changes will be required to CI after transitioning to a newer version.&lt;/p&gt;

&lt;p&gt;We’d love to hear your feedback and ideas on the new rules, metrics, or commands! You can always reach us via the community &lt;a href="https://t.me/DartCodeMetrics"&gt;chat on Telegram&lt;/a&gt; or post the &lt;a href="https://github.com/dart-code-checker/dart-code-metrics/issues"&gt;issue on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This command is just a part of the 4.0 release, which also includes new rules. We’ll discuss them in the next article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt; We are currently working on adding new commands and the next candidate is a command to check unused mocks in a project (might help with cases, when you keep all your mocks in a single file and they eventually become unused). Please let us know what do you think about this command, will it be useful for you?&lt;/p&gt;

</description>
      <category>dart</category>
      <category>flutter</category>
      <category>codequality</category>
      <category>linter</category>
    </item>
    <item>
      <title>Improving Code Quality With Dart Code Metrics</title>
      <dc:creator>Dmitry Zhifarsky</dc:creator>
      <pubDate>Thu, 27 May 2021 19:44:18 +0000</pubDate>
      <link>https://forem.com/incendial/improving-code-quality-with-dart-code-metrics-31dn</link>
      <guid>https://forem.com/incendial/improving-code-quality-with-dart-code-metrics-31dn</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/dart-code-checker/dart-code-metrics"&gt;Dart Code Metrics&lt;/a&gt; is a static code analysis tool that allows you to collect code metrics and provide additional rules for the analyzer. The tool helps developers monitor the quality of code and improve it. In this article, we'd like to share the capabilities of Dart Code Metrics with the community. This tool helped us at Wrike, and we hope it'll help you, too.&lt;/p&gt;

&lt;p&gt;It can be launched via the command line, which is connected as a plugin to the Dart Analysis Server, or as a library. Launching via the command line allows you to easily integrate the tool into the CI/CD process, and you can get results in Сonsole, HTML, JSON, CodeClimate, or GitHub. Connecting the tool as a plugin to the Analysis Server allows you to receive real-time feedback directly from the IDE.&lt;/p&gt;

&lt;p&gt;Why did we develop a tool like this? Wrike already has about 2.5 million lines of code written in Dart. A code base like this comes with the price of maintenance - so how do you know when it's time to refactor your code, and what do you start with?&lt;/p&gt;

&lt;p&gt;Dart SDK is distributed with an Analyzer, which has a built-in linter with a set of rules. In the official &lt;em&gt;pub&lt;/em&gt;, you can also find recommended rulesets: &lt;a href="https://pub.dev/packages/pedantic"&gt;pedantic&lt;/a&gt;, &lt;a href="https://pub.dev/packages/effective_dart"&gt;effective_dart&lt;/a&gt;, etc. This helps us avoid making mistakes and maintain the codebase as suggested by the author of the language. However, we didn't have enough analytical data on the code, and that started it all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Metrics
&lt;/h2&gt;

&lt;p&gt;After researching &lt;a href="https://www.springer.com/gp/book/9783540244295"&gt;materials&lt;/a&gt; on evaluating and designing program code, we realized the first step was to implement a collection of software metrics from the code.&lt;/p&gt;

&lt;p&gt;Now the analyzer collects the following metrics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cyclomatic complexity&lt;/li&gt;
&lt;li&gt;Lines of executable code&lt;/li&gt;
&lt;li&gt;Lines of code&lt;/li&gt;
&lt;li&gt;Number of parameters&lt;/li&gt;
&lt;li&gt;Number of methods&lt;/li&gt;
&lt;li&gt;Maximum nesting&lt;/li&gt;
&lt;li&gt;Weight of class&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We set a base threshold value for each metric, after which code refactoring is recommended. At the same time, threshold values ​​can be easily predefined and passed to the tool when either called from the console, or during the plugin configuration for the analyzer via &lt;em&gt;analysis_options.yaml&lt;/em&gt;. You can read more about this &lt;a href="https://github.com/dart-code-checker/dart-code-metrics#configuration"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the next step the tool finds anti-patterns in the codebase, relying on data from several metrics. Only two anti-patterns are currently implemented - long-method and long-parameter-list - but we'll expand this list in the future.&lt;br&gt;
While metrics like number of parameters or number of methods are easy enough to understand, what about cyclomatic complexity?&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Cyclomatic_complexity"&gt;cyclomatic complexity&lt;/a&gt; of a piece of code is the number of linearly independent routes in the code. For example, if the source code doesn't contain any branch points or loops, then its complexity is one, since there's only one route through the code. If the code has a single if-statement containing one simple condition, we have two routes through the code: the if-statement is true or false.&lt;/p&gt;

&lt;p&gt;Many independent routes in the function body impact the code's readability and maintenance. So it's better to split the function in such cases.&lt;/p&gt;

&lt;p&gt;The tool provides various report formats to visualize the metrics. We'll get back to this later in the "Reports" section.&lt;/p&gt;
&lt;h2&gt;
  
  
  Linting
&lt;/h2&gt;

&lt;p&gt;Initially, the tool only collected metrics, but then we added linting.&lt;/p&gt;

&lt;p&gt;Other ecosystems have useful rules like unused arguments check, class member ordering check, etc. They're not available in the built-in Dart SDK linter, so we made our own linter.&lt;/p&gt;

&lt;p&gt;Why did we decide to add linting to a separate package instead of making PR in the built-in analyzer? Because we decided to implement extended configuration capabilities. For example, we can configure the exact ordered list of class members that should be checked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The current list of rules:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;General rules&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;avoid-unused-parameters&lt;/li&gt;
&lt;li&gt;binary-expression-operand-order&lt;/li&gt;
&lt;li&gt;double-literal-format&lt;/li&gt;
&lt;li&gt;member-ordering&lt;/li&gt;
&lt;li&gt;member-ordering-extended&lt;/li&gt;
&lt;li&gt;newline-before-return&lt;/li&gt;
&lt;li&gt;no-boolean-literal-compare&lt;/li&gt;
&lt;li&gt;no-empty-block&lt;/li&gt;
&lt;li&gt;no-equal-arguments&lt;/li&gt;
&lt;li&gt;no-equal-then-else&lt;/li&gt;
&lt;li&gt;no-magic-number&lt;/li&gt;
&lt;li&gt;no-object-declaration&lt;/li&gt;
&lt;li&gt;prefer-conditional-expressions&lt;/li&gt;
&lt;li&gt;prefer-trailing-comma&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For &lt;em&gt;Intl&lt;/em&gt; library&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;prefer-intl-name&lt;/li&gt;
&lt;li&gt;provide-correct-intl-args&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For &lt;em&gt;Dart Angular&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;avoid-preserve-whitespace-false&lt;/li&gt;
&lt;li&gt;component-annotation-arguments-ordering&lt;/li&gt;
&lt;li&gt;prefer-on-push-cd-strategy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find the most up-to-date list &lt;a href="https://github.com/dart-code-checker/dart-code-metrics#rules"&gt;in the documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Stylistic rules aren't the only important things to consider; we also want to highlight potential errors like no-equal-then-else, no-equal-arguments, and more.&lt;/p&gt;

&lt;p&gt;Our rules were partially based on issues that we'd encounter during our reviews. Ideally, we want the issues to be covered automatically so we can focus on the work that matters. Another part of our rules emerged during the process of studying other tools' rules. (Shoutout to PVS-Studio, TSLint, and ESLint for inspiration!)&lt;/p&gt;

&lt;p&gt;Let's take a closer look at some of those rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Avoid unused parameters.&lt;/strong&gt; Checks for unused parameters for functions or methods. An unused parameter can indicate that it's no longer needed during refactoring, or that a variable is somewhere in the body of a function (or method) instead of that parameter. In the first case the rule helps remove unused code; the second indicates a possible error.&lt;/p&gt;

&lt;p&gt;Here's a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;em&gt;value&lt;/em&gt; parameter isn't used here, and the analyzer will display the message "Parameter is unused."&lt;/p&gt;

&lt;p&gt;Since Dart allows you to inherit from any class and requires that the parameter be included in the descendants, it can be renamed to _ in the base class, and the analyzer will skip it.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Prefer trailing comma.&lt;/strong&gt; Checks for the trailing comma for arguments, parameters, enumerations, and collections, provided they span multiple lines.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;firstFunction&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;firstArgument&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;secondArgument&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;thirdArgument&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For a function like this, the rule will suggest adding a comma at the end so that once formatted it turns into:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;firstFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;firstArgument&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;secondArgument&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;thirdArgument&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If the parameters were initially placed on one line, the analyzer won't consider it an error:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;secondFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;arg1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;arg2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;arg3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can also specify a &lt;em&gt;break-on&lt;/em&gt; parameter for the rule, which enables additional checking for the specified number of elements. For example, without &lt;em&gt;break-on&lt;/em&gt;, the example above is considered correct. But if you configure the rule for &lt;code&gt;break-on: 2&lt;/code&gt;, the analyzer will display an error for this function and suggest adding a comma.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No equal arguments.&lt;/strong&gt; Checks whether the same argument is passed more than once when instantiating a class or calling a method/function.&lt;/p&gt;

&lt;p&gt;Suppose there's a certain user class and a separate function that creates this user:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getFirstName&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Both User class fields are strings, and it's easy to miss that the same variable is passed when you create it. In such cases, the rule will indicate the variable &lt;em&gt;firstName&lt;/em&gt; is passed more than once, which may be an error.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Member ordering extended.&lt;/strong&gt; The rule checks the class member order. The rule received an &lt;em&gt;extended&lt;/em&gt; postfix since we already had a member ordering rule, but it wasn't as flexible.&lt;/p&gt;

&lt;p&gt;The rule accepts an ordering configuration with quite a flexible template. It allows you to specify not just the type of a class member (field, method, constructor), but also keywords such as late, const, final, or, for example, nullable.&lt;/p&gt;

&lt;p&gt;The configuration can look like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;public-late-final-fields&lt;/li&gt;
&lt;li&gt;private-late-final-fields&lt;/li&gt;
&lt;li&gt;public-nullable-fields&lt;/li&gt;
&lt;li&gt;private-nullable-fields&lt;/li&gt;
&lt;li&gt;named-constructors&lt;/li&gt;
&lt;li&gt;factory-constructors&lt;/li&gt;
&lt;li&gt;getters&lt;/li&gt;
&lt;li&gt;setters&lt;/li&gt;
&lt;li&gt;public-static-methods&lt;/li&gt;
&lt;li&gt;private-static-methods&lt;/li&gt;
&lt;li&gt;protected-methods&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or be simplified to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fields&lt;/li&gt;
&lt;li&gt;methods&lt;/li&gt;
&lt;li&gt;setters&lt;/li&gt;
&lt;li&gt;getters (or, if there's no need to separate, just getters-setters)&lt;/li&gt;
&lt;li&gt;constructors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read more about the rule's capabilities &lt;a href="https://github.com/dart-code-checker/dart-code-metrics/blob/master/doc/rules/member-ordering-extended.md"&gt;in the documentation&lt;/a&gt;.&lt;br&gt;
Additionally, the rule may require alphabetical sorting. To do this, you need to pass &lt;code&gt;alphabetize: true&lt;/code&gt; to its configuration.&lt;/p&gt;
&lt;h2&gt;
  
  
  Reports
&lt;/h2&gt;

&lt;p&gt;To visualize all the collected metrics and linting results, the tool conveniently provides reports in one of the following formats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Console&lt;/li&gt;
&lt;li&gt;HTML&lt;/li&gt;
&lt;li&gt;JSON&lt;/li&gt;
&lt;li&gt;CodeClimate&lt;/li&gt;
&lt;li&gt;GitHub&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Console format is the default, and can be transferred to the console utility via the &lt;em&gt;--reporter&lt;/em&gt; flag.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart pub run dart_code_metrics:metrics lib
&lt;span class="c"&gt;# or for a Flutter package&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;flutter pub run dart_code_metrics:metrics lib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When executing the command on the Dart Code Metrics codebase, we'll receive the following report in the console:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r9SmXPay--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k8n187xtijn7v8k3oegz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r9SmXPay--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k8n187xtijn7v8k3oegz.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to choose a different type reporter (e.g., HTML), you need to run the following command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart pub run dart_code_metrics:metrics lib &lt;span class="nt"&gt;--reporter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;html
&lt;span class="c"&gt;# or for a Flutter package&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;flutter pub run dart_code_metrics:metrics lib &lt;span class="nt"&gt;--reporter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The report will be generated in the metrics folder. The resulting folder can also be passed using the &lt;em&gt;--output-directory&lt;/em&gt; or &lt;em&gt;-o&lt;/em&gt; flag:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IDfKUt2z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kuhc4310tirgvwfkxatw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IDfKUt2z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kuhc4310tirgvwfkxatw.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the report, you can view each file separately:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Mht7mzkY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ing6g1vaxh3ppikdtmdi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mht7mzkY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ing6g1vaxh3ppikdtmdi.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To view detailed information on metrics, you need to hover over the icons to the left of the code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iU9yb1_w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qt96q47u8x71a2c7asob.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iU9yb1_w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qt96q47u8x71a2c7asob.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're using GitHub Workflows and want to get a report immediately in the created PRs, you need to add a new step to the pipeline:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;your_job_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;...&lt;/span&gt;
    &lt;span class="s"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;
     &lt;span class="s"&gt;- name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Code Metrics&lt;/span&gt;
       &lt;span class="s"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flutter pub run dart_code_metrics:metrics --reporter=github lib&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will allow you to get reports in this format:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eaC5gWPT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sxmqcad6fdmxpe7ztim8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eaC5gWPT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sxmqcad6fdmxpe7ztim8.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Detailed information about all types of metrics and configuration methods can be found &lt;a href="https://github.com/dart-code-checker/dart-code-metrics#metrics"&gt;in the documentation&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Installing
&lt;/h2&gt;

&lt;p&gt;If you want to try the package for yourself, here's a short guide on connecting it as a plug-in for Dart analyzer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: install the package as a dev dependency.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart pub add &lt;span class="nt"&gt;--dev&lt;/span&gt; dart_code_metrics
&lt;span class="c"&gt;# or for a Flutter package&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;flutter pub add &lt;span class="nt"&gt;--dev&lt;/span&gt; dart_code_metrics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or, add the package manually to pubspec.yaml.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Important: If your package hasn't been migrated to null safety yet, use version 2.5.0.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dev_dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;dart_code_metrics&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^3.3.3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Run the command to install dependencies.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dart pub get
&lt;span class="c"&gt;# or for a Flutter package&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;flutter pub get
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Step 2: Add configuration to analysis_options.yaml.&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;This configuration specifies the &lt;em&gt;long-method&lt;/em&gt; and &lt;em&gt;long-parameter-list&lt;/em&gt; anti-patterns, metrics with their threshold values, and rules. The entire list of available metrics can be found &lt;a href="https://github.com/dart-code-checker/dart-code-metrics#metrics"&gt;here&lt;/a&gt;, and the list of rules &lt;a href="https://github.com/dart-code-checker/dart-code-metrics#rules"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Reload the IDE for the analyzer to detect the plugin.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you want to use the package as a CLI, check out the documentation &lt;a href="https://github.com/dart-code-checker/dart-code-metrics#cli"&gt;here&lt;/a&gt;. To use it as a Library, take a look at the documentation &lt;a href="https://github.com/dart-code-checker/dart-code-metrics/blob/master/example/example.dart"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Given the popularity of Flutter, we're considering what metrics and rules could help developers with this framework. We're open to suggestions; if you have ideas for rules or metrics that could be useful to Dart or Flutter developers, feel free to write to us or report an issue via &lt;a href="https://github.com/dart-code-checker/dart-code-metrics"&gt;GitHub&lt;/a&gt;. We'll be happy to make developers' lives better.&lt;/p&gt;

&lt;p&gt;Our plans for the future can always be tracked in the public project repository in the &lt;a href="https://github.com/dart-code-checker/dart-code-metrics/issues"&gt;issues&lt;/a&gt; list or in &lt;a href="https://github.com/dart-code-checker/dart-code-metrics/projects"&gt;projects&lt;/a&gt;, where you can also leave feedback on the tool.&lt;/p&gt;

&lt;p&gt;Feel free to join our &lt;a href="https://t.me/DartCodeMetrics"&gt;community on Telegram&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>dart</category>
      <category>flutter</category>
      <category>codequality</category>
    </item>
  </channel>
</rss>
