<?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>DEV Community: Simone Chiaretta</title>
    <description>The latest articles on DEV Community by Simone Chiaretta (@simonech).</description>
    <link>https://dev.to/simonech</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%2F171618%2F65dee280-3ef0-4a80-bf7f-1adb77b5f458.jpeg</url>
      <title>DEV Community: Simone Chiaretta</title>
      <link>https://dev.to/simonech</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/simonech"/>
    <language>en</language>
    <item>
      <title>How to uninstall old versions of .NET Core</title>
      <dc:creator>Simone Chiaretta</dc:creator>
      <pubDate>Thu, 12 Mar 2020 22:00:26 +0000</pubDate>
      <link>https://dev.to/simonech/how-to-uninstall-old-versions-of-net-core-3a51</link>
      <guid>https://dev.to/simonech/how-to-uninstall-old-versions-of-net-core-3a51</guid>
      <description>&lt;p&gt;Uninstalling old versions of .NET Core used to be a tedious process, so much that I had 1.0 and previews of 2.0 still installed.&lt;/p&gt;

&lt;p&gt;But now it's super easy thanks to the newly released &lt;a href="https://devblogs.microsoft.com/dotnet/announcing-the-net-core-uninstall-tool-1-0/"&gt;.NET Core Uninstall Tool&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Just &lt;a href="https://github.com/dotnet/cli-lab/releases"&gt;install the tool&lt;/a&gt;, and launch the following command to remove all that is not needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ./dotnet-core-uninstall remove --runtime --all
sudo ./dotnet-core-uninstall remove --sdk --all

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



&lt;p&gt;But if you want to understand more, please keep on reading.&lt;/p&gt;

&lt;h3&gt;
  
  
  See which version you have installed
&lt;/h3&gt;

&lt;p&gt;If you run the following command on your terminal you can see all the runtimes and SDKs installed on your machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet --list-sdks
dotnet --list-runtimes

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



&lt;p&gt;On my Mac I have 10 SDKs&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jgFY5ZK6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1080/netcore-sdks-before-compressor.png%3Fwidth%3D800" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jgFY5ZK6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1080/netcore-sdks-before-compressor.png%3Fwidth%3D800" alt=".NET Core SDKs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and 8 versions of the ASP.NET Core runtime and 13 versions of the NETCore runtime.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ka3H0THn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1079/netcore-runtimes-before-compressor.png%3Fwidth%3D800" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ka3H0THn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1079/netcore-runtimes-before-compressor.png%3Fwidth%3D800" alt=".NET Core runtimes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you wanted to get rid of the old version, you had to go and manually delete the content of the folders on Mac and via the "Add or Remove Programs" on Windows.&lt;/p&gt;

&lt;p&gt;But now you can have a tool to do it for you, the &lt;a href="https://docs.microsoft.com/en-us/dotnet/core/additional-tools/uninstall-tool"&gt;.NET Core Uninstall Tool&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The .NET Core Uninstall Tool
&lt;/h3&gt;

