<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Danilo Maia Florenzano</title>
    <description>The latest articles on Forem by Danilo Maia Florenzano (@daniloflorenzano).</description>
    <link>https://forem.com/daniloflorenzano</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%2F913731%2Fc0f5f51a-b984-4fcb-9fca-2808ad43411c.JPG</url>
      <title>Forem: Danilo Maia Florenzano</title>
      <link>https://forem.com/daniloflorenzano</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/daniloflorenzano"/>
    <language>en</language>
    <item>
      <title>Using ActionBlock as a Multithread Recursive Dynamic Queue in .NET</title>
      <dc:creator>Danilo Maia Florenzano</dc:creator>
      <pubDate>Sun, 02 Nov 2025 16:29:54 +0000</pubDate>
      <link>https://forem.com/daniloflorenzano/using-actionblock-as-a-multithread-recursive-dynamic-queue-in-net-2c3m</link>
      <guid>https://forem.com/daniloflorenzano/using-actionblock-as-a-multithread-recursive-dynamic-queue-in-net-2c3m</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“TPL Dataflow is an interesting mix of asynchronous and parallel technologies. It’s useful when you have a sequence of processes that need to be applied to your data.”&lt;/em&gt;&lt;br&gt;&lt;br&gt;
— &lt;em&gt;Stephen Cleary, Concurrency in C# Cookbook&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;I recently needed to traverse a recursive category tree — starting with ~20 root nodes, each with an unknown number of subcategories (and sub-subcategories, and so on).&lt;/p&gt;

&lt;p&gt;This kind of &lt;strong&gt;dynamically expanding workload&lt;/strong&gt; doesn’t play well with static parallelization tools like &lt;code&gt;Parallel.ForEach&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Static Work Distribution
&lt;/h2&gt;

