{"id":392038,"date":"2024-06-29T10:11:02","date_gmt":"2024-06-29T10:11:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=392038"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2024-06-29T10:11:02","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=392038","title":{"rendered":"<span>Talking About Errors in the QuantConnect Lean Code<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/c03\/5c9\/633\/c035c9633cc626bfaa3c257ef762961c.png\" alt=\"image1.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/c03\/5c9\/633\/c035c9633cc626bfaa3c257ef762961c.png\"\/><\/div>\n<p>  This article discusses errors found using a static analyzer in an open source project. There are some simple things that can help you avoid them. For example, the usage of language syntactic constructs starting from C# 8.0. We hope it will be exciting. Have fun reading! <br \/>  <a name=\"habracut\"><\/a><br \/>  <a href=\"https:\/\/github.com\/QuantConnect\/Lean\/\">QuantConnect Lean<\/a> is an open source algorithmic trading engine designed for easy strategy research, backtesting, and live trading. Compatible with Windows, Linux, and macOS. Integrates with prevalent data providers and brokerage companies to quickly deploy algorithmic trading strategies. <\/p>\n<p>  The check was implemented by using the <a href=\"https:\/\/www.viva64.com\/en\/pvs-studio\/\">PVS-Studio static analyzer<\/a>. PVS-Studio is a tool designed to detect errors and potential vulnerabilities in the source code of programs, written in C, C++, C#, and Java. <\/p>\n<h2>Accidents are not accidental.<\/h2>\n<p>  <\/p>\n<pre><code class=\"cpp\">public virtual DateTime NextDate(....) {   ....   \/\/ both are valid dates, so chose one randomly   if (   IsWithinRange(nextDayOfWeek, minDateTime, maxDateTime)        &amp;&amp; IsWithinRange(previousDayOfWeek, minDateTime, maxDateTime))   {     return _random.Next(0, 1) == 0  \/\/ &lt;=            ? previousDayOfWeek            : nextDayOfWeek;   }   .... }<\/code><\/pre>\n<p>  <a href=\"https:\/\/www.viva64.com\/en\/w\/v3022\/\">V3022<\/a> Expression &#8216;_random.Next(0, 1) == 0&#8217; is always true. RandomValueGenerator.cs 142<\/p>\n<p>  The bottom line was that either one or the other value was selected with a 50% probability. However, in this case, the <i>Next<\/i> method will always return 0. <\/p>\n<p>  This happens because the second argument is not included in the range of values. That is, the value that the method can return will be in the range [0,1). Let&#8217;s fix that:<\/p>\n<pre><code class=\"cpp\">public virtual DateTime NextDate(....) {   ....   \/\/ both are valid dates, so chose one randomly   if (   IsWithinRange(nextDayOfWeek, minDateTime, maxDateTime)        &amp;&amp; IsWithinRange(previousDayOfWeek, minDateTime, maxDateTime))   {     return _random.Next(0, 2) == 0            ? previousDayOfWeek            : nextDayOfWeek;   }   .... }<\/code><\/pre>\n<p>  <\/p>\n<h2>Passing reference-type parameters<\/h2>\n<p>  <b>Example<\/b><\/p>\n<pre><code class=\"cpp\">\/\/\/ &lt;summary> \/\/\/ Copy contents of the portfolio collection to a new destination. \/\/\/ &lt;\/summary> \/\/\/ &lt;remarks> \/\/\/ IDictionary implementation calling the underlying Securities collection \/\/\/ &lt;\/remarks> \/\/\/ &lt;param name=\"array\">Destination array&lt;\/param> \/\/\/ &lt;param name=\"index\">Position in array to start copying&lt;\/param> public void CopyTo(KeyValuePair&lt;Symbol, SecurityHolding>[] array, int index) {   array = new KeyValuePair&lt;Symbol, SecurityHolding>[Securities.Count];   var i = 0;   foreach (var asset in Securities)   {     if (i >= index)     {       array[i] = new KeyValuePair&lt;Symbol,SecurityHolding>(asset.Key,                                                           asset.Value.Holdings);     }     i++;   } }<\/code><\/pre>\n<p>  <a href=\"https:\/\/www.viva64.com\/en\/w\/v3061\/\">V3061<\/a> Parameter &#8216;array&#8217; is always rewritten in method body before being used. SecurityPortfolioManager.cs 192<\/p>\n<p>  The method accepts the collection and immediately overwrites its value. Accept that this looks rather suspiciously. So, let&#8217;s try to understand what this method must do.<\/p>\n<p>  According to the comment and the method&#8217;s name, it becomes clear that another array must be copied to the array passed. However, this will not happen, and the value of the <i>array<\/i> outside the current method will remain unchanged.<\/p>\n<p>  It happens because the <i>array<\/i> argument will be passed to the method by value, not by reference. Thus, when the assign operation is done, the <i>array<\/i> variable accessible inside the method will store a reference to the new object. The argument value passed to the method will remain unchanged. To fix this, the reference type argument must be passed by reference:<\/p>\n<pre><code class=\"cpp\">public void CopyTo(out KeyValuePair&lt;Symbol, SecurityHolding>[] array, \/\/ &lt;=                    int index) {   array = new KeyValuePair&lt;Symbol, SecurityHolding>[Securities.Count];   .... }<\/code><\/pre>\n<p>  Since we are certainly creating a new array in the method, the <i>out <\/i>modifier must be used instead of <i>ref<\/i>. This immediately indicates that the variable inside will be assigned a value.<\/p>\n<p>  By the way, this case enlarges the collection of my colleague, Andrey Karpov, you can learn about it from the article &#171;<a href=\"https:\/\/www.viva64.com\/en\/b\/0723\/\">Getting started collecting errors in copy functions<\/a>&#171;.<\/p>\n<h2>Unbinding the resources<\/h2>\n<p>  <\/p>\n<pre><code class=\"cpp\">public static string ToSHA256(this string data) {   var crypt = new SHA256Managed();   var hash = new StringBuilder();   var crypto = crypt.ComputeHash(Encoding.UTF8.GetBytes(data),                                   0,                                   Encoding.UTF8.GetByteCount(data));   foreach (var theByte in crypto)   {     hash.Append(theByte.ToStringInvariant(\"x2\"));   }   return hash.ToString(); }<\/code><\/pre>\n<p>  <a href=\"https:\/\/www.viva64.com\/en\/w\/v3114\/\">V3114<\/a> IDisposable object &#8216;crypt&#8217; is not disposed before method returns. Extensions.cs 510<\/p>\n<p>  To understand the meaning of this diagnostic, let&#8217;s first recall a little bit of theory. If you don&#8217;t mind, I will take information from the documentation for this diagnostic: <\/p>\n<p>  &#171;The garbage collector automatically unbinds the memory associated with a controlled object if it is no longer in use and there are no visible references to it. However, we can&#8217;t say for sure when exactly the garbage collection will occur (unless you call it manually). In addition, the garbage collector does not have information about unmanaged resources such as handles, windows, or open files and threads. The <i>Dispose<\/i> method is usually used to unbind such unmanaged resources&#187;. <\/p>\n<p>  In other words, we have created a <i>crypt<\/i> variable of the <i>SHA256Managed<\/i> type, which implements the <i>IDisposable<\/i> interface. As a result, when we exit the method, the potentially captured resources will not be released. <\/p>\n<p>  To prevent this, I recommend choosing <i>using<\/i>. The <i>Dispose<\/i> method is activated automatically upon reaching the closing curly bracket associated with the <i>using<\/i> instruction. Let&#8217;s take a look at this:<\/p>\n<pre><code class=\"cpp\">public static string ToSHA256(this string data) {   using (var crypt = new SHA256Managed())   {     var hash = new StringBuilder();     ....   } }<\/code><\/pre>\n<p>  But if you don&#8217;t like curly brackets, then in C# 8.0 you can write like this:<\/p>\n<pre><code class=\"cpp\">public static string ToSHA256(this string data) {   using var crypt = new SHA256Managed();   var hash = new StringBuilder();   .... }<\/code><\/pre>\n<p>  The difference with the previous version is that the <i>Dispose<\/i> method is activated when the closing curly bracket of the method is reached. This is the end of the piece where <i>crypt<\/i> is declared.<\/p>\n<h2>Real numbers<\/h2>\n<p>  <\/p>\n<pre><code class=\"cpp\">public bool ShouldPlot {   get   {     ....     if (Time.TimeOfDay.Hours &lt; 10.25) return true;     ....   } }  public struct TimeSpan : IComparable,                           IComparable&lt;TimeSpan>,                           IEquatable&lt;TimeSpan>,                           IFormattable {   ....   public double TotalHours { get; }   public int Hours { get; }   .... }<\/code><\/pre>\n<p>  <a href=\"https:\/\/www.viva64.com\/en\/w\/v3040\/\">V3040<\/a> The &#8216;10.25&#8217; literal of the &#8216;double&#8217; type is compared to a value of the &#8216;int&#8217; type. OpeningBreakoutAlgorithm.cs 426<\/p>\n<p>  It looks strange that in the condition the value of an <i>int<\/i> variable is compared with a <i>double-type<\/i> literal. This looks odd and another variable is clearly supposed to be here. And, indeed, if you check out which similarly named fields <i>TimeOfDay<\/i> has, we will find:<\/p>\n<pre><code class=\"cpp\">public double TotalHours { get; }<\/code><\/pre>\n<p>  The code probably should look like this:<\/p>\n<pre><code class=\"cpp\">public bool ShouldPlot {   get   {     ....     if (Time.TimeOfDay.TotalHours &lt; 10.25) return true;     ....   } }<\/code><\/pre>\n<p>  Also keep in mind that <a href=\"https:\/\/rsdn.org\/article\/alg\/float.xml\">you mustn&#8217;t check<\/a> floating-point numbers for direct equality (&#171;==&#187;, &#171;!=&#187;). And don&#8217;t forget about <a href=\"https:\/\/www.viva64.com\/en\/examples\/v3041\/\">typecasting<\/a>.<\/p>\n<h2>Switch statement<\/h2>\n<p>  <b>Tip 1<\/b><\/p>\n<pre><code class=\"cpp\">public IEnumerable&lt;TradingDay> GetDaysByType(TradingDayType type,                                              DateTime start,                                               DateTime end) {   Func&lt;TradingDay, bool> typeFilter = day =>   {     switch (type)        \/\/ &lt;=     {       case TradingDayType.BusinessDay:         return day.BusinessDay;       case TradingDayType.PublicHoliday:         return day.PublicHoliday;       case TradingDayType.Weekend:         return day.Weekend;       case TradingDayType.OptionExpiration:         return day.OptionExpirations.Any();       case TradingDayType.FutureExpiration:         return day.FutureExpirations.Any();       case TradingDayType.FutureRoll:         return day.FutureRolls.Any();       case TradingDayType.SymbolDelisting:         return day.SymbolDelistings.Any();       case TradingDayType.EquityDividends:         return day.EquityDividends.Any();     };     return false;   };   return GetTradingDays(start, end).Where(typeFilter); }<\/code><\/pre>\n<p>  <a href=\"https:\/\/www.viva64.com\/en\/w\/v3002\/\">V3002<\/a> The switch statement does not cover all values of the &#8216;TradingDayType&#8217; enum: EconomicEvent. TradingCalendar.cs 79<\/p>\n<p>  The type of the variable <i>type<\/i> is <i>TradingDayType<\/i>, and it is <i>enum<\/i>:<\/p>\n<pre><code class=\"cpp\">public enum TradingDayType {   BusinessDay,   PublicHoliday,   Weekend,   OptionExpiration,   FutureExpiration,   FutureRoll,   SymbolDelisting,   EquityDividends,   EconomicEvent }<\/code><\/pre>\n<p>  If you count, you will see that there are 9 elements in the enumeration, but only 8 are checked in <i>switch<\/i>. Such situation could happen due to code extension. To prevent this, I always recommend explicitly using <i>default<\/i>:<\/p>\n<pre><code class=\"cpp\">public IEnumerable&lt;TradingDay> GetDaysByType(TradingDayType type,                                              DateTime start,                                               DateTime end) {   Func&lt;TradingDay, bool> typeFilter = day =>   {     switch (type)     {       ....       default:         return false;     };   };   return GetTradingDays(start, end).Where(typeFilter); }<\/code><\/pre>\n<p>  As you may have noticed, the <i>return<\/i> statement that stood after the <i>switch<\/i> moved to the <i>default<\/i> section. In this case, the program&#8217;s logic has not changed, but I still recommend writing it this way.<\/p>\n<p>  Code extensibility is the reason for it. In the case of the original, it&#8217;s possible to safely add some logic before <i>return false<\/i>, without suspecting that this is the <i>default<\/i> of the <i>switch <\/i>statement. Now everything is evident and clear.<\/p>\n<p>  However, if you think that only part of the enumeration elements should always be processed in your case, you can throw an exception:<\/p>\n<pre><code class=\"cpp\">default:   throw new CustomExeption(\"Invalid enumeration element\");<\/code><\/pre>\n<p>  Personally, I got hooked on this syntactic sugar C# 8.0:<\/p>\n<pre><code class=\"cpp\">Func&lt;TradingDay, bool> typeFilter = day => {   return type switch   {     TradingDayType.BusinessDay      => day.BusinessDay,     TradingDayType.PublicHoliday    => day.PublicHoliday,     TradingDayType.Weekend          => day.Weekend,     TradingDayType.OptionExpiration => day.OptionExpirations.Any(),     TradingDayType.FutureExpiration => day.FutureExpirations.Any(),     TradingDayType.FutureRoll       => day.FutureRolls.Any(),     TradingDayType.SymbolDelisting  => day.SymbolDelistings.Any(),     TradingDayType.EquityDividends  => day.EquityDividends.Any(),     _ => false   }; };<\/code><\/pre>\n<p>  <b>Tip 2<\/b><\/p>\n<pre><code class=\"cpp\">public string[] GetPropertiesBy(SecuritySeedData type) {   switch (type)   {     case SecuritySeedData.None:       return new string[0];      case SecuritySeedData.OpenInterest:       return new[] { \"OpenInterest\" };  \/\/ &lt;=      case SecuritySeedData.OpenInterestTick:       return new[] { \"OpenInterest\" };  \/\/ &lt;=      case SecuritySeedData.TradeTick:       return new[] {\"Price\", \"Volume\"};      ....      case SecuritySeedData.Fundamentals:       return new string[0];      default:       throw new ArgumentOutOfRangeException(nameof(type), type, null);   } }<\/code><\/pre>\n<p>  <a href=\"https:\/\/www.viva64.com\/en\/w\/v3139\/\">V3139<\/a> Two or more case-branches perform the same actions. SecurityCacheTests.cs 510<\/p>\n<p>  In two different <i>cases<\/i>, the same value is returned. It looks very suspicious in such a form. It feels like someone copied, pasted and forgot to change the code. Therefore, here&#8217;s my advice: if the same logic must be performed for different values, then combine the <i>case<\/i> that way:<\/p>\n<pre><code class=\"cpp\">public string[] GetPropertiesBy(SecuritySeedData type) {   switch (type)   {     case SecuritySeedData.None:       return new string[0];      case SecuritySeedData.OpenInterest:     case SecuritySeedData.OpenInterestTick:       return new[] { \"OpenInterest\" };      ....   } }<\/code><\/pre>\n<p>  This clearly indicates what we want and removes an extra line as well. \ud83d\ude42<\/p>\n<h2>If statement<\/h2>\n<p>  <b>Example 1<\/b><\/p>\n<pre><code class=\"cpp\">[TestCaseSource(nameof(DataTypeTestCases))] public void HandlesAllTypes&lt;T>(....) where T : BaseData, new() {   ....   if (   symbol.SecurityType != SecurityType.Equity       || resolution != Resolution.Daily       || resolution != Resolution.Hour)   {     actualPricePointsEnqueued++;     dataPoints.Add(dataPoint);   }   .... }<\/code><\/pre>\n<p>  <a href=\"https:\/\/www.viva64.com\/en\/w\/v3022\/\">V3022<\/a> Expression &#8216;symbol.SecurityType != SecurityType.Equity || resolution != Resolution.Daily || resolution != Resolution.Hour&#8217; is always true. LiveTradingDataFeedTests.cs 1431<\/p>\n<p>  The condition is always true. After all, in order to have the condition failed, the variable <i>resolution<\/i> must have the <i>Resolution.Daily<\/i> value and <i>Resolution.Hour<\/i> at a time. A possible fixed variant:<\/p>\n<pre><code class=\"cpp\">[TestCaseSource(nameof(DataTypeTestCases))] public void HandlesAllTypes&lt;T>(....) where T : BaseData, new() {   ....   if (   symbol.SecurityType != SecurityType.Equity       || (   resolution != Resolution.Daily            &amp;&amp; resolution != Resolution.Hour))   {     actualPricePointsEnqueued++;     dataPoints.Add(dataPoint);   }   .... }<\/code><\/pre>\n<p>  Some tips for the <i>if<\/i> statement. When there is a condition that consists entirely of &#171;||&#187; operators, then after writing, verify whether the same variable is checked for <b>inequality<\/b> to something else several times in a row. <\/p>\n<p>  The situation is similar in the condition with the &#171;&amp;&amp;&#187; operator. If a variable is checked for <b>equality<\/b> to something repeatedly, it is most likely to be a logical error.<\/p>\n<p>  Also, if you write a compound condition, and it contains &#171;&amp;&amp;&#187;and &#171;||&#187;, do not hesitate to put parentheses. This can help you either to see an error or to avoid it.<\/p>\n<p>  <b>Example 2<\/b><\/p>\n<pre><code class=\"cpp\">public static string SafeSubstring(this string value,                                     int startIndex,                                    int length) {   if (string.IsNullOrEmpty(value))   {     return value;   }    if (startIndex > value.Length - 1)   {     return string.Empty;   }    if (startIndex &lt; -1)   {     startIndex = 0;   }    return value.Substring(startIndex,                           Math.Min(length, value.Length - startIndex)); }<\/code><\/pre>\n<p>  <a href=\"https:\/\/www.viva64.com\/en\/w\/v3057\/\">V3057<\/a> The &#8216;Substring&#8217; function could receive the &#8216;-1&#8217; value while non-negative value is expected. Inspect the first argument. StringExtensions.cs 311<\/p>\n<p>  According to the analyzer the value -1 can be passed as the first argument of the <i>Substring<\/i> method. This will cause an exception of the type <i>System.ArgumentOutOfRangeException<\/i>. Let&#8217;s see why this value can be obtained. In this example, we take no interest in the first two conditions, so they will be omitted in the reasoning.<\/p>\n<p>  The <i>startIndex<\/i> parameter has the <i>int<\/i> type, so its values are in the [-2147483648, 2147483647] range. Therefore, to prevent bounds violation, the developer wrote the following condition:<\/p>\n<pre><code class=\"cpp\">if (startIndex &lt; -1) {   startIndex = 0; }<\/code><\/pre>\n<p>  That is, it was assumed that if a negative value was received, we would simply change it to 0. But instead of &#171;&lt;=&#187; they wrote &#171;&lt;&#171;, and now the range&#8217;s lower limit of the <i>startIndex<\/i> variable (from the analyzer&#8217;s point of view) is -1. <\/p>\n<p>  In these situations, I suggest using a construction like this:<\/p>\n<pre><code class=\"cpp\">if (variable &lt; value) {   variable = value; }<\/code><\/pre>\n<p>  This combination is much easier to read, since it involves one less value. So, I suggest you fix the problem like this:<\/p>\n<pre><code class=\"cpp\">public static string SafeSubstring(....) {   ....   if (startIndex &lt; 0)   {     startIndex = 0;   }    return value.Substring(startIndex,                           Math.Min(length, value.Length - startIndex)); }<\/code><\/pre>\n<p>  You can say that we could have just changed the sign in the condition in the initial example:<\/p>\n<pre><code class=\"cpp\">if (startIndex &lt;= -1) {   startIndex = 0; }<\/code><\/pre>\n<p>  The error also disappears. However, the logic will look like this:<\/p>\n<pre><code class=\"cpp\">if (variable &lt;= value - 1) {   variable = value; }<\/code><\/pre>\n<p>  Agree that it looks overloaded.<\/p>\n<p>  <b>Example 3<\/b><\/p>\n<pre><code class=\"cpp\">public override void OnEndOfAlgorithm() {   var buyingPowerModel = Securities[_contractSymbol].BuyingPowerModel;   var futureMarginModel = buyingPowerModel as FutureMarginModel;   if (buyingPowerModel == null)   {     throw new Exception($\"Invalid buying power model. \" +                         $\"Found: {buyingPowerModel.GetType().Name}. \" +                         $\"Expected: {nameof(FutureMarginModel)}\");     }   .... }<\/code><\/pre>\n<p>  <a href=\"https:\/\/www.viva64.com\/en\/w\/v3080\/\">V3080<\/a> Possible null dereference. Consider inspecting &#8216;buyingPowerModel&#8217;. BasicTemplateFuturesAlgorithm.cs 107<\/p>\n<p>  <a href=\"https:\/\/www.viva64.com\/en\/w\/v3019\/\">V3019<\/a> Possibly an incorrect variable is compared to null after type conversion using &#8216;as&#8217; keyword. Check variables &#8216;buyingPowerModel&#8217;, &#8216;futureMarginModel&#8217;. BasicTemplateFuturesAlgorithm.cs 105<\/p>\n<p>  A very interesting fragment. The analyzer issues two warnings at once. And in fact, they contain the problem and its cause. Firstly, let&#8217;s see what happens if the condition is met. Since <i>buyingPowerModel<\/i> will be strictly <i>null<\/i> inside, dereferencing will occur:<\/p>\n<pre><code class=\"cpp\">$\"Found: {buyingPowerModel.GetType().Name}. \"<\/code><\/pre>\n<p>  The reason is that the condition has a wrong variable compared to <i>null<\/i>. It&#8217;s obvious that <i>futureMarginModel<\/i> should be written instead of <i>buyingPowerModel<\/i>. A fixed version:<\/p>\n<pre><code class=\"cpp\">public override void OnEndOfAlgorithm() {   var buyingPowerModel = Securities[_contractSymbol].BuyingPowerModel;   var futureMarginModel = buyingPowerModel as FutureMarginModel;   if (futureMarginModel == null)   {     throw new Exception($\"Invalid buying power model. \" +                         $\"Found: {buyingPowerModel.GetType().Name}. \" +                         $\"Expected: {nameof(FutureMarginModel)}\");     }   .... }<\/code><\/pre>\n<p>  However, there is still a problem with dereferencing <i>buyingPowerModel<\/i> inside the condition. After all, <i>futureMarginModel<\/i> will be <i>null<\/i> not only when it is not <i>FutureMarginModel<\/i>, but also when <i>buyingPowerModel<\/i> is <i>null<\/i>. So I suggest this version:<\/p>\n<pre><code class=\"cpp\">public override void OnEndOfAlgorithm() {   var buyingPowerModel = Securities[_contractSymbol].BuyingPowerModel;   var futureMarginModel = buyingPowerModel as FutureMarginModel;   if (futureMarginModel == null)   {     string foundType =    buyingPowerModel?.GetType().Name                         ?? \"the type was not found because the variable is null\";     throw new Exception($\"Invalid buying power model. \" +                         $\"Found: {foundType}. \" +                         $\"Expected: {nameof(FutureMarginModel)}\");      }   .... }<\/code><\/pre>\n<p>  Personally, I have recently got to like writing such constructions using <i>is<\/i>. So the code becomes shorter and it is more difficult to make a mistake. This example is completely similar to the example above:<\/p>\n<pre><code class=\"cpp\">public override void OnEndOfAlgorithm() {   var buyingPowerModel = Securities[_contractSymbol].BuyingPowerModel;   if (!(buyingPowerModel is FutureMarginModel futureMarginModel))   {     ....   }   .... }<\/code><\/pre>\n<p>  Moreover, in C# 9.0 we will be able to write the keyword <i>not<\/i>:<\/p>\n<pre><code class=\"cpp\">public override void OnEndOfAlgorithm() {   var buyingPowerModel = Securities[_contractSymbol].BuyingPowerModel;   if (buyingPowerModel is not FutureMarginModel futureMarginModel)   {     ....   }   .... }<\/code><\/pre>\n<p>  <b>Example 4<\/b><\/p>\n<pre><code class=\"cpp\">public static readonly Dictionary&lt;....>    FuturesExpiryDictionary = new Dictionary&lt;....>() {   ....   if (twoMonthsPriorToContractMonth.Month == 2)   {     lastBusinessDay = FuturesExpiryUtilityFunctions                       .NthLastBusinessDay(twoMonthsPriorToContractMonth, 1);   }   else   {     lastBusinessDay = FuturesExpiryUtilityFunctions                       .NthLastBusinessDay(twoMonthsPriorToContractMonth, 1);   }   .... }<\/code><\/pre>\n<p>  <a href=\"https:\/\/www.viva64.com\/en\/w\/v3004\/\">V3004<\/a> The &#8216;then&#8217; statement is equivalent to the &#8216;else&#8217; statement. FuturesExpiryFunctions.cs 1561<\/p>\n<p>  The same logic runs under different conditions. Since one of the arguments is a numeric literal, it is likely that another value may be passed. For example:<\/p>\n<pre><code class=\"cpp\">public static readonly Dictionary&lt;....>    FuturesExpiryDictionary = new Dictionary&lt;....>() {   ....   if (twoMonthsPriorToContractMonth.Month == 2)   {     lastBusinessDay = FuturesExpiryUtilityFunctions                       .NthLastBusinessDay(twoMonthsPriorToContractMonth, 2);   }   else   {     lastBusinessDay = FuturesExpiryUtilityFunctions                       .NthLastBusinessDay(twoMonthsPriorToContractMonth, 1);   }   .... }<\/code><\/pre>\n<p>  But this is nothing more than an assumption. Here I would like to draw attention to the fact that the error occurs in the container&#8217;s initialization. The size of this initialization is almost 2000 lines:<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/087\/52c\/993\/08752c993506f2fde906a3e748b47915.png\" alt=\"image2.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/087\/52c\/993\/08752c993506f2fde906a3e748b47915.png\"\/><\/div>\n<p>  Also, the code fragments inside are similar in appearance, which is logical, because here the collection is simply filled in. Therefore, be very careful when copying something in large and similar sections. Make changes at once, because then your eyes will get tired and you won&#8217;t see the problem.<\/p>\n<p>  <b>Example 5<\/b><\/p>\n<pre><code class=\"cpp\">public AuthenticationToken GetAuthenticationToken(IRestRequest request) {   ....   if (request.Method == Method.GET &amp;&amp; request.Parameters.Count > 0)   {     var parameters = request.Parameters.Count > 0                      ? string.Join(....)                      : string.Empty;     url = $\"{request.Resource}?{parameters}\";   } }<\/code><\/pre>\n<p>  <a href=\"https:\/\/www.viva64.com\/en\/w\/v3022\/\">V3022<\/a> Expression &#8216;request.Parameters.Count > 0&#8217; is always true. GDAXBrokerage.Utility.cs 63<\/p>\n<p>  The condition in the ternary operator is always true, because this check was already performed above. Now this is either a redundant check, or the &#171;&amp;&amp;&#187; and &#171;||&#187; operators are mixed up in the condition above. <\/p>\n<p>  To avoid this, when you are in a condition, always keep in mind at what values you will enter it.<\/p>\n<p>  A possible fixed variant:<\/p>\n<pre><code class=\"cpp\">public AuthenticationToken GetAuthenticationToken(IRestRequest request) {   ....   if (request.Method == Method.GET &amp;&amp; request.Parameters.Count > 0)   {     var parameters = string.Join(....);     url = $\"{request.Resource}?{parameters}\";   } }<\/code><\/pre>\n<p>  <b>Example 6<\/b><\/p>\n<pre><code class=\"cpp\">public bool Setup(SetupHandlerParameters parameters) {   ....   if (job.UserPlan == UserPlan.Free)   {     MaxOrders = 10000;   }   else   {     MaxOrders = int.MaxValue;     MaximumRuntime += MaximumRuntime;   }    MaxOrders = job.Controls.BacktestingMaxOrders; \/\/ &lt;=   .... }<\/code><\/pre>\n<p>  <a href=\"https:\/\/www.viva64.com\/en\/w\/v3008\/\">V3008<\/a> The &#8216;MaxOrders&#8217; variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 244, 240. BacktestingSetupHandler.cs 244<\/p>\n<p>  Here, the <i>MaxOrders<\/i> variable is assigned a value twice in a row. In other words, logic with conditions is unnecessary.<\/p>\n<p>  To fix this, we have 2 options. We either remove the assignments in the then-else branches, or the assignment after the condition. Most likely, the code is covered by tests, and the program works correctly. Therefore, we will leave only the last assignment. A possible fixed variant:<\/p>\n<pre><code class=\"cpp\">public bool Setup(SetupHandlerParameters parameters) {   ....   if (job.UserPlan != UserPlan.Free)   {     MaximumRuntime += MaximumRuntime;   }    MaxOrders = job.Controls.BacktestingMaxOrders;   .... }<\/code><\/pre>\n<p>  <\/p>\n<h2>Typical human failings<\/h2>\n<p>  This section will cover copy-paste errors, accidentally pressed keys, and so on. Basically, the most common problems of human imperfection. We are not robots, so these situations are typical. <\/p>\n<p>  General recommendations on them: <\/p>\n<ul>\n<li>When copying something, make changes to the copy as soon as you paste it;<\/li>\n<li>review the code;<\/li>\n<li>use special tools that will look for errors for you. <\/li>\n<\/ul>\n<p>  <b>Case 1<\/b><\/p>\n<pre><code class=\"cpp\">public class FisherTransform : BarIndicator, IIndicatorWarmUpPeriodProvider {   private readonly Minimum _medianMin;   private readonly Maximum _medianMax;   public override bool IsReady => _medianMax.IsReady &amp;&amp; _medianMax.IsReady; }<\/code><\/pre>\n<p>  <a href=\"https:\/\/www.viva64.com\/en\/w\/v3001\/\">V3001<\/a> There are identical sub-expressions &#8216;_medianMax.IsReady&#8217; to the left and to the right of the &#8216;&amp;&amp;&#8217; operator. FisherTransform.cs 72<\/p>\n<p>  In this example, the <i>IsReady<\/i> field must depend on two conditions, but in fact it depends on one. It&#8217;s all the fault of a typo. Most likely, instead of <i>_medianMin<\/i>, <i>_medianMax<\/i> was written. A fixed version:<\/p>\n<pre><code class=\"cpp\">public class FisherTransform : BarIndicator, IIndicatorWarmUpPeriodProvider {   private readonly Minimum _medianMin;   private readonly Maximum _medianMax;   public override bool IsReady => _medianMin.IsReady &amp;&amp; _medianMax.IsReady; }<\/code><\/pre>\n<p>  <b>Case 2<\/b><\/p>\n<pre><code class=\"cpp\">public BacktestResultPacket(....) : base(PacketType.BacktestResult) {   try   {     Progress = Math.Round(progress, 3);     SessionId = job.SessionId; \/\/ &lt;=     PeriodFinish = endDate;     PeriodStart = startDate;     CompileId = job.CompileId;     Channel = job.Channel;     BacktestId = job.BacktestId;     Results = results;     Name = job.Name;     UserId = job.UserId;     ProjectId = job.ProjectId;     SessionId = job.SessionId; \/\/ &lt;=     TradeableDates = job.TradeableDates;   }   catch (Exception err)    {     Log.Error(err);   } }<\/code><\/pre>\n<p>  <a href=\"https:\/\/www.viva64.com\/en\/w\/v3008\/\">V3008<\/a> The &#8216;SessionId&#8217; variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 182, 172. BacktestResultPacket.cs 182<\/p>\n<p>  The class has many fields that must be initialized \u2013 many lines in the constructor. Everything is merged, and one field is initialized several times. In this case, there may be an extra initialization, or they forgot to initialize some other field.<\/p>\n<p>  If you are interested, you can also check out <a href=\"https:\/\/viva64.com\/en\/examples\/v3008\/\">other errors<\/a> found by this diagnostic rule. <\/p>\n<p>  <b>Case 3<\/b><\/p>\n<pre><code class=\"cpp\">private const string jsonWithScore =             \"{\" +             \"\\\"id\\\":\\\"e02be50f56a8496b9ba995d19a904ada\\\",\" +             \"\\\"group-id\\\":\\\"a02be50f56a8496b9ba995d19a904ada\\\",\" +             \"\\\"source-model\\\":\\\"mySourceModel-1\\\",\" +             \"\\\"generated-time\\\":1520711961.00055,\" +             \"\\\"created-time\\\":1520711961.00055,\" +             \"\\\"close-time\\\":1520711961.00055,\" +             \"\\\"symbol\\\":\\\"BTCUSD XJ\\\",\" +             \"\\\"ticker\\\":\\\"BTCUSD\\\",\" +             \"\\\"type\\\":\\\"price\\\",\" +             \"\\\"reference\\\":9143.53,\" +             \"\\\"reference-final\\\":9243.53,\" +             \"\\\"direction\\\":\\\"up\\\",\" +             \"\\\"period\\\":5.0,\" +             \"\\\"magnitude\\\":0.025,\" +             \"\\\"confidence\\\":null,\" +             \"\\\"weight\\\":null,\" +             \"\\\"score-final\\\":true,\" +             \"\\\"score-magnitude\\\":1.0,\" +             \"\\\"score-direction\\\":1.0,\" +             \"\\\"estimated-value\\\":1113.2484}\";  private const string jsonWithExpectedOutputFromMissingCreatedTimeValue =             \"{\" +             \"\\\"id\\\":\\\"e02be50f56a8496b9ba995d19a904ada\\\",\" +             \"\\\"group-id\\\":\\\"a02be50f56a8496b9ba995d19a904ada\\\",\" +             \"\\\"source-model\\\":\\\"mySourceModel-1\\\",\" +             \"\\\"generated-time\\\":1520711961.00055,\" +             \"\\\"created-time\\\":1520711961.00055,\" +             \"\\\"close-time\\\":1520711961.00055,\" +             \"\\\"symbol\\\":\\\"BTCUSD XJ\\\",\" +             \"\\\"ticker\\\":\\\"BTCUSD\\\",\" +             \"\\\"type\\\":\\\"price\\\",\" +             \"\\\"reference\\\":9143.53,\" +             \"\\\"reference-final\\\":9243.53,\" +             \"\\\"direction\\\":\\\"up\\\",\" +             \"\\\"period\\\":5.0,\" +             \"\\\"magnitude\\\":0.025,\" +             \"\\\"confidence\\\":null,\" +             \"\\\"weight\\\":null,\" +             \"\\\"score-final\\\":true,\" +             \"\\\"score-magnitude\\\":1.0,\" +             \"\\\"score-direction\\\":1.0,\" +             \"\\\"estimated-value\\\":1113.2484}\";<\/code><\/pre>\n<p>  <a href=\"https:\/\/www.viva64.com\/en\/w\/v3091\/\">V3091<\/a> Empirical analysis. It is possible that a typo is present inside the string literal. The &#8216;score&#8217; word is suspicious. InsightJsonConverterTests.cs 209<\/p>\n<p>  Sorry for the large and scary code. Here different fields have the same values. This is a classic error from the copy-paste family. Copied, fell into the muse, forgot to make changes \u2013 here&#8217;s the error. <\/p>\n<p>  <b>Case 4<\/b><\/p>\n<pre><code class=\"cpp\">private void ScanForEntrance() {   var shares = (int)(allowedDollarLoss\/expectedCaptureRange);   ....   if (ShouldEnterLong)   {     MarketTicket = MarketOrder(symbol, shares);     ....   }   else if (ShouldEnterShort)   {     MarketTicket = MarketOrder(symbol, - -shares); \/\/ &lt;=     ....     StopLossTicket = StopMarketOrder(symbol, -shares, stopPrice);     ....   }   .... }<\/code><\/pre>\n<p>  <a href=\"https:\/\/www.viva64.com\/en\/w\/v3075\/\">V3075<\/a> The &#8216;-&#8216; operation is executed 2 or more times in succession. Consider inspecting the &#8216;- -shares&#8217; expression. OpeningBreakoutAlgorithm.cs 328<\/p>\n<p>  The unary operator &#171;-&#187; was used twice in a row. Thus, the value passed to the <i>MarketOrder<\/i> method remains unchanged. It&#8217;s a tricky question how many unary minuses should be left here. Perhaps the prefix decrement operator &#171;&#8212;&#187; was meant to be here, but the <i>space bar<\/i> was accidentally pressed. There are so many variants, so one of the possible corrected options is: <\/p>\n<pre><code class=\"cpp\">private void ScanForEntrance() {   ....   if (ShouldEnterLong)   {     MarketTicket = MarketOrder(symbol, shares);     ....   }   else if (ShouldEnterShort)   {     MarketTicket = MarketOrder(symbol, -shares);     ....     StopLossTicket = StopMarketOrder(symbol, -shares, stopPrice);     ....   }   .... }<\/code><\/pre>\n<p>  <b>Case 5<\/b><\/p>\n<pre><code class=\"cpp\">private readonly SubscriptionDataConfig _config; private readonly DateTime _date; private readonly bool _isLiveMode; private readonly BaseData _factory;  public ZipEntryNameSubscriptionDataSourceReader(     SubscriptionDataConfig config,      DateTime date,     bool isLiveMode) {   _config = config;   _date = date;   _isLiveMode = isLiveMode;   _factory = _factory = config.GetBaseDataInstance(); \/\/ &lt;= }<\/code><\/pre>\n<p>  <a href=\"https:\/\/www.viva64.com\/en\/w\/v3005\/\">V3005<\/a> The &#8216;_factory&#8217; variable is assigned to itself. ZipEntryNameSubscriptionDataSourceReader.cs 50<\/p>\n<p>  The <i>_factory<\/i> field is assigned the same value twice. There are only four fields in the class, so it&#8217;s probably just a misprint. A fixed version:<\/p>\n<pre><code class=\"cpp\">public ZipEntryNameSubscriptionDataSourceReader(....) {   _config = config;   _date = date;   _isLiveMode = isLiveMode;   _factory = config.GetBaseDataInstance(); }<\/code><\/pre>\n<p>  <\/p>\n<h2>Conclusion<\/h2>\n<p>  There are many places where you can make a mistake. We notice and fix some of them immediately. Some of them are fixed in a code review, but I recommend assigning some of them to special tools. <\/p>\n<p>  Also, if you like such a format, please write about it. I&#8217;ll do more like this. Thank you!<\/p><\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/533302\/\"> https:\/\/habr.com\/ru\/articles\/533302\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/c03\/5c9\/633\/c035c9633cc626bfaa3c257ef762961c.png\" alt=\"image1.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/c03\/5c9\/633\/c035c9633cc626bfaa3c257ef762961c.png\"\/><\/div>\n<p>  This article discusses errors found using a static analyzer in an open source project. There are some simple things that can help you avoid them. For example, the usage of language syntactic constructs starting from C# 8.0. We hope it will be exciting. Have fun reading!   <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-392038","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/392038","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=392038"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/392038\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=392038"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=392038"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=392038"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}