﻿# Why use static analysis? Exploring an error from Akka\.NET

"Use static analysis regularly, not just before releases\.\.\. The earlier you find errors, the cheaper they are to fix\.\.\." You probably heard this a hundred times\. Today we'll answer the "Why?" question once again\. An error from the Akka\.NET project will assist us\. 

![0940_AkkaNET_Error/image1.png](https://import.viva64.com/docx/blog/0940_AkkaNET_Error/image1.png)

**The error**

We'll start with a task\. Find a defect in the code below:

```cpp
protected override bool ReceiveRecover(object message)
{
  switch (message)
  {
    case ShardId shardId:
      _shards.Add(shardId);
      return true;
    case SnapshotOffer offer when (offer.Snapshot is 
                                   ShardCoordinator.CoordinatorState state):
      _shards.UnionWith(state.Shards.Keys.Union(state.UnallocatedShards));
      return true;
    case SnapshotOffer offer when (offer.Snapshot is State state):
      _shards.Union(state.Shards);
      _writtenMarker = state.WrittenMigrationMarker;
      return true;
    case RecoveryCompleted _:
      Log.Debug("Recovery complete. Current shards [{0}]. Written Marker {1}", 
                string.Join(", ", _shards), 
                _writtenMarker);

      if (!_writtenMarker)
      {
        Persist(MigrationMarker.Instance, _ =>
        {
          Log.Debug("Written migration marker");
          _writtenMarker = true;
        });
      }
      return true;
    case MigrationMarker _:
      _writtenMarker = true;
      return true;
  }
  ....
}
```

Let's examine the code above and see what the problem is\.

The _\_shards_ variable is of type _HashSet<ShardId\>_\. The code above calls several methods that change the state of this set\.

_HashSet<T\>\.Add_:

```cpp
_shards.Add(shardId);
```

_HashSet<T\>\.UnionWith_: 

```cpp
_shards.UnionWith(state.Shards.Keys.Union(state.UnallocatedShards));
```

However, one of these calls is incorrect: 

```cpp
_shards.Union(state.Shards);
```

It does not change the state of the _\_shards_ object\. _Enumerable\.Union_ is a LINQ extension method that does not change the original collection and returns a modified collection instead\. This means, the method call's result must be saved somewhere or used somehow\. We do not see that in the code\.

The PVS\-Studio analyzer issued the following warning:_ V3010 The return value of function 'Union' is required to be utilized\. Akka\.Cluster\.Sharding EventSourcedRememberEntitiesCoordinatorStore\.cs 123_

By the way, here's what the fixed code looks like:

```cpp
_shards.UnionWith(state.Shards);
```

**How we found the error — or talk number 101 on the benefits of static analysis**

Every night our server runs static analysis for several open\-source projects\. These include Akka\.NET\. Why do we do it? This practice offers a few benefits:

* it provides an extra way to test the analyzer;
* it helps us write notes like this one and provides us with interesting examples that demonstrate the benefits of static analysis\.

We wrote more about it [here](https://pvs-studio.com/en/blog/posts/cpp/0799/)\.

And now a few words on our case at hand — how the error appeared and how it was fixed\.

_April 20, 2022:_

* code with an error is [committed](https://github.com/akkadotnet/akka.net/commit/2cbdbcbd07ac65596a8a38eb30e54ba22041d1b1)  to the Akka\.NET project's dev branch \(a [link](https://github.com/akkadotnet/akka.net/blob/8e7f02149451856c9160f9cd28d687ff8a166a11/src/contrib/cluster/Akka.Cluster.Sharding/Internal/EventSourcedRememberEntitiesCoordinatorStore.cs#L123) to the specific line of code\);

_April 21, 2022:_

* our server analyzes the code and sends me an email with warnings;
* I investigate the problem and create an [issue](https://github.com/akkadotnet/akka.net/issues/5862) on GitHub;
* the developers fix the error\. A [link](https://github.com/akkadotnet/akka.net/pull/5863/commits/263a459e11e4d1a273819b728f0dcc5cb7320934) to the commit\.

I think that was some pretty smooth collaboration\! Thanks to the developers for the prompt fix\.

And now to the important question — how long would this error have existed in the code if events had taken a different turn? Here I'll leave some room for your imagination\.

**So what can you do right now to avoid mistakes like this one?**

* Use a static analyzer\. You can download one [here](https://pvs-studio.com/en/pvs-studio/try-free/?promo=pvs_akka)\. Remember to use the _pvs\_akka_ promo code — then, instead of 7 days, the trial license will work 30 days\.
* If you want to read more articles and notes like this one, [follow](https://twitter.com/_SergVasiliev_) me on Twitter\.