<?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: Khashayar Nourian</title>
    <description>The latest articles on DEV Community by Khashayar Nourian (@knourian).</description>
    <link>https://dev.to/knourian</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3176094%2F30886680-a94a-45d8-a8ba-b17e07549877.jpeg</url>
      <title>DEV Community: Khashayar Nourian</title>
      <link>https://dev.to/knourian</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/knourian"/>
    <language>en</language>
    <item>
      <title>Task, async, and await: the lifetime of asynchronous work</title>
      <dc:creator>Khashayar Nourian</dc:creator>
      <pubDate>Sat, 03 Oct 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/knourian/task-async-and-await-the-lifetime-of-asynchronous-work-9p</link>
      <guid>https://dev.to/knourian/task-async-and-await-the-lifetime-of-asynchronous-work-9p</guid>
      <description>&lt;p&gt;A method that fetches an HTTP response and parses it involves two related tasks: the HTTP task carries the response text, while the method's task represents the full work through parsing. Keeping those responsibilities separate makes it easier to see which result, failure, or cancellation reaches the caller.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;await&lt;/code&gt; lets a method yield while an operation is incomplete and continue when it finishes; it does not block a thread just to wait, and it does not guarantee a pause if the task is already complete. The article follows that flow through &lt;code&gt;HttpClient&lt;/code&gt;, error handling, cancellation, and continuation context—including why &lt;code&gt;ConfigureAwait(false)&lt;/code&gt; is a scoped library-code choice, not a rule for every &lt;code&gt;await&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The practical point: keep the task with the work so callers can observe its result and handle its outcome. For independent requests, start both before awaiting them; &lt;code&gt;Task.WhenAll&lt;/code&gt; collects their results but does not start them.&lt;/p&gt;

</description>
      <category>engineering</category>
      <category>async</category>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>CQRS with a separate read store: useful projections, new guarantees</title>
      <dc:creator>Khashayar Nourian</dc:creator>
      <pubDate>Mon, 07 Sep 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/knourian/cqrs-with-a-separate-read-store-useful-projections-new-guarantees-5b6k</link>
      <guid>https://dev.to/knourian/cqrs-with-a-separate-read-store-useful-projections-new-guarantees-5b6k</guid>
      <description>&lt;p&gt;A separate read store is not the next mandatory CQRS step. It is useful when a screen, report, or read workload needs a shape that the transactional write model should not own.&lt;/p&gt;

&lt;p&gt;For an order-tracking screen, a projection can keep one denormalized row with an order number, customer name, status, last-updated time, and total. That can remove repeated joins and let read traffic scale separately from command handling.&lt;/p&gt;

&lt;p&gt;The trade-off is visible behavior. A command can commit before the projection updates, so the next read can be stale. Treat the write side as authoritative, make projections rebuildable, and state what the user should expect after a successful command. If a shared database and direct projection already work, keep them.&lt;/p&gt;

</description>
      <category>engineering</category>
      <category>architecture</category>
      <category>cqrs</category>
    </item>
    <item>
      <title>Minimal CQRS: separate code paths, keep one application and one database</title>
      <dc:creator>Khashayar Nourian</dc:creator>
      <pubDate>Thu, 03 Sep 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/knourian/minimal-cqrs-separate-code-paths-keep-one-application-and-one-database-kf1</link>
      <guid>https://dev.to/knourian/minimal-cqrs-separate-code-paths-keep-one-application-and-one-database-kf1</guid>
      <description>&lt;p&gt;CQRS does not have to begin with a second database, a queue, or a separate service.&lt;/p&gt;

&lt;p&gt;A useful first step is much smaller: keep one application and one database, but give commands and queries separate code paths. A command such as &lt;code&gt;PlaceOrder&lt;/code&gt; loads the state it needs, checks business rules, and commits a change. A query such as &lt;code&gt;GetOrderSummary&lt;/code&gt; can project exactly the fields a screen needs without rebuilding a domain aggregate.&lt;/p&gt;

&lt;p&gt;The database is shared. The responsibilities are not.&lt;/p&gt;

&lt;p&gt;This keeps transactions, immediate reads after a successful command, and a simple deployment model. It does not create independent read scaling or reporting projections for free. Those are later decisions, not a starting requirement.&lt;/p&gt;

</description>
      <category>engineering</category>
      <category>architecture</category>
      <category>cqrs</category>
    </item>
    <item>
      <title>CQS and commands: make the application understand intent</title>
      <dc:creator>Khashayar Nourian</dc:creator>
      <pubDate>Wed, 26 Aug 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/knourian/cqs-and-commands-make-the-application-understand-intent-4hp3</link>
      <guid>https://dev.to/knourian/cqs-and-commands-make-the-application-understand-intent-4hp3</guid>
      <description>&lt;p&gt;&lt;code&gt;SetStatus(itemId, Deactivated)&lt;/code&gt; tells an application what a field should contain. &lt;code&gt;DeactivateInventoryItem(itemId, reason)&lt;/code&gt; tells it what the user wants to do.&lt;/p&gt;

&lt;p&gt;That difference matters when the action has rules. A deactivation may require a reason, permission, a valid state transition, and a transaction that saves the result. With a behavior-focused command, those concerns have one natural home instead of being inferred from changed fields or scattered between the UI and a generic update handler.&lt;/p&gt;