&lt;p&gt;If we run &lt;code&gt;Parallel.ForEach&lt;/code&gt; on the 20 root categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Thread 1&lt;/strong&gt; might get a small branch and finish in 1 second.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thread 2&lt;/strong&gt; might get a massive branch and take 10 minutes.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even with &lt;code&gt;MaxDegreeOfParallelism = 50&lt;/code&gt;, most threads finish early and go idle — while a few get stuck processing deep, heavy trees.  &lt;strong&gt;Load imbalance and wasted resources.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: &lt;code&gt;ActionBlock&amp;lt;T&amp;gt;&lt;/code&gt; as a Dynamic Work Queue
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.dataflow.actionblock-1" rel="noopener noreferrer"&gt;&lt;code&gt;ActionBlock&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/a&gt; from TPL Dataflow provides a &lt;strong&gt;centralized, thread-safe queue&lt;/strong&gt; with &lt;strong&gt;dynamic task generation&lt;/strong&gt; and &lt;strong&gt;controlled concurrency&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here’s how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create one &lt;code&gt;ActionBlock&amp;lt;CategoryNode&amp;gt;&lt;/code&gt; with a fixed concurrency limit.
&lt;/li&gt;
&lt;li&gt;“Prime” it with the initial root categories.
&lt;/li&gt;
&lt;li&gt;Each worker processes its node, finds subcategories, and &lt;strong&gt;posts them back&lt;/strong&gt; into the same &lt;code&gt;ActionBlock&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;The block keeps running until all items (current + pending) are done.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This pattern is effectively a &lt;strong&gt;recursive, self-balancing queue&lt;/strong&gt; — all threads stay busy until the entire tree is processed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example Implementation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MultithreadTreeParser&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;_activeItems&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;ActionBlock&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CategoryNode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_actionBlock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;!;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;StartAsync&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;rootNode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;GetDepartmentsRootNodeAsync&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to get root node"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ExecutionDataflowBlockOptions&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;MaxDegreeOfParallelism&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="n"&gt;_actionBlock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ActionBlock&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CategoryNode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;ProcessCategoryAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;subs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SubCategories&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;Interlocked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt; &lt;span class="n"&gt;_activeItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sub&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;subs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_actionBlock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SendAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;finally&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Interlocked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Decrement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt; &lt;span class="n"&gt;_activeItems&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;_actionBlock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Complete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;rootSubs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rootNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SubCategories&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Interlocked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt; &lt;span class="n"&gt;_activeItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rootSubs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sub&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rootSubs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_actionBlock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SendAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_actionBlock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Completion&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Dynamic load balancing: Workers pull from a shared queue. As soon as they finish, they grab the next available node.&lt;/li&gt;
&lt;li&gt;Recursive workload expansion: Each task can add new tasks safely to the same queue.&lt;/li&gt;
&lt;li&gt;Controlled parallelism: MaxDegreeOfParallelism keeps resource usage in check.&lt;/li&gt;
&lt;li&gt;Clean completion tracking: _activeItems counts in-flight work — when it hits zero, the pipeline gracefully completes.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Dumb HTTP Server in C# .NET</title>
      <dc:creator>Danilo Maia Florenzano</dc:creator>
      <pubDate>Sat, 21 Jun 2025 22:25:38 +0000</pubDate>
      <link>https://forem.com/daniloflorenzano/dumb-http-server-in-c-net-2acd</link>
      <guid>https://forem.com/daniloflorenzano/dumb-http-server-in-c-net-2acd</guid>
      <description>&lt;p&gt;I saw this video where the server was coded in Rust. If you're trying to learn how it works, maybe it will be useful.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/7GBlCinu9yg?si=V3kefRCceXqJald8" rel="noopener noreferrer"&gt;Coding a Web Server in 25 Lines - Computerphile&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to just copy and paste the code and see it working, make sure you have an &lt;code&gt;index.html&lt;/code&gt; file in the project folder. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7wezvvc3fvj7jf9ba9zo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7wezvvc3fvj7jf9ba9zo.png" alt="index.html in the project folder" width="227" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code sample
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;TcpListener class description:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The System.Net.Sockets.TcpListener class provide TCP services at a higher level of abstraction than the System.Net.Sockets.Socket class. System.Net.Sockets.TcpListener is used to create a host process that listens for connections from TCP clients.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Net&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Net.Sockets&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tcpListener&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TcpListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IPAddress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Loopback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;9999&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;tcpListener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tcpListener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AcceptTcpClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetStream&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;StreamReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadLine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrWhiteSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;okResponse&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"HTTP/1.1 200 OK\r\n\r\n"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UTF8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;okResponse&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;projectPath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DirectoryInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Directory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetCurrentDirectory&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parent&lt;/span&gt;&lt;span class="p"&gt;!.&lt;/span&gt;&lt;span class="n"&gt;Parent&lt;/span&gt;&lt;span class="p"&gt;!.&lt;/span&gt;&lt;span class="n"&gt;Parent&lt;/span&gt;&lt;span class="p"&gt;!.&lt;/span&gt;&lt;span class="n"&gt;FullName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;htmlBuffer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UTF8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadAllText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;projectPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"index.html"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;htmlBuffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs8mcbklbx9mrhkw9p454.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs8mcbklbx9mrhkw9p454.png" alt="browser" width="800" height="687"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the server console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;GET / HTTP/1.1
Host: 127.0.0.1:9999
User-Agent: Mozilla/5.0 &lt;span class="o"&gt;(&lt;/span&gt;Windows NT 10.0&lt;span class="p"&gt;;&lt;/span&gt; Win64&lt;span class="p"&gt;;&lt;/span&gt; x64&lt;span class="p"&gt;;&lt;/span&gt; rv:139.0&lt;span class="o"&gt;)&lt;/span&gt; Gecko/20100101 Firefox/139.0
Accept: text/html,application/xhtml+xml,application/xml&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;q&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.9,&lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;q&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.8
Accept-Language: en-GB,en&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;q&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.5
Accept-Encoding: &lt;span class="nb"&gt;gzip&lt;/span&gt;, deflate, br, zstd
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Priority: &lt;span class="nv"&gt;u&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0, i
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>programming</category>
      <category>web</category>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>POO: Herança versus Composição</title>
      <dc:creator>Danilo Maia Florenzano</dc:creator>
      <pubDate>Sun, 08 Jun 2025 15:56:25 +0000</pubDate>
      <link>https://forem.com/daniloflorenzano/poo-heranca-versus-composicao-45gh</link>
      <guid>https://forem.com/daniloflorenzano/poo-heranca-versus-composicao-45gh</guid>
      <description>&lt;h2&gt;
  
  
  Como decidir
&lt;/h2&gt;

&lt;p&gt;Usar &lt;strong&gt;herança&lt;/strong&gt; quando precisar de:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reaproveitamento de código&lt;/li&gt;
&lt;li&gt;polimorfismo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Usar &lt;strong&gt;composição&lt;/strong&gt; quando precisar de:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reaproveitamento de código&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Usar uma &lt;strong&gt;interface&lt;/strong&gt; quando precisar de:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;polimorfismo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ou seja, a herança é bem vinda quando, e somente quando, as duas necessidades forem verdade. Do contrario, prefira sempre composição.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;É importante ressaltar que a herança pode levar a um acoplamento mais forte entre as classes, o que pode dificultar a manutenção e evolução do código.&lt;br&gt;
A composição, por outro lado, promove um acoplamento mais fraco, permitindo maior flexibilidade e reutilização de componentes. Por isso, muitos autores recomendam a composição como uma abordagem preferencial na Programação Orientada a Objetos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exemplo
&lt;/h2&gt;