&lt;p&gt;After you &lt;a href="https://github.com/dotnet/cli-lab/releases"&gt;installed it&lt;/a&gt;, there are a few commands you can run:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;list&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dry-run&lt;/code&gt; (or &lt;code&gt;whatif&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;remove&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  The list command
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;list&lt;/code&gt; command shows all the SDKs and runtimes you have installed. You can use the options &lt;code&gt;--sdk&lt;/code&gt; or &lt;code&gt;--runtime&lt;/code&gt; to just show either the SDKs or the runtimes. Or &lt;code&gt;--x64&lt;/code&gt; or &lt;code&gt;--x86&lt;/code&gt; to filter based on the architecture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e7-sJ5Ci--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1087/uninstall-list-compressor.png%3Fwidth%3D800" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e7-sJ5Ci--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1087/uninstall-list-compressor.png%3Fwidth%3D800" alt="list all"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, some runtimes and on SDK are marked as not safe to remove.&lt;/p&gt;

&lt;h4&gt;
  
  
  The dry-run command
&lt;/h4&gt;

&lt;p&gt;If you have multiple version installed, you probably don't want to delete them individually. The uninstall tool has a series of options to do a bulk delete. But before you delete everything by mistake, you might want to see what each option does. And here comes the &lt;code&gt;dry-run&lt;/code&gt; command, which lists the versions that would be deleted by the &lt;code&gt;remove&lt;/code&gt; command when called with the same options. Here some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--all&lt;/code&gt; will delete everything&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s6MCr1l0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1083/uninstall-dry-run-all-compressor.png%3Fwidth%3D800" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s6MCr1l0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1083/uninstall-dry-run-all-compressor.png%3Fwidth%3D800" alt="--all"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--all-below &amp;lt;version&amp;gt;&lt;/code&gt;, deletes all versions below the one specified&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--STqx8B8c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1081/uninstall-dry-run-all-below-compressor.png%3Fwidth%3D800" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--STqx8B8c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1081/uninstall-dry-run-all-below-compressor.png%3Fwidth%3D800" alt="--all-below"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--all-but &amp;lt;versions&amp;gt;&lt;/code&gt;, deletes everything but the specified versions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--all-lower-patches&lt;/code&gt;, deletes all versions for which there is a higher patch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--asHSIuzs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1084/uninstall-dry-run-all-lower-compressor.png%3Fwidth%3D800" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--asHSIuzs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1084/uninstall-dry-run-all-lower-compressor.png%3Fwidth%3D800" alt="--all-lower-patches"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--all-previews&lt;/code&gt;, deletes all preview versions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8pZxrFhJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1085/uninstall-dry-run-all-preview-compressor.png%3Fwidth%3D800" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8pZxrFhJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1085/uninstall-dry-run-all-preview-compressor.png%3Fwidth%3D800" alt="--all-previews"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--all-previews-but-latest&lt;/code&gt;, just keeps the more recent preview (useful when testing pre-releases)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--major-minor &amp;lt;major.minor&amp;gt;&lt;/code&gt;, deletes all the version of the specified &lt;code&gt;major.minor&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice that in none of the examples, the versions listed as "not safe" are not appearing. This because if you remove them you might break some functionality. To include them, add the &lt;code&gt;--force&lt;/code&gt; option. But don't worry, you'll get a nice red message to warn you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5d7D2eC8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1082/uninstall-dry-run-all-below-force-compressor.png%3Fwidth%3D800" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5d7D2eC8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1082/uninstall-dry-run-all-below-force-compressor.png%3Fwidth%3D800" alt="--all-below-force"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  The Remove command
&lt;/h4&gt;

&lt;p&gt;Once you've found the parameters to delete the right versions, you can use them with the &lt;code&gt;remove&lt;/code&gt; command, to actually delete the versions. The only difference is that you need to run the tool with elevated rights (as Administrator on Windows or via &lt;code&gt;sudo&lt;/code&gt; on Mac), and that there is a &lt;code&gt;--yes&lt;/code&gt; option to skip the confirmation.&lt;/p&gt;

&lt;p&gt;Normally, unless you want to start a new application in an older version, you can delete everything except the latest SDK and runtimes. If you want to be sure you don't cause any problem, the safest commands are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./dotnet-core-uninstall remove --runtime --all
./dotnet-core-uninstall remove --sdk --all

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



&lt;p&gt;These will uninstall everything that is not needed by Visual Studio.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cgBHwdCJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1086/uninstall-list-after-compressor.png%3Fwidth%3D800" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cgBHwdCJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1086/uninstall-list-after-compressor.png%3Fwidth%3D800" alt="list all after uninstall"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you know you are not going to build new projects with older runtimes, you can also just run &lt;code&gt;remove --runtime --all-but 3.1.1 --force&lt;/code&gt; to just keep the latest version.&lt;/p&gt;

</description>
      <category>netcore</category>
    </item>
    <item>
      <title>7 easy steps to install MiniProfiler on an ASP.NET MVC website</title>
      <dc:creator>Simone Chiaretta</dc:creator>
      <pubDate>Mon, 15 Jul 2019 17:01:40 +0000</pubDate>
      <link>https://dev.to/simonech/7-easy-steps-to-install-miniprofiler-on-an-asp-net-mvc-website-1pp5</link>
      <guid>https://dev.to/simonech/7-easy-steps-to-install-miniprofiler-on-an-asp-net-mvc-website-1pp5</guid>
      <description>&lt;p&gt;Today I wanted to add &lt;a href="https://miniprofiler.com/dotnet/" rel="noopener noreferrer"&gt;MiniProfiler&lt;/a&gt; to an ASP.NET MVC web application (not .NET Core), but unfortunately &lt;a href="https://www.nuget.org/packages/MiniProfiler.Mvc5/" rel="noopener noreferrer"&gt;the NuGet package&lt;/a&gt; doesn't set up things correctly, the &lt;a href="https://miniprofiler.com/dotnet/AspDotNet" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; is a bit lacking, and &lt;a href="https://github.com/MiniProfiler/dotnet/tree/master/samples/Samples.Mvc5" rel="noopener noreferrer"&gt;their sample project&lt;/a&gt; doesn't work so what was supposedly a simple task, took almost a full day of research to make it work.&lt;/p&gt;

&lt;p&gt;In this post, I'm going to explain in 7 easy steps how to install &lt;a href="https://miniprofiler.com/dotnet/" rel="noopener noreferrer"&gt;MiniProfiler&lt;/a&gt; on an empty ASP.NET MVC web application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 - Create an ASP.NET MVC application
&lt;/h3&gt;

&lt;p&gt;To keep things easy, let's start with creating a new ASP.NET MVC application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1077%2Fnew-project.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1077%2Fnew-project.png" alt="Choose ASP.NET Web Application Project"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1073%2Fchoose-template.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1073%2Fchoose-template.png" alt="Choose the MVC template"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 - Install the MiniProfiler.MVC5 Nuget package
&lt;/h3&gt;

&lt;p&gt;The correct NuGet package to install is &lt;code&gt;MiniProfiler.MVC5&lt;/code&gt;, which supplies the core &lt;code&gt;MiniProfiler&lt;/code&gt; package and provides the correct integration with ASP.NET MVC.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Install-Package MiniProfiler.Mvc5

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3 - Add the minimum MiniProfiler configuration
&lt;/h3&gt;

&lt;p&gt;The configuration happens in the &lt;code&gt;Application_Start&lt;/code&gt;, &lt;code&gt;Application_BeginRequest&lt;/code&gt; and &lt;code&gt;Application_EndRequest&lt;/code&gt; inside the &lt;code&gt;Global.asax.cs&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;Application_Start&lt;/code&gt; you have to add the following line, to set up the default options.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MiniProfiler.Configure(new MiniProfilerOptions());

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

&lt;/div&gt;



&lt;p&gt;Moreover, then add the &lt;code&gt;Application_BeginRequest&lt;/code&gt; and &lt;code&gt;Application_EndRequest&lt;/code&gt; methods to start and stop the tracking at each request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;protected void Application_BeginRequest()
{
    MiniProfiler profiler = null;
    if (Request.IsLocal)
    {
        profiler = MiniProfiler.StartNew();
    }
}

protected void Application_EndRequest()
{
    MiniProfiler.Current?.Stop();
}

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4 - Include the scripts in the view
&lt;/h3&gt;

&lt;p&gt;You now need to include the scripts in the views. The easiest way is to add them in &lt;code&gt;Shared/_Layout.cshtml&lt;/code&gt; master view.&lt;/p&gt;

&lt;p&gt;At the top, add the namespace &lt;code&gt;using&lt;/code&gt; declaration &lt;code&gt;@using StackExchange.Profiling;&lt;/code&gt; and at the bottom, just before the &lt;code&gt;&amp;lt;/body&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @MiniProfiler.Current.RenderIncludes()
&amp;lt;/body&amp;gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5 - Configure the site to route all requests as managed code
&lt;/h3&gt;

&lt;p&gt;If you run the site now, nothing happens. The reason is that MiniProfiler relies on a JavaScript library rendered at the moment, and it is requested as &lt;code&gt;.js&lt;/code&gt;, so usually it wouldn't be executed as .NET request. So, you have to add the following line in the &lt;code&gt;web.config&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;system.webServer&amp;gt;
   &amp;lt;modules runAllManagedModulesForAllRequests="true" /&amp;gt;
 &amp;lt;/system.webServer&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;Running now the website you get the MiniProfiler UI in the top left corner of the site, and by clicking you get the execution timings of the page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1074%2Fminiprofiler-ui-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1074%2Fminiprofiler-ui-1.png" alt="Basic profiling information"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6 - Configure to track MVC Controller
&lt;/h3&gt;

&lt;p&gt;The current view is not very useful, as it shows nothing, apart from overall execution. In an ASP.NET MVC application, you can start tracking a bit more information on the execution time of each action, by adding a new filter into the pipeline. Open the &lt;code&gt;FilterConfig.cs&lt;/code&gt; file (if you are following along with the basic template) and add this line to the &lt;code&gt;RegisterGlobalFilters&lt;/code&gt; method&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;filters.Add(new ProfilingActionFilter());

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

&lt;/div&gt;



&lt;p&gt;Now, rerun the same site, and you'll also see the execution time of the controller.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1075%2Fminiprofiler-ui-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1075%2Fminiprofiler-ui-2.png" alt="Profiling Action and Controllers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 7 - Start using it
&lt;/h3&gt;

&lt;p&gt;There is no real step 7... but it's cool to have 7 steps.&lt;/p&gt;

&lt;p&gt;Jokes aside, now that the basic configuration is working, you can head to the official documentation to see &lt;a href="https://miniprofiler.com/dotnet/HowTo/ProfileCode" rel="noopener noreferrer"&gt;how to start profiling&lt;/a&gt; portions of your code in a way that matters, usually done via the &lt;code&gt;Step&lt;/code&gt; and &lt;code&gt;CustomTiming&lt;/code&gt; methods.&lt;/p&gt;

&lt;p&gt;Here some sample code you could add to your actions to experiment a bit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public ActionResult Index()
{
    var profiler = MiniProfiler.Current;
    using (profiler.Step("Set page title"))
    {
        ViewBag.Title = "Home Page";
    }

    using (profiler.Step("Doing complex stuff"))
    {
        using (profiler.Step("Step A"))
        {
            // simulate fetching a url
            using (profiler.CustomTiming("http", "GET http://google.com"))
            {
                Thread.Sleep(10);
            }
        }
        using (profiler.Step("Step B"))
        {
            // simulate fetching a url
            using (profiler.CustomTiming("http", "GET http://stackoverflow.com"))
            {
                Thread.Sleep(20);
            }

            using (profiler.CustomTiming("redis", "SET \"mykey\" 10"))
            {
                Thread.Sleep(5);
            }
        }
    }

    // now something that loops
    for (int i = 0; i &amp;lt; 15; i++)
    {
        using (profiler.CustomTiming("redis", "SET \"mykey\" 10"))
        {
            Thread.Sleep(i);
        }
    }

    return View();
}

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

&lt;/div&gt;



&lt;p&gt;This code generates the trace shown in the following picture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1076%2Fminiprofiler-ui-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1076%2Fminiprofiler-ui-3.png" alt="Warnings and categories"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can notice some interesting information detected by MiniProfiler. It detected that the code is calling the same 15 times (the loop at the bottom of the action method) and that how much of the time is spent in different categories of operations (in the example, &lt;code&gt;http&lt;/code&gt; and &lt;code&gt;redis&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;An additional feature to add would be tracking SQL statements with the EF6 integration.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>performance</category>
    </item>
    <item>
      <title>How to run micro-benchmarking with BenchmarkDotNet - Bonus post from The Ray Tracer Challenge series</title>
      <dc:creator>Simone Chiaretta</dc:creator>
      <pubDate>Mon, 24 Jun 2019 07:32:08 +0000</pubDate>
      <link>https://dev.to/simonech/how-to-run-micro-benchamarking-with-benchmarkdotnet-bonus-post-from-the-ray-tracer-challenge-series-4eic</link>
      <guid>https://dev.to/simonech/how-to-run-micro-benchamarking-with-benchmarkdotnet-bonus-post-from-the-ray-tracer-challenge-series-4eic</guid>
      <description>&lt;p&gt;In the context of my &lt;a href="http://codeclimber.net.nz/archive/2019/05/22/raytracer-challenge-netcore-intro/" rel="noopener noreferrer"&gt;Ray Tracer Challenge&lt;/a&gt;, I wanted to run some performance analysis on my basic operations and data structures. For this installed and used &lt;a href="https://benchmarkdotnet.org" rel="noopener noreferrer"&gt;BenchmarkDotNet&lt;/a&gt;, an OSS benchmarking tool used by Microsoft for performance testing the .NET Core runtime and class library.&lt;/p&gt;

&lt;p&gt;In this post, I'm going to share what I learned about this powerful tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to install BenchmarkDotNet
&lt;/h2&gt;

&lt;p&gt;BenchmarkDotNet is not an application you have to install. It is a .NET library. To install it, create a console application and install the NuGet package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet new console
dotnet add package BenchmarkDotNet

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

&lt;/div&gt;



&lt;p&gt;As simple as that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing benchmarks
&lt;/h2&gt;

&lt;p&gt;Now that you have the project, you need to create a class with the benchmarks you want to run, and finally, add one line to the &lt;code&gt;Main&lt;/code&gt; of the &lt;code&gt;Program&lt;/code&gt; to start the execution of the benchmarks.&lt;/p&gt;

&lt;p&gt;Here a simple example that shows how to test the "performances" of the &lt;code&gt;Sleep&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System;
using System.Threading;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

namespace MyBench
{
    public class Sleeps
    {
        [Benchmark]
        public void Time50() =&amp;gt; Thread.Sleep(50);

        [Benchmark(Baseline = true)]
        public void Time100() =&amp;gt; Thread.Sleep(100);

        [Benchmark]
        public void Time150() =&amp;gt; Thread.Sleep(150);
    }

    class Program
    {
        static void Main(string[] args)
        {
            var summary = BenchmarkRunner.Run&amp;lt;Sleeps&amp;gt;();
        }
    }
}

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

&lt;/div&gt;



&lt;p&gt;Notice that every method has the &lt;code&gt;[Benchmark]&lt;/code&gt; attribute.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running benchmarks
&lt;/h2&gt;

&lt;p&gt;Now it's time to run the benchmarks. To do it, just run the console application: &lt;code&gt;dotnet run&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Unfortunately here you encountered the first problem, indicated by a red line in the terminal: you cannot run a benchmark in debug mode.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Assembly MyBench which defines benchmarks is non-optimized Benchmarkwas built without optimization enabled (most probably a DEBUGconfiguration). Please, build it in RELEASE. If you want to debug thebenchmarks, please seehttps://benchmarkdotnet.org/articles/guides/troubleshooting.html#debugging-benchmarks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Unless you want to run the benchmark in debug mode, you have to run it in release mode: &lt;code&gt;dotnet run -c Release&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At this point, you see either one or two more red messages in the terminal, but the execution goes on and complete successfully.&lt;/p&gt;

&lt;p&gt;The first complains that there is no solution file. Since you only created a project, this is normal. So skip over it.&lt;/p&gt;

&lt;p&gt;The second, which might not appear depending on the OS and permission of the users you logged in with, is also not affecting the success of the execution but might affect the results.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Failed to set up high priority. Make sure you have the rightpermissions. Message: Permission denied&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This message means that the benchmark runner was not able to set the execution to high CPU priority, so the benchmark will run slower, especially if other applications are running at the same time.&lt;/p&gt;

&lt;p&gt;If you encounter this problem, either run the command as Administrator on Windows or &lt;code&gt;sudo&lt;/code&gt; it if running on Mac or Linux.&lt;/p&gt;

&lt;p&gt;Having solved the two issues, the correct way of starting the benchmark is &lt;code&gt;sudo dotnet run -c Release&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Analysing the results
&lt;/h2&gt;

&lt;p&gt;After a while (the example of this post took 45 seconds to complete), you get a summary with the mean execution time of all your benchmarks. By default, you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Markdown (Github dialect)&lt;/li&gt;
&lt;li&gt;HTML report&lt;/li&gt;
&lt;li&gt;CSV you can import in Excel for additional analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As example this is what I got from my machine:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Mean&lt;/th&gt;
&lt;th&gt;Error&lt;/th&gt;
&lt;th&gt;StdDev&lt;/th&gt;
&lt;th&gt;Ratio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Time50&lt;/td&gt;
&lt;td&gt;52.28 ms&lt;/td&gt;
&lt;td&gt;0.4682 ms&lt;/td&gt;
&lt;td&gt;0.4380 ms&lt;/td&gt;
&lt;td&gt;0.51&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time100&lt;/td&gt;
&lt;td&gt;101.99 ms&lt;/td&gt;
&lt;td&gt;0.9778 ms&lt;/td&gt;
&lt;td&gt;0.9146 ms&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time150&lt;/td&gt;
&lt;td&gt;151.74 ms&lt;/td&gt;
&lt;td&gt;0.9426 ms&lt;/td&gt;
&lt;td&gt;0.8817 ms&lt;/td&gt;
&lt;td&gt;1.49&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Usually, you'd get only the Mean, Error and StdDev columns, but since one of the benchmarks was marked as baseline (using the attribute &lt;code&gt;[Benchmark(Baseline = true)]&lt;/code&gt;), there is also the Ratio column, which tells you the relative difference in performances.&lt;/p&gt;

&lt;p&gt;BenchmarkDotNet can also generate plots with a summary of the results and with a detailed analysis of each execution. It relies on &lt;a href="https://www.r-project.org/" rel="noopener noreferrer"&gt;R&lt;/a&gt; (a statistical analysis framework) for the execution, so you'd need to install it. On Mac, it's as easy as &lt;code&gt;brew install r&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1067%2F5-barplot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1067%2F5-barplot.png" alt="enter image description here"&gt;&lt;/a&gt; &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1069%2F5-boxplot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1069%2F5-boxplot.png" alt="enter image description here"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional features of BenchmarkDotNet
&lt;/h2&gt;

&lt;p&gt;We just scratched the surface of BenchmarkDotNet. It has many more features that allow you to run benchmarks under different conditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Environments
&lt;/h3&gt;

&lt;p&gt;You can, for example, ask to run the same benchmark on different frameworks, like .NET Core, Mono, x86 or x64 and then compare the results. This is configured via attributes, &lt;code&gt;[CoreJob, ClrJob, MonoJob]&lt;/code&gt;, or by providing a configuration object.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parameters
&lt;/h3&gt;

&lt;p&gt;Another interesting feature is the possibility of executing the same benchmarks with different parameters, for example, to see if a particular operation degrades when the number of iterations increases. This is also done with an attribute, [Params].&lt;/p&gt;

&lt;p&gt;For example, the same &lt;code&gt;Sleep&lt;/code&gt; test could have been done using parameters instead of creating three different benchmarks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Sleeps
{
    [Params(50, 100, 150)]
    public int T { get; set; }

    [Benchmark]
    public void Sleep() =&amp;gt; Thread.Sleep(T);
}

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

&lt;/div&gt;



&lt;p&gt;The result is slightly different:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;T&lt;/th&gt;
&lt;th&gt;Mean&lt;/th&gt;
&lt;th&gt;Error&lt;/th&gt;
&lt;th&gt;StdDev&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sleep&lt;/td&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;td&gt;52.09 ms&lt;/td&gt;
&lt;td&gt;0.7825 ms&lt;/td&gt;
&lt;td&gt;0.7319 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sleep&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;102.21 ms&lt;/td&gt;
&lt;td&gt;1.2101 ms&lt;/td&gt;
&lt;td&gt;1.1319 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sleep&lt;/td&gt;
&lt;td&gt;150&lt;/td&gt;
&lt;td&gt;152.25 ms&lt;/td&gt;
&lt;td&gt;1.3064 ms&lt;/td&gt;
&lt;td&gt;1.2220 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This approach makes it also more comfortable to compare the results using the default plots generated with R, as some of the charts become more useful.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1066%2F5-barplot-params.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1066%2F5-barplot-params.png" alt="enter image description here"&gt;&lt;/a&gt; &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1068%2F5-boxplot-params.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1068%2F5-boxplot-params.png" alt="enter image description here"&gt;&lt;/a&gt; &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1070%2F5-density-params.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fcodeclimber.net.nz%2Fmedia%2F1070%2F5-density-params.png" alt="enter image description here"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Running benchmarks
&lt;/h2&gt;

&lt;p&gt;You have already seen the most straightforward way of running the benchmark by merely running the project.&lt;/p&gt;

&lt;p&gt;Unfortunately, this method is very limited.&lt;/p&gt;

&lt;h3&gt;
  
  
  Specifying console arguments
&lt;/h3&gt;

&lt;p&gt;A better method is to change the &lt;code&gt;Main&lt;/code&gt; to use &lt;code&gt;BenchmarkSwitcher&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;static void Main(string[] args)
            =&amp;gt; BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);

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

&lt;/div&gt;



&lt;p&gt;This allows a lot of parameters to be passed to the benchmark execution. You can filter which benchmarks to run, change the runtimes on which to run, and specify other configurations parameters that otherwise had to be specified in code or with attributes directly in the benchmark.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using the global dotnet tool
&lt;/h3&gt;

&lt;p&gt;A final way of running benchmarks is via the global dotnet tool.&lt;/p&gt;

&lt;p&gt;You can install it via &lt;code&gt;dotnet tool install -g BenchmarkDotNet.Tool&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once installed you can run a benchmark by specifying the name of the dll (&lt;code&gt;dotnet benchmark MyBench.dll&lt;/code&gt;), and then the same console arguments as with the &lt;code&gt;BenchmarkSwitcher&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;I hope I gave you a good overview of this fantastic tool. You can read more information on the official web site &lt;a href="https://benchmarkdotnet.org/articles/overview.html" rel="noopener noreferrer"&gt;https://benchmarkdotnet.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While exploring this tool, I tried testing the performance of various ways of concatenating strings. Is &lt;code&gt;StringBuilder&lt;/code&gt; faster or slower than &lt;code&gt;String.Join&lt;/code&gt;? Follow me &lt;a href="https://dev.to/simonech"&gt;on DEV.to&lt;/a&gt; and &lt;a href="https://twitter.com/simonech" rel="noopener noreferrer"&gt;on Twitter&lt;/a&gt; to get notified when my analysis on this gets published.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>netcore</category>
      <category>discuss</category>
      <category>challenge</category>
    </item>
    <item>
      <title>Free eBook on ASP.Net Core 2.2 is available for download</title>
      <dc:creator>Simone Chiaretta</dc:creator>
      <pubDate>Fri, 21 Jun 2019 13:53:33 +0000</pubDate>
      <link>https://dev.to/simonech/free-ebook-on-asp-net-core-2-2-is-available-for-download-1moo</link>
      <guid>https://dev.to/simonech/free-ebook-on-asp-net-core-2-2-is-available-for-download-1moo</guid>
      <description>&lt;p&gt;The eBook on ASP.NET Core 2 I wrote together with &lt;a href="http://tostring.it/"&gt;Ugo Lattanzi&lt;/a&gt; is available for &lt;a href="https://www.syncfusion.com/ebooks/aspnet-core-2-succinctly"&gt;download for free&lt;/a&gt; from the &lt;a href="https://www.syncfusion.com/resources/techportal/ebooks"&gt;Free Ebooks section of Syncfusion Tech Portal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In April 2017, Ugo Lattanzi and I published &lt;a href="https://www.syncfusion.com/ebooks/asp_net_core_succinctly"&gt;ASP.NET Core Succinctly&lt;/a&gt;, and it became one of the most downloaded ebook for 2017 and was also &lt;a href="https://www.syncfusion.com/awards/succinctlyseries/2017succinctlyreadersawards"&gt;2017 Succinctly Readers Awards Silver Winner&lt;/a&gt;, among all the 33 books released by Succinctly in 2017.&lt;/p&gt;

&lt;p&gt;This year we published an update to the book. All code and explanation have been adapted and updated to cover version 2.2 of ASP.NET Core, and also we added features that were not available before like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Health Checks&lt;/li&gt;
&lt;li&gt;SPA templates&lt;/li&gt;
&lt;li&gt;Razor Pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, if you haven't already, go download the &lt;a href="https://www.syncfusion.com/ebooks/aspnet-core-2-succinctly"&gt;book&lt;/a&gt; and let us know what you think of it.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>netcore</category>
      <category>book</category>
    </item>
    <item>
      <title>The Ray Tracer Challenge - Drawing to a canvas and saving the image to a file</title>
      <dc:creator>Simone Chiaretta</dc:creator>
      <pubDate>Mon, 10 Jun 2019 16:51:24 +0000</pubDate>
      <link>https://dev.to/simonech/the-ray-tracer-challenge-drawing-to-a-canvas-and-saving-the-image-to-a-file-5gl6</link>
      <guid>https://dev.to/simonech/the-ray-tracer-challenge-drawing-to-a-canvas-and-saving-the-image-to-a-file-5gl6</guid>
      <description>&lt;p&gt;In the previous post, I've shown how I implemented chapter 1 of the &lt;a href="https://amzn.to/2Elaxkr"&gt;Ray Tracing Challenge book&lt;/a&gt;, coding the basic primitives and their operations. And also implemented a ballistic trajectory calculator. In chapter 2, the goal is to be able to draw an image on a canvas and then saving it to a file.&lt;/p&gt;

&lt;p&gt;If you didn't, I recommend you read my &lt;a href="http://codeclimber.net.nz/archive/2019/05/22/raytracer-challenge-netcore-intro/"&gt;introductory post&lt;/a&gt; which explains what I'm trying to achieve and why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges encountered
&lt;/h2&gt;

&lt;p&gt;This was a more straightforward exercise than the one in the previous chapter, but still, not everything was simple.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modeling the Color class
&lt;/h3&gt;

&lt;p&gt;The concept behind drawing images is very simple. An image is a matrix of pixels, and the value of each pixel is a color. And a color is a "tuple" of three values (the Red, Green, Blue components).&lt;/p&gt;

&lt;p&gt;For this reason, the author suggests refactoring the implementation of the &lt;code&gt;Tuple&lt;/code&gt; so that there is no need to reimplement the basic operations (add, subtract and multiplication by a scalar). I thought of creating a &lt;code&gt;TupleBase&lt;/code&gt; class, which extends &lt;code&gt;Array&lt;/code&gt; and implement those 3 operations on the array. Unfortunately, in C#, the &lt;code&gt;Array&lt;/code&gt; is a sealed class, and cannot be used as base class. I thought of using a &lt;code&gt;List&lt;/code&gt;, but it would probably with a very high-performance cost. I finally decided to just duplicate the code for the 3 operations, and come back to it after this chapter is done.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Color
{
    public static readonly Color Black = new Color(0, 0, 0);

    public Color(double r, double g, double b)
    {
        Red = r;
        Green = g;
        Blue = b;
    }

    public double Red { get; set; }
    public double Green { get; set; }
    public double Blue { get; set; }

    //All operations
}

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



&lt;p&gt;On my GitHub repository, you see the implementation till this point going the tag &lt;a href="https://github.com/simonech/ray-tracer-challenge-netcore/tree/Chapter-2.1"&gt;Chapter 2.1&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modeling the Canvas class
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Canvas&lt;/code&gt; class was pretty straightforward to implement. I used a bi-dimensional array to store the values and implemented an index accessor for setting and reading the values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Canvas
{
    private Color[,] canvas;

    public Canvas(int width, int height) : this(width, height, Color.Black)
    {

    }
    public Canvas(int width, int height, Color background)
    {
        Width = width;
        Height = height;
        canvas = new Color[width, height];
        Initialize(background);
    }

    public int Width { get; set; }
    public int Height { get; set; }

    public Color this[int x, int y]
    {
        get
        {
            return canvas[x, y];
        }

        set
        {
            canvas[x, y] = value;
        }
    }
}

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



&lt;p&gt;This indexer works fine, but intellisense doesn't show the name of the variables, and while writing the exercise I wish I wrote an explicit method to set the color of a pixel, like &lt;code&gt;Canvas.SetPixelAt(int x, int y, Color color)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On my GitHub repository, you see the implementation of the canvas on the tag &lt;a href="https://github.com/simonech/ray-tracer-challenge-netcore/tree/Chapter-2.2"&gt;Chapter 2.2&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Finally, while writing this post I realized I could have used the same approach also for the base tuple class. I guess now I know how to refactor the implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing the PPM writer
&lt;/h3&gt;

&lt;p&gt;The PPM file format is the most basic file format existing. Each pixel is represented with a string with the three components. If a pixel is white, it will be represented as &lt;code&gt;255 255 255&lt;/code&gt;, 12 bytes per pixel. While a black pixel will be 6 bytes. This makes it probably the most inefficient image format existing. I guess in my "refactoring sprint", I'll try to implement a more efficient format.&lt;/p&gt;

&lt;p&gt;Each row of pixels is represented as a series of lines, of max 70 chars, so the code for rendering must also take care of this limit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public string GetPPMContent()
{
    var builder = new StringBuilder();
    builder.AppendLine("P3");
    builder.AppendLine($"{Width} {Height}");
    builder.AppendLine("255");
    for (int y = 0; y &amp;lt; Height; y++)
    {
        int lineLength = 0;
        for (int x = 0; x &amp;lt; Width; x++)
        {
            string[] colorA = canvas[x, y].ToRGBA();
            foreach (var color in colorA)
            {
                if (lineLength + 1 + color.Length &amp;gt; 70)
                {
                    builder.AppendLine();
                    lineLength = 0;
                }
                if(lineLength!=0)
                {
                    builder.Append(" ");
                    lineLength++;
                }
                builder.Append(color);
                lineLength += color.Length;
            }
        }
        builder.AppendLine();
    }
    return builder.ToString();
}

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



&lt;p&gt;This algorithm works but doesn't feel right. Probably there is a more elegant way of doing it. More food for my refactoring sprint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;p&gt;With those basic image drawing methods implemented, the exercise for chapter 2 was drawing the trajectory implemented in the previous chapter. This was a pretty simple exercise. Only needed to make sure the trajectory felt inside the canvas.&lt;/p&gt;

&lt;p&gt;Here is the code for the method that plots the position of the projectile on the canvas, in red.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private static void Draw(Canvas canvas, Tuple position)
{
    var x = (int)sys.Math.Round(position.X);
    var y = canvas.Height - (int)sys.Math.Round(position.Y) - 1;
    //sys.Console.WriteLine($" {x},{y} - {position}");
    if (x &amp;gt;= 0 &amp;amp;&amp;amp; x &amp;lt;= canvas.Width - 1 &amp;amp;&amp;amp; y &amp;gt;= 0 &amp;amp;&amp;amp; y &amp;lt;= canvas.Height - 1)
    {
        canvas[x, y] = new Color(1, 0, 0);
    }
}

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



&lt;p&gt;The complex part of the exercise was finding some initial values that would produce something visible. The values used in chapter 1 would have fit in a 10 by 10 image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var p = new Projectile(Tuple.Point(0, 0, 0), Tuple.Vector(1, 1, 0).Normalize());
var e = new Environment(Tuple.Vector(0, -0.1, 0), Tuple.Vector(-0.01, 0, 0));
var c = new Canvas(10, 10);

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



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r8PuH23E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1061/4-trajectory-10x10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r8PuH23E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1061/4-trajectory-10x10.png" alt="10 by 10"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To generate something more visible I had to increase the velocity of the projectile by 11 (while keeping gravity and wind the same) and launched it at a steeper angle. And with these values, the chart fits into an image which is 900 per 550.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var p = new Projectile(Tuple.Point(0, 1, 0), Tuple.Vector(1, 1.8, 0).Normalize().Multiply(11.3));
var e = new Environment(Tuple.Vector(0, -0.1, 0), Tuple.Vector(-0.01, 0, 0));
var c = new Canvas(900, 550);

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



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hfLZWZ_n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1062/4-trajectory-900x500.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hfLZWZ_n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1062/4-trajectory-900x500.png" alt="900 by 550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On my GitHub repository, you can have a look at the &lt;a href="https://github.com/simonech/ray-tracer-challenge-netcore/tree/Chapter2-End/Exercises/Chapter%202"&gt;code of the exercise&lt;/a&gt;, and the output, both images, the &lt;a href="https://github.com/simonech/ray-tracer-challenge-netcore/blob/Chapter2-End/Exercises/Chapter%202/Results/file-10x10.ppm"&gt;10x10&lt;/a&gt; and &lt;a href="https://github.com/simonech/ray-tracer-challenge-netcore/blob/Chapter2-End/Exercises/Chapter%202/Results/file-900x500.ppm"&gt;900x550&lt;/a&gt; sizes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;This chapter was easier to implement than the previous one, but there is still something I'd love to improve. Specifically, I'd like to refactor the &lt;code&gt;Color&lt;/code&gt; implementation as child class of a &lt;code&gt;TupleBase&lt;/code&gt; shared with the other &lt;code&gt;Tuple&lt;/code&gt; class for point and vectors. Also, see if I can make the PPM serialization code a bit nicer and find a more storage efficient file format.&lt;/p&gt;

&lt;p&gt;Together with these tasks, I also want to go back to the basic primitives and implement math as operations overloads and do some performance testing to find the most performing data storage solution.&lt;/p&gt;

&lt;p&gt;If you like this series of posts and don't want to miss my next episode, please consider subscribing.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>challenge</category>
      <category>netcore</category>
      <category>discuss</category>
    </item>
    <item>
      <title>The Ray Tracer Challenge - Implementing primitives and vector algebra operations</title>
      <dc:creator>Simone Chiaretta</dc:creator>
      <pubDate>Wed, 05 Jun 2019 11:46:11 +0000</pubDate>
      <link>https://dev.to/simonech/the-ray-tracer-challenge-implementing-primitives-and-vector-algebra-operations-23ed</link>
      <guid>https://dev.to/simonech/the-ray-tracer-challenge-implementing-primitives-and-vector-algebra-operations-23ed</guid>
      <description>&lt;p&gt;After setting up the project, in this post I start implementing the code for the first chapter of the &lt;a href="https://amzn.to/2Elaxkr"&gt;Ray tracing challenge book&lt;/a&gt;, which focuses mostly on defining primitives (Point and Vectors), and vector algebra operations like addition, subtraction and also dot and cross products. And a simple ballistic problem to put all the operations in practice.&lt;/p&gt;

&lt;p&gt;If you want to know more, you can read &lt;a href="http://codeclimber.net.nz/archive/2019/05/22/raytracer-challenge-netcore-intro/"&gt;the motivations about this "challenge" in my introductory post&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges encountered
&lt;/h2&gt;

&lt;p&gt;At first, it looked a simple task: how hard could it be to write some methods to perform simple addition, subtractions, and some other basic formulas?&lt;/p&gt;

&lt;p&gt;But it was not.&lt;/p&gt;

&lt;h3&gt;
  
  
  "Re-learning" vector algebra
&lt;/h3&gt;

&lt;p&gt;The first main challenge was "re-learning" vector algebra, and the meaning of the various operations. The book explained well enough for the purpose of the implementation, but I wanted to understand a bit more, and Wikipedia helped a lot. Here some of the links I found:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Euclidean_vector"&gt;Euclidean vector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Dot_product"&gt;Dot product&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Cross_product"&gt;Cross product&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Modeling the primitives
&lt;/h3&gt;

&lt;p&gt;The main primitive in the 3D space is a Tuple (of 4 elements), with the 3 coordinates (&lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;, &lt;code&gt;z&lt;/code&gt;) and a value (&lt;code&gt;w&lt;/code&gt;) to identify it is either a vector (&lt;code&gt;w=0&lt;/code&gt;) or a point (&lt;code&gt;w=1&lt;/code&gt;). I don't know if this is a standard approach or just something the author of the book came up with. Additionally, in chapter 1 the reasoning is not explained but refers to a later chapter to better understand the meaning of this abstraction.&lt;/p&gt;

&lt;p&gt;In order to simplify the creation points and vectors, as tuples with the correct value for &lt;code&gt;w&lt;/code&gt;, it suggests creating factory methods.&lt;/p&gt;

&lt;p&gt;But the book uses pseudocode so that the ray tracer can be implemented in any language, both procedural and object-oriented. For this reason, no additional advice is given on how to actually implement it.&lt;/p&gt;

&lt;p&gt;I tried a few approaches.&lt;/p&gt;

&lt;h4&gt;
  
  
  Inheritance
&lt;/h4&gt;

&lt;p&gt;Instead of creating factory methods, since C# is an object-oriented language, I implemented the primitives as a &lt;code&gt;Tuple&lt;/code&gt; base class, that implements all common operations, and two subclasses, &lt;code&gt;Point&lt;/code&gt; and &lt;code&gt;Vector&lt;/code&gt;, whose constructor sets the correct value for the &lt;code&gt;w&lt;/code&gt; parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Tuple
{
    public Tuple(double x, double y, double z, double w)
    {
        X = x;
        Y = y;
        Z = z;
        W = w;
    }

    public double X { get; set; }
    public double Y { get; set; }
    public double Z { get; set; }
    public double W { get; set; }

    public Tuple Add(Tuple other)
    {
        return new Tuple(
            X + other.X,
            Y + other.Y,
            Z + other.Z,
            W + other.W
        );
    }

    // All other operations
    ...
}

public class Point : Tuple
{
    public Point(double x, double y, double z) : base(x, y, z, 1.0f) { }
}