&lt;p&gt;The UI can still help by explaining obvious failures early. It cannot be the final authority because another client, a retry, or a concurrent request can reach the same operation.&lt;/p&gt;

&lt;p&gt;A command is also not an event. A command asks for work and may be rejected. An event describes something that already happened after the command succeeded.&lt;/p&gt;

</description>
      <category>engineering</category>
      <category>architecture</category>
      <category>cqrs</category>
      <category>cqs</category>
    </item>
    <item>
      <title>When CRUD stops describing the work</title>
      <dc:creator>Khashayar Nourian</dc:creator>
      <pubDate>Mon, 24 Aug 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/knourian/when-crud-stops-describing-the-work-479</link>
      <guid>https://dev.to/knourian/when-crud-stops-describing-the-work-479</guid>
      <description>&lt;p&gt;CRUD is not the enemy. It is often the smallest correct design for a profile, a team setting, or a simple lookup table.&lt;/p&gt;

&lt;p&gt;The trouble starts when a changed object hides a business action. An API that receives an updated inventory DTO can see that &lt;code&gt;Status&lt;/code&gt; became &lt;code&gt;Deactivated&lt;/code&gt;, but it still has to infer why that happened, whether a reason is required, who is allowed to do it, and what should happen next.&lt;/p&gt;

&lt;p&gt;That is where Command-Query Separation helps. A query returns information. A command asks the system to change something. &lt;code&gt;DeactivateInventoryItem(id, reason)&lt;/code&gt; says more than a generic update ever can.&lt;/p&gt;

&lt;p&gt;This does not require two databases, a message broker, or microservices. It starts with making the request visible where the rules belong.&lt;/p&gt;

</description>
      <category>engineering</category>
      <category>architecture</category>
      <category>cqrs</category>
      <category>cqs</category>
    </item>
    <item>
      <title>Async, concurrency, and parallelism are different</title>
      <dc:creator>Khashayar Nourian</dc:creator>
      <pubDate>Mon, 17 Aug 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/knourian/async-concurrency-and-parallelism-are-different-51h6</link>
      <guid>https://dev.to/knourian/async-concurrency-and-parallelism-are-different-51h6</guid>
      <description>&lt;p&gt;Async, concurrency, and parallelism answer different questions. Async is about avoiding a block while waiting for I/O. Concurrency is about letting independent operations make progress over the same period. Parallelism is about running CPU-bound calculations at the same time on different cores.&lt;/p&gt;

&lt;p&gt;Two downloads can overlap without using two CPU cores. Two image-processing jobs can use multiple cores without any network wait. The distinction matters because the right tool depends on where the time goes.&lt;/p&gt;

&lt;p&gt;Start with the bottleneck: use async for external waits, concurrency when independent waits can overlap, and parallelism when measurement shows CPU work is the problem. Keep small local work simple.&lt;/p&gt;

</description>
      <category>engineering</category>
      <category>software</category>
      <category>async</category>
    </item>
    <item>
      <title>Why async programming exists</title>
      <dc:creator>Khashayar Nourian</dc:creator>
      <pubDate>Sat, 15 Aug 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/knourian/why-async-programming-exists-2c6b</link>
      <guid>https://dev.to/knourian/why-async-programming-exists-2c6b</guid>
      <description>&lt;p&gt;A slow HTTP request is not the same thing as a slow calculation. When an application waits for a database, file system, or remote service, most of that time is spent waiting on work outside the process.&lt;/p&gt;

&lt;p&gt;Async lets the application yield during that wait and return to work that is ready. A UI can stay responsive, and a server can use its available capacity for other requests. The external operation still takes as long as it takes; async does not make the database or API faster.&lt;/p&gt;

&lt;p&gt;I use async for meaningful I/O waits, not for a short calculation that already has its data in memory.&lt;/p&gt;

</description>
      <category>engineering</category>
      <category>software</category>
      <category>async</category>
    </item>
    <item>
      <title>Three Ways to Clean Up Local Git Branches</title>
      <dc:creator>Khashayar Nourian</dc:creator>
      <pubDate>Thu, 13 Aug 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/knourian/three-ways-to-clean-up-local-git-branches-4c64</link>
      <guid>https://dev.to/knourian/three-ways-to-clean-up-local-git-branches-4c64</guid>
      <description>&lt;p&gt;Local branches accumulate for different reasons, so one cleanup command is not safe for every situation. A branch whose upstream is gone is different from one already merged into &lt;code&gt;main&lt;/code&gt;, and both differ from a local branch you want to discard regardless of its merge status.&lt;/p&gt;

&lt;p&gt;This post compares all three cases with Git Bash and PowerShell commands. The key safety distinction is &lt;code&gt;-d&lt;/code&gt; versus &lt;code&gt;-D&lt;/code&gt;: &lt;code&gt;-d&lt;/code&gt; protects unmerged work, while &lt;code&gt;-D&lt;/code&gt; bypasses that check. In particular, the gone-upstream command force-deletes matches without pausing for a preview, so inspect the list first if you need to protect local-only commits.&lt;/p&gt;

&lt;p&gt;Choose the cleanup that matches the branch state, change the integration branch names to fit your repository, and do not force-delete work you may need.&lt;/p&gt;

</description>
      <category>engineering</category>
      <category>git</category>
      <category>developerproductivit</category>
      <category>workflow</category>
    </item>
  </channel>
</rss>