&lt;p&gt;No exemplo da imagem, a herança não é justificada porque nenhuma das classes herdeiras sobrescreve o método da classe principal (polimorfismo), apenas é reaproveitado o &lt;code&gt;Metodo1()&lt;/code&gt; (reaproveitamento de código).&lt;br&gt;
Nesse caso, como apenas um dos requisitos é preenchido, é melhor usar composição.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsl4eswhcnmhr1t0xvn3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsl4eswhcnmhr1t0xvn3g.png" alt="Exemplo de composição" width="387" height="658"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Há também a abordagem de não usar herança mesmo em casos que preencham os dois requisitos. Pois ambos podem ser satisfeitos através da combinação de interfaces e composição.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fet4eb2z9egi61av2fpj3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fet4eb2z9egi61av2fpj3.png" alt="Exemplo de composição com interface " width="400" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Referência
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=C3B5IIlt4-0" rel="noopener noreferrer"&gt;Only Use Inheritance If You Want Both of These - by Christopher Okhravi&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>oop</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>Podman com Quadlets em produção</title>
      <dc:creator>Danilo Maia Florenzano</dc:creator>
      <pubDate>Fri, 06 Jun 2025 22:52:41 +0000</pubDate>
      <link>https://forem.com/daniloflorenzano/podman-com-quadlets-em-producao-1f1h</link>
      <guid>https://forem.com/daniloflorenzano/podman-com-quadlets-em-producao-1f1h</guid>
      <description>&lt;p&gt;Aluguei uma VPS e queria disponibilizar uma API que desenvolvi.&lt;/p&gt;

&lt;p&gt;Optei por utilizar contêineres. A escolha do &lt;strong&gt;Podman&lt;/strong&gt; foi feita considerando o objetivo de melhorar minha afinidade com a ferramenta e, também, usufruir da integração nativa com o &lt;strong&gt;systemd&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Para atingir um resultado satisfatório, considerando a inicialização dos contêineres no boot e a possibilidade de acompanhar logs pelo &lt;code&gt;journalctl&lt;/code&gt;, executei os seguintes passos:&lt;/p&gt;




&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Criei um pod com os contêineres necessários.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Gerei um arquivo YAML para Kubernetes a partir do pod:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;podman generate kube xpto-pod &lt;span class="nt"&gt;-f&lt;/span&gt; /tmp/my_pod_kube.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Criei um arquivo &lt;code&gt;.kube&lt;/code&gt;, referenciando o &lt;code&gt;.yaml&lt;/code&gt; gerado:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;xpto-pod.kube&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=Serviço XPTO
After=network-online.target
Wants=network-online.target

[Install]
WantedBy=multi-user.target

[Service]
Restart=on-failure
RestartSec=5s
TimeoutStartSec=900

[Kube]
Yaml=/tmp/my_pod_kube.yaml
PublishPort=8080:80
LogDriver=journald
SetWorkingDirectory=yaml
KubeDownForce=true
&lt;/code&gt;&lt;/pre&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Obs&lt;/strong&gt;: A seção &lt;code&gt;[Install]&lt;/code&gt; é essencial para que o systemd inicie o pod automaticamente no boot.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Movi o arquivo para a pasta correta:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo mv &lt;/span&gt;xpto-pod.kube /etc/containers/systemd/
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Recarreguei os serviços do systemd:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl daemon-reexec
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl daemon-reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Finalizado! Para verificar se o serviço está em execução:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl status xpto-pod.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Continuo explorando formas de usar o &lt;strong&gt;Podman&lt;/strong&gt; e suas ferramentas e integrações.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fontes que utilizei para alcançar esse resultado:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/live/LsZB_mI7TcQ?si=ZKEaWhoXwgrhYves" rel="noopener noreferrer"&gt;Quadlets, Pods, and working with the latest Podman, Podman 5&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://oracle-base.com/articles/linux/podman-generate-and-play-kubernetes-yaml-files" rel="noopener noreferrer"&gt;Podman: Generate and Play Kubernetes YAML Files&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html" rel="noopener noreferrer"&gt;Documentação oficial: podman-systemd.unit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>linux</category>
      <category>devops</category>
      <category>programming</category>
      <category>containers</category>
    </item>
    <item>
      <title>O André Darcie trouxe a true bem sintetizada. Blazor não vai morrer, mas é necessário conhecer suas limitações e seu propósito para saber identificar seus casos de uso.</title>
      <dc:creator>Danilo Maia Florenzano</dc:creator>
      <pubDate>Tue, 10 Dec 2024 12:46:04 +0000</pubDate>
      <link>https://forem.com/daniloflorenzano/o-andre-darcie-trouxe-a-true-bem-sintetizada-blazor-nao-vai-morrer-mas-e-necessario-conhecer-suas-2265</link>
      <guid>https://forem.com/daniloflorenzano/o-andre-darcie-trouxe-a-true-bem-sintetizada-blazor-nao-vai-morrer-mas-e-necessario-conhecer-suas-2265</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/andredarcie" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F386955%2Fe908afc9-e12e-40ec-92ef-cd158638af28.png" alt="andredarcie"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/andredarcie/o-futuro-do-blazor-15d2" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;O Futuro do Blazor&lt;/h2&gt;
      &lt;h3&gt;André N. Darcie ・ Dec 9 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#dotnet&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#blazor&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#braziliandevs&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
    </item>
  </channel>
</rss>
