Announcing DCM for Teams
If you’re not familiar with DCM (previously known as Dart Code Metrics) — it’s a static analysis tool that helps improve the quality and consistency of Dart code by identifying and reporting problems, such as bugs and code that doesn’t follow best practices. It also collects analytical data on the code through calculating code metrics and can be configured to set thresholds for these metrics. You can read more on our website.
Our website also got a significant update, check it out!
2022 was a huge year for DCM — 26 releases, 32 new rules added, a lot of existing rules improved, several new commands (like check-unused-code and check-unnecessary-nullable-parameters) added, but we received a lot of feedback that the current IDE integration scales poorly and it’s a real pain to use DCM on large projects.
So that’s why today we’re excited to present you a version that still focuses on helping you build better software, but also aims to scale with your codebase — DCM for Teams!
It’s not an update for the current version (now named as Individuals version), they both will stay available (current one distributed via pub and the new one distributed as executable + the IDE extension).
Key Differences
No more plugins API
DCM for Teams comes with a significant change on how the code is being analyzed when opened from the IDE. Current DCM version uses the plugins API for the IDEs integration which is a performance bottleneck that causes a lot of problems.
But no more. DCM for Teams has its own analysis process, which is integrated into the IDE via our newly created VS Code extension and IntelliJ / Android Studio plugin.
Let’s take a look how it affected the performance part.
For CLI (both with warm up cache):
As you can see, Teams executable takes 4.8 seconds to run. While pub version — 21.4 seconds on the same codebase.
If we run non warm up versions, the executable take 16 seconds and the pub version — 32.
For IDEs integration (on the same repo, after the initial errors displayed)
Our measurements indicate that the DCM analysis process uses less memory compared to the Dart analysis process, which we believe is a positive start.
But, if we enable the current version of DCM with the plugins API on the same repository, we’ll see a memory consumption of approximately 1 GB.
In summary, the DCM process in combination with the Dart process on average uses twice as less memory compared to the Dart process with the DCM plugin.
We believe that our understanding of the performance difference might change after the new version will be used on other larger repositories, but we’re also looking into how to make it even better.
Moving towards a separate DCM analysis process also allowed a change in how DCM is distributed. If previously it was a package that you’d install via pub, the new version is an executable which is distributed differently (more like the Dart SDK) which might be considered a downside, but it also allows you not to depend on the DCM transitive dependencies. So, less dependency resolution problems for you and no need to add it as a dependency to every package you have.
Another benefit is that no matter how many Dart packages are opened in the IDE, only one analysis process will be running in the background.
Also, analysis process and the command now reuse the same cache (the same mechanism as for the Dart SDK), so if you work on a project in your IDE and run the commands from the console, they both will perform better.
New Features
Apart from the plugins API migration, there are several new features available for Teams version (and more to come).
Improved quick fixes
Quick fixes are essential for developers productivity and that’s why the Teams version has more rules that support quick fixes, but also introduces new ones: fix all of type, fix all in a file, ignore and ignore in a file.
The list of rules that now support the quick fixes:
- avoid-duplicate-exports
- avoid-late-keyword
- avoid-redundant-async
- avoid-top-level-members-in-tests
- avoid-unnecessary-type-assertions
- avoid-unnecessary-type-casts
- avoid-unrelated-type-assertions
- avoid-unused-parameters
- newline-before-return
- no-equal-then-else
- prefer-match-file-name
- member-ordering
Member-ordering quick fix is a tricky one, it also tries to save the newlines (for example, if you have a set of class fields that are not separated by a newline, the fix will move them together not breaking existing formatting), but has a downside — applying multiple fixes with the member-ordering fix can break your code. But this problem will be addressed in the nearest releases.
DCM now provides more generic quick fixes and allows to fix all similar or just all issues in a file or add an ignore:
And the same quick fixes for the IntelliJ / Android Studio:
New rules
There are four new rules, included into the initial release:
avoid-unnecessary-nullable-return-type. Warns when the return type of a function is declared nullable, but the function returns non-nullable value. Handling unnecessary nullable return values results in a more complex code (since you need to check for potential null value) and increases the amount of tests.
For example:
String? someFunction() {
return 'str';
}
This function clearly returns non-nullable value ‘str’, so the rule will suggest to mark the return type String?
as non-nullable String
. Then, any code that uses this function can be simplified to only handle the non-nullable value.
avoid-unrelated-type-casts. Warns when a type cast (“as”) is used in a way that will always result in an error. Such type casts can be made by mistake, but lead to potential runtime exceptions.
For example:
final regularString = '';
final result = regularString as int;
If we try to cast a String
to an int
, it’s a compile time error, but the analyzer won’t highlight this as a problem. Here is a dartpad example.
format-test-name. Requires a test name to match the given pattern. Can be useful if you have a specific naming approach for your tests since it can help you avoid manual checks on code reviews.
For example:
test('what a test')
Some might find this name acceptable, but you (for example) want all of your tests to start with should
. You can enable this rule, set its test-name-pattern
option to ^should
and standardise all your test names to start with should
.
prefer-declaring-const-constructor. Warns when a class constructor is not declared as const, but the class has only final / const fields. Declaring const class constructors can result in performance improvements and it’s usually preferable to declare const constructors everywhere possible.
For example:
class Square {
Square(this.sideLength, this.color);
final double sideLength;
final Color color;
}
Constructors of classes like Square
are great candidates to be marked as const
. But if a class extends another class that has non-const constructor, the rule won’t trigger.
New licensing model
Current DCM version is distributed for free, but we want to focus more on developing and improving the product. That’s why DCM for Teams requires a paid license. We understand that many of our users have come to rely on our free version and have benefited from the tool in their development process and we want to assure you that it will still be available, but the Teams version will provide additional features.
There are several plans available for you (aside the free Individuals version):
- Teams plan: 10 activations
- Business plan: 30 activations
- Custom: up to 100 activations
To get more details on how these plans differ, see our pricing page.
We believe that this transition will allow us to better serve our users and we look forward to continuing to provide you with the high quality code analysis tooling.
Requesting a trial. If you’re interested in trying out DCM for Teams, you can request a trial version that will be available for 30 days (instead of a year like for a regular license). To do that, open the For Teams page of our website and press the “Request a trial” button.
After you submit the form with your email, you will receive an email with the license data and instructions on how to get started with the trial version.
What’s next
Improving existing commands. Current implementation of check-unused-code command looks only for top member declarations (like classes, functions, etc), and has some false-positives along with other commands. We want to focus on fixing these issues and make commands a more reliable assistant in your day-to-day development.
Improving quick fixes. As mentioned before, quick fixes can significantly improve developer’s productivity, so we want to focus on them too. We plan to make them more reliable in terms of breaking the code (the goal is to avoid it at all) and add a cli command to fix all the issues.
New commands. We have several ideas for more general and Flutter specific commands, but no details yet. We’ll provide a separate update on the new commands a bit later.
New rules. More rules are coming for the Teams version. These rules will focus more on errors and general architecture. We’re also evaluating what packages from the Dart ecosystem can have their separate rules (like we did for equatable). They will also be added to the Teams version rules set.
Baseline support. Some feedback we received was about adding DCM to an existing codebase and that this process is not easy. We want to address this problem by introducing support for baseline when you will be able to ignore existing code or have a specific config that automatically ignores all existing issues allowing you to partially enable rules for the new code.
Sharing your feedback
If there is something you miss from DCM right now or want us to make something better or have any general feedback — there are several ways to share: you can fill this google form or send us feedback directly from our website.
We’re also interested in your feedback about DCM for Teams, so any feedback is very welcome!