public class Vector : Tuple
{
    public Vector(double x, double y, double z) : base(x, y, z, 0) { }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It all went fine in the implementation of the library, but things started to fail in the first exercise. The reason is that adding a &lt;code&gt;Point&lt;/code&gt; to a &lt;code&gt;Vector&lt;/code&gt; should produce a &lt;code&gt;Point&lt;/code&gt;. But with this inheritance scheme, that addition will create a &lt;code&gt;Tuple&lt;/code&gt; that cannot be cast to a &lt;code&gt;Point&lt;/code&gt;. It took me a while to understand that there is no way around this problem (it's actually how inheritance works).&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;Projectile&lt;/code&gt; (the exercise is a simple ballistic trajectory calculator) is defined as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public Projectile(Point position, Vector velocity)
{
    Position = position;
    Velocity = velocity;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When updating the position of the projectile after one &lt;em&gt;tick&lt;/em&gt; you have to add the current position to the current velocity. The result is logically another point (the new &lt;code&gt;w&lt;/code&gt; is &lt;code&gt;1+0=1&lt;/code&gt;), but the &lt;code&gt;Add&lt;/code&gt; method returns a new &lt;code&gt;Tuple&lt;/code&gt;, and this cannot be cast to a &lt;code&gt;Point&lt;/code&gt; later on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static Projectile Update(Projectile p, Environment e)
{
    return new Projectile(
        p.Position.Add(p.Velocity),
        p.Velocity.Add(e.Gravity).Add(e.Wind)
    );
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can see far I went before getting stuck, on my repo, on branch &lt;a href="https://github.com/simonech/ray-tracer-challenge-netcore/tree/Chapter-1.2"&gt;Chapter 1.2&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's a pity this doesn't work because that would have allowed the most code re-use and keeping point and vector as two separate entities.&lt;/p&gt;

&lt;h4&gt;
  
  
  Inner value
&lt;/h4&gt;

&lt;p&gt;I then started looking for another solution, to be able to keep the two separate objects, and I implemented them using the "inner value" approach (not sure it's the right name): both &lt;code&gt;Point&lt;/code&gt; and &lt;code&gt;Vector&lt;/code&gt; have an "innerValue" object of type &lt;code&gt;Tuple&lt;/code&gt; on which all operations are done.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Tuple
{
    public Tuple(double x, double y, double z, double w)
    {
        X = x;
        Y = y;
        Z = z;
        W = w;
    }

    public double X { get; set; }
    public double Y { get; set; }
    public double Z { get; set; }
    public double W { get; set; }

    public Tuple Add(Tuple other)
    {
        return new Tuple(
            X + other.X,
            Y + other.Y,
            Z + other.Z,
            W + other.W
        );
    }

    // All other operations
    ...
}

public class Point
{
    private Tuple _innerValue;

    public Tuple InnerValue { get =&amp;gt; _innerValue; set =&amp;gt; _innerValue = value; }

    public Point(double x, double y, double z)
    {
        InnerValue = new Tuple(x, y, z, 1);
    }

    public Point(Tuple tuple)
    {
        InnerValue = tuple;
    }

    public double X { get =&amp;gt; _innerValue.X; set =&amp;gt; _innerValue.X = value; }
    public double Y { get =&amp;gt; _innerValue.Y; set =&amp;gt; _innerValue.Y = value; }
    public double Z { get =&amp;gt; _innerValue.Z; set =&amp;gt; _innerValue.Z = value; }

    public Point Add(Vector other)
    {
        return new Point(InnerValue.Add(other.InnerValue));
    }
    // All other operations
}

public class Vector
{
    private Tuple _innerValue;

    public Tuple InnerValue { get =&amp;gt; _innerValue; set =&amp;gt; _innerValue = value; }

    public Vector(double x, double y, double z) 
    {
        InnerValue = new Tuple(x, y, z, 0);
    }

    public Vector(Tuple tuple)
    {
        InnerValue = tuple;
    }

    public double X { get =&amp;gt; _innerValue.X; set =&amp;gt; _innerValue.X = value; }
    public double Y { get =&amp;gt; _innerValue.Y; set =&amp;gt; _innerValue.Y = value; }
    public double Z { get =&amp;gt; _innerValue.Z; set =&amp;gt; _innerValue.Z = value; }

    public Vector Add(Vector other)
    {
        return new Vector(InnerValue.Add(other.InnerValue));
    }

    public Vector Add(Point other)
    {
        return new Vector(InnerValue.Add(other.InnerValue));
    }

    //All other operations

}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This approach works, but, unlike the previous approach, I had to reimplement all methods, with the logic of the operation, was delegated to the &lt;code&gt;Tuple&lt;/code&gt;. The advantage of this approach is that it is possible to limit the operations (for example, you cannot add 2 points, or subtract a point from a vector) and specify the correct return type (the sum of two vectors is a vector, but the sum of a point and a vector is a point).&lt;/p&gt;

&lt;p&gt;This approach works, but it doesn't feel right. Too much code duplication.&lt;/p&gt;

&lt;p&gt;You can see how this was implemented on the branch &lt;a href="https://github.com/simonech/ray-tracer-challenge-netcore/tree/inner-element"&gt;inner-element&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Using factory methods
&lt;/h4&gt;

&lt;p&gt;Finally, I tried using to the suggestion of the author, and I deleted the two classes, only keeping the &lt;code&gt;Tuple&lt;/code&gt;, to which I added the 2 static factory methods to set the &lt;code&gt;w&lt;/code&gt; parameter for points (&lt;code&gt;w=1&lt;/code&gt;) and vectors (&lt;code&gt;w=0&lt;/code&gt;). The disadvantage is that I lose the possibility of limiting some operations to either point or vectors and that I cannot easily understand if a tuple is a point or a vector just by reading the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Tuple
{
    public static Tuple Point(double x, double y, double z)
    {
        return new Tuple(x, y, z, 1);
    }

    public static Tuple Vector(double x, double y, double z)
    {
        return new Tuple(x, y, z, 0);
    }

    public Tuple(double x, double y, double z, double w)
    {
        X = x;
        Y = y;
        Z = z;
        W = w;
    }

    public double X { get; set; }
    public double Y { get; set; }
    public double Z { get; set; }
    public double W { get; set; }

    public bool IsPoint { get =&amp;gt; W == 1; }
    public bool IsVector { get =&amp;gt; W == 0; }

    public Tuple Add(Tuple other)
    {
        return new Tuple(
            X + other.X,
            Y + other.Y,
            Z + other.Z,
            W + other.W
        );
    }

//All other operations

}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This book adopts a TTD approach, so a data structure that works now might need some refactoring to support new features. For this reason, I finally decided to use the approach suggested by the author, of using factory methods. I will possibly come back on this decision later in the book when concepts become more clear.&lt;/p&gt;

&lt;p&gt;You can see how this was implemented on the branch &lt;a href="https://github.com/simonech/ray-tracer-challenge-netcore/tree/factory-methods"&gt;factory-methods&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which data type to use
&lt;/h3&gt;

&lt;p&gt;The book suggests using a "native" floating point data type since these values will be used a lot. I decided to use a &lt;code&gt;double&lt;/code&gt;, even if probably a &lt;code&gt;float&lt;/code&gt; would be enough, to avoid lots of casting given that all the &lt;code&gt;System.Math&lt;/code&gt; methods work with &lt;code&gt;Double&lt;/code&gt; types. And also I'm lazy and I don't want to add &lt;code&gt;f&lt;/code&gt; every time I want to specify a value as literal (just &lt;code&gt;1.7&lt;/code&gt; vs &lt;code&gt;1.7f&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Performances
&lt;/h3&gt;

&lt;p&gt;I already see some performance issues in this code: creating a new object every time an operation is done will create zillions of objects, and memory will increase.&lt;/p&gt;

&lt;p&gt;Also using fields instead of properties, or using struct instead of classes might bring some performance improvement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;p&gt;As already mentioned above, the final exercise was about the "Hello World" exercise of vector and physics: the trajectory of a bullet shot with an initial velocity and subject to gravity and wind.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using codeclimber.raytracer;
public class Environment
{
    public Environment(Tuple gravity, Tuple wind)
    {
        Gravity = gravity;
        Wind = wind;
    }

    public Tuple Gravity { get; set; }
    public Tuple Wind { get; set; }
}

public class Projectile
{
    public Projectile(Tuple position, Tuple velocity)
    {
        Position = position;
        Velocity = velocity;
    }

    public Tuple Position { get; set; }
    public Tuple Velocity { get; set; }

    public override string ToString()
    {
        return $"{Position} (v={Velocity})";
    }
}

class Program
{
    static void Main(string[] args)
    {
        var p = new Projectile(Tuple.Point(0, 1, 0), Tuple.Vector(1, 1, 0).Normalize());
        var e = new Environment(Tuple.Vector(0, -0.1, 0), Tuple.Vector(-0.01, 0, 0));
        int i = 0;
        while (p.Position.Y &amp;gt;= 0)
        {
            i++;
            sys.Console.WriteLine($"{i} - {p}");
            p = Update(p, e);
        }
    }

    public static Projectile Update(Projectile p, Environment e)
    {
        return new Projectile(
            p.Position.Add(p.Velocity),
            p.Velocity.Add(e.Gravity).Add(e.Wind)
        );
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The code is that simple that it just prints out the list of coordinates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GtsqLLMB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1059/3-text-output.png%3Fwidth%3D700" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GtsqLLMB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1059/3-text-output.png%3Fwidth%3D700" alt="Output of the projectile example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To see I got it right, I imported the result in excel and drawn a chart.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zndnJW3d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1058/3-ballistic-trajectory.png%3Fwidth%3D650" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zndnJW3d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codeclimber.net.nz/media/1058/3-ballistic-trajectory.png%3Fwidth%3D650" alt="Trajectory charted with Excel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On my GitHub repository you can have a look at the &lt;a href="https://github.com/simonech/ray-tracer-challenge-netcore/tree/Chapter1-End/Exercises/Chapter%201"&gt;code of the exercise&lt;/a&gt;, and the output, both &lt;a href="https://github.com/simonech/ray-tracer-challenge-netcore/blob/Chapter1-End/Exercises/Chapter%201/Results/trajectory.txt"&gt;text&lt;/a&gt; and &lt;a href="https://github.com/simonech/ray-tracer-challenge-netcore/blob/Chapter1-End/Exercises/Chapter%201/Results/Projectile-trajectory.xlsx"&gt;Excel&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;The basic operations are now implemented. The next chapter in the book is about implementing the code to write images on disk, in &lt;a href="https://en.wikipedia.org/wiki/Netpbm_format"&gt;PPM format&lt;/a&gt; (I suppose the easiest format to implement).&lt;/p&gt;

&lt;p&gt;What do you think? Do you think there is a more elegant way to deal with &lt;code&gt;Point&lt;/code&gt; and &lt;code&gt;Vector&lt;/code&gt; other than using the two static factory methods? Anything else?&lt;/p&gt;

&lt;p&gt;I've posted the code already yesterday on my Github repo and I've received already two comments (as issues on my Github repo).&lt;/p&gt;

&lt;p&gt;One &lt;a href="https://github.com/simonech/ray-tracer-challenge-netcore/issues/2"&gt;spotted a mistake&lt;/a&gt; I did and the other one posted &lt;a href="https://github.com/simonech/ray-tracer-challenge-netcore/issues/1"&gt;some great suggestions&lt;/a&gt;. He suggested that I could use the new &lt;code&gt;System.MathF&lt;/code&gt; class introduced in .NET Core 2.1, to use floats instead of the double (but I'd still have to type the &lt;code&gt;f&lt;/code&gt; in literals). He also suggested I use operator overload instead of the methods &lt;code&gt;Add&lt;/code&gt;, &lt;code&gt;Subtract&lt;/code&gt;, and so on.&lt;/p&gt;

&lt;p&gt;I'll switch to operators overload and I'll do a bit of performance optimization before starting with calling these simple operation zillion times.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://feeds.feedburner.com/~ff/Codeclimber?a=5myDr0taUQ0:Y_DrFr_snQU:V_sGLiPBpWU"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4z6ELWds--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/Codeclimber%3Fi%3D5myDr0taUQ0:Y_DrFr_snQU:V_sGLiPBpWU" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Codeclimber?a=5myDr0taUQ0:Y_DrFr_snQU:G79ilh31hkQ"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RxcwcNun--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/Codeclimber%3Fd%3DG79ilh31hkQ" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Codeclimber?a=5myDr0taUQ0:Y_DrFr_snQU:dnMXMwOfBR0"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Yytk-Bxx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/Codeclimber%3Fd%3DdnMXMwOfBR0" alt=""&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Codeclimber?a=5myDr0taUQ0:Y_DrFr_snQU:F7zBnMyn0Lo"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z0_zaL1T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Eff/Codeclimber%3Fi%3D5myDr0taUQ0:Y_DrFr_snQU:F7zBnMyn0Lo" alt=""&gt;&lt;/a&gt;&lt;br&gt;
 &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kU8uvWdq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Er/Codeclimber/%257E4/5myDr0taUQ0" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kU8uvWdq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Er/Codeclimber/%257E4/5myDr0taUQ0" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>challenge</category>
      <category>netcore</category>
      <category>discuss</category>
    </item>
    <item>
      <title>The Ray Tracer Challenge - Setting up the project with the dotnet CLI</title>
      <dc:creator>Simone Chiaretta</dc:creator>
      <pubDate>Thu, 30 May 2019 21:49:41 +0000</pubDate>
      <link>https://dev.to/simonech/the-ray-tracer-challenge-setting-up-the-project-with-the-dotnet-cli-4016</link>
      <guid>https://dev.to/simonech/the-ray-tracer-challenge-setting-up-the-project-with-the-dotnet-cli-4016</guid>
      <description>&lt;p&gt;Here it comes, the first post of my journey developing a Ray Tracer using .NET Core on a Mac, using only VS Code. If you didn't, I recommend you read my &lt;a href="http://codeclimber.net.nz/archive/2019/05/22/raytracer-challenge-netcore-intro/"&gt;introductory post&lt;/a&gt; which explains what I'm trying to achieve and why.&lt;/p&gt;

&lt;p&gt;In this first post I'll talk about the libraries and tools I decided to use, and how I setup the project structure using the &lt;code&gt;dotnet&lt;/code&gt; CLI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools used
&lt;/h2&gt;

&lt;p&gt;The only two tools I'm using are VS Code and the &lt;code&gt;dotnet&lt;/code&gt; CLI. Let's see how I configured the two.&lt;/p&gt;

&lt;h3&gt;
  
  
  VS Code
&lt;/h3&gt;

&lt;p&gt;As I mentioned in the &lt;a href="http://codeclimber.net.nz/archive/2019/05/22/raytracer-challenge-netcore-intro/"&gt;introduction to this series of posts&lt;/a&gt;, I'm using VS Code, with the basic &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.csharp"&gt;C#/Omnisharp extension&lt;/a&gt; that comes when you download VS Code. In addition, I'm using two other extensions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the &lt;a href="https://marketplace.visualstudio.com/items?itemName=jchannon.csharpextensions"&gt;C# Extensions&lt;/a&gt;, which adds some nice contextual menu and some additional refactoring;&lt;/li&gt;
&lt;li&gt;the &lt;a href="https://marketplace.visualstudio.com/items?itemName=formulahendry.dotnet-test-explorer"&gt;.NET Core Test Explorer&lt;/a&gt;, which adds a tree-view UI for all the tests in the workspace.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  dotnet CLI
&lt;/h3&gt;

&lt;p&gt;The other tool I use, which comes with .NET Core, is the &lt;code&gt;dotnet&lt;/code&gt; CLI. One thing I learned while going through the documentation is that it supports TAB completion, but, in order to have it, it must be configured. You can follow the steps on the page "&lt;a href="https://docs.microsoft.com/en-us/dotnet/core/tools/enable-tab-autocomplete"&gt;How to enable TAB completion for .NET Core CLI&lt;/a&gt;" in .NET Core doc site.&lt;/p&gt;

&lt;p&gt;But, in short, add the following code to the &lt;code&gt;~/.bashrc&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# bash parameter completion for the dotnet CLI

_dotnet_bash_complete()
{
  local word=${COMP_WORDS[COMP_CWORD]}

  local completions
  completions="$(dotnet complete --position "${COMP_POINT}" "${COMP_LINE}")"

  COMPREPLY=( $(compgen -W "$completions" -- "$word") )
}

complete -f -F _dotnet_bash_complete dotnet
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Normally Linux-based systems run this script every time the terminal is opened. But the default MacOS Terminal app runs another file, the &lt;code&gt;~/.bash_profile&lt;/code&gt; (which is normally executed only at login). Other terminals might behave differently, so it's better to add the script in both places. You can either copy the same code in the other file or just include the following lines in the &lt;code&gt;.bash_profile&lt;/code&gt; file, so that it automatically calls &lt;code&gt;.bashrc&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if [-f ~/.bashrc]; then
   source ~/.bashrc
fi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Libraries used: xUnit
&lt;/h2&gt;

&lt;p&gt;I'm pretty sure some NuGet packages already exist to compute vector and matrix computations, and for saving images. But that would defeat the point of the whole exercise. The only external library I'm referencing is the testing framework.&lt;/p&gt;

&lt;p&gt;The book already provides the full test suite in Gherkin format to be used with Cucumber, so the obvious choice, to save time, would be to use the .NET counterpart of Cucumber: &lt;a href="https://specflow.org/"&gt;SpecFlow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But despite &lt;a href="https://specflow.org/2019/specflow-3-is-here/"&gt;supporting .NET Core&lt;/a&gt;, it seems that SpecFlow relies heavily on its Visual Studio plugin in order to parse the feature files and generate the executable tests. I found some posts explaining how to do it without, but I'd rather start coding instead of spending time working around limitations of one specific testing framework.&lt;/p&gt;

&lt;p&gt;So I'll just start with xUnit, and after the first few chapters are completed, go back, try to make SpecFlow work on .NET Core without Visual Studio, and re-implement the tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the project structure using the dotnet CLI
&lt;/h2&gt;

&lt;p&gt;The project is simple: two projects (one .NET Standard class lib and one test project) and a solution to link them together.&lt;/p&gt;

&lt;p&gt;And here comes the first bit I learned in this process: the &lt;code&gt;dotnet&lt;/code&gt; CLI is awesome! You can create solution files, projects and also adding projects to solutions and adding references from one project to another.&lt;/p&gt;

&lt;p&gt;All without any manual editing of the files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet new sln -o src -n ray-tracer-challenge
cd src
dotnet new classlib -o raytracer -n codeclimber.raytracer
dotnet new xunit -o xUnit -n codeclimber.raytracer.xUnit
dotnet sln add **/*.csproj
cd xUnit/
dotnet add reference ../raytracer/codeclimber.raytracer.csproj 
cd ..
dotnet build
dotnet test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This list of commands creates a solution inside a folder called &lt;code&gt;src&lt;/code&gt; and 2 projects in their own sub-folders. Then it adds them to the solution, adds a reference from the testing project to the class library, and finally, build and run the tests.&lt;/p&gt;

&lt;p&gt;You can see the code at this point in time by going on the Github repo of this project and switching to the two branches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/simonech/ray-tracer-challenge-netcore/tree/Chapter-0.1"&gt;Chapter 0.1&lt;/a&gt; - Just a script that uses the &lt;code&gt;dotnet&lt;/code&gt; CLI to create the project structure and makes sure everything is working fine.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/simonech/ray-tracer-challenge-netcore/tree/Chapter-0.2"&gt;Chapter 0.2&lt;/a&gt; - The basic projects (lib and xUnit test lib) with simple code to make sure testing works fine.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Now that the environment is setup correctly, in the next post I'll start implementing the exercises of the first chapter of the book &lt;a href="https://amzn.to/2Elaxkr"&gt;The Ray Tracer Challenge - A Test-Driven Guide to Your First 3D Renderer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can see the full list of posts in the &lt;a href="https://dev.to/archive/2019/05/22/raytracer-challenge-netcore-intro/"&gt;introduction to the series&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>netcore</category>
      <category>vscode</category>
      <category>challenge</category>
    </item>
    <item>
      <title>The Ray Tracer Challenge... in .NET Core</title>
      <dc:creator>Simone Chiaretta</dc:creator>
      <pubDate>Sat, 25 May 2019 09:10:27 +0000</pubDate>
      <link>https://dev.to/simonech/the-ray-tracer-challenge-in-net-core-25ii</link>
      <guid>https://dev.to/simonech/the-ray-tracer-challenge-in-net-core-25ii</guid>
      <description>&lt;p&gt;I just bought the book &lt;a href="https://amzn.to/2Elaxkr"&gt;The Ray Tracer Challenge - A Test-Driven Guide to Your First 3D Renderer&lt;/a&gt; and in the upcoming months, I'll be developing my own ray tracer, in .NET Core.&lt;/p&gt;

&lt;p&gt;I will also document my learning experience on the blog, for me, to keep track of my progress, and maybe discuss some implementation decisions with you, my readers, but also to share what I learn in the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why am I doing it
&lt;/h2&gt;

&lt;p&gt;Nowadays I spend most of my time building CMS-based projects, using APIs provided by vendors, and aggregating results coming from Cloud-based services. And I stopped enjoying development.&lt;/p&gt;

&lt;p&gt;I needed a change, I needed to find back my love for developing, and I needed to challenge myself to learn something new. The book teaches the theory of a ray tracing, and, using a TDD approach, makes you implement, from scratch, all the pieces needed: starting from basic vector and matrix computations, to image processing and storing, and finally going into the real-deal of rendering 3D scenes from scratch.&lt;/p&gt;

&lt;p&gt;Rebuilding all the basic primitives might sound silly at first, in the current development world were developers reuse code and packages even for simple tasks as adding padding to strings. But the goal of the book is to help you rediscover the fun of developing from scratch, doing things yourself, without relying on stuff done by others.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technologies used
&lt;/h2&gt;

&lt;p&gt;The project will be implemented with .NET Core 2.2, with no external libraries, to adhere the most to the concept of the book, which is to build everything from scratch, even features that might exist already as part of .NET Standard or in other packages, like &lt;code&gt;Color&lt;/code&gt;, &lt;code&gt;Point&lt;/code&gt;, image rendering and serializing.&lt;/p&gt;

&lt;p&gt;My objective is also to build everything using a Mac, the &lt;code&gt;dotnet&lt;/code&gt; CLI and VS Code, to prove (mostly to myself) that this is a feasible approach, and that you can do everything you need without the full-blown Visual Studio.&lt;/p&gt;

&lt;p&gt;I'll also try to use the latest features of the C# language, whenever makes sense.&lt;/p&gt;

&lt;p&gt;The book recommends the usage of Cucumber for the testing and even provides the full set of features in Gherkin. SpecFlow is the only Gherkin implementation for .NET, but it seems like the support for .NET Core is not very advanced, and still relies on their Visual Studio plugin for generating the test files. So I'll start with plain old unit testing with xUnit, and will move to SpecFlow later.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'll be learning
&lt;/h2&gt;

&lt;p&gt;Such a project will involve a lot of learning: I will learn new things, improve the knowledge I have and since there is a lot of math involved, I will re-learn things I've learned at the university.&lt;/p&gt;

&lt;p&gt;Specifically, things I hope to learn better are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Obviously, how raytracing works;&lt;/li&gt;
&lt;li&gt;Math, Algebra, Matrix, Vectors, and similar stuff;&lt;/li&gt;
&lt;li&gt;usage of the &lt;code&gt;dotnet&lt;/code&gt; CLI;&lt;/li&gt;
&lt;li&gt;a more advanced use of VS Code (now I mostly use it "just" as text editor);&lt;/li&gt;
&lt;li&gt;New features of C# (with new I mean from v6 onwards);&lt;/li&gt;
&lt;li&gt;xUnit;&lt;/li&gt;
&lt;li&gt;BDD with Gherkin and SpecFlow;&lt;/li&gt;
&lt;li&gt;Performance testing once everything is done.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Show me the code
&lt;/h2&gt;

&lt;p&gt;All code is hosted on Github: &lt;a href="https://github.com/simonech/ray-tracer-challenge-netcore"&gt;https://github.com/simonech/ray-tracer-challenge-netcore&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The repository will also include the posts of the series. To familiarize yourself with the structure of the repository, please have a look at the &lt;a href="https://github.com/simonech/ray-tracer-challenge-netcore/blob/master/README.md"&gt;README&lt;/a&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Content
&lt;/h2&gt;

&lt;p&gt;I'll try to write a post at least once per chapter of the book, and document how things are going, the challenges I faced and what I learned. I will update this table of content with every post published&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Ray Tracer Challenge... in .NET Core - Introduction (this post)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope you will subscribe to my &lt;a href="http://codeclimber.net.nz"&gt;blog&lt;/a&gt; (if you don't have already) and will learn together with my how implementing ray tracing in .NET Core.&lt;/p&gt;

</description>
      <category>netcore</category>
      <category>dotnet</category>
      <category>math</category>
      <category>challenge</category>
    </item>
  </channel>
</rss>
