<?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: Aleksandr Gusev</title>
    <description>The latest articles on DEV Community by Aleksandr Gusev (@aleksandr_gusev_it).</description>
    <link>https://dev.to/aleksandr_gusev_it</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%2F3722273%2F5243199d-577f-4828-82c5-b39bc42d9257.jpg</url>
      <title>DEV Community: Aleksandr Gusev</title>
      <link>https://dev.to/aleksandr_gusev_it</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aleksandr_gusev_it"/>
    <language>en</language>
    <item>
      <title>What We Learned Rewriting an Interactive Map Editor: Fabric.js, CORS, and 20,000 Lines of Legacy TypeScript</title>
      <dc:creator>Aleksandr Gusev</dc:creator>
      <pubDate>Tue, 07 Jul 2026 18:43:01 +0000</pubDate>
      <link>https://dev.to/aleksandr_gusev_it/what-we-learned-rewriting-an-interactive-map-editor-fabricjs-cors-and-20000-lines-of-legacy-2njb</link>
      <guid>https://dev.to/aleksandr_gusev_it/what-we-learned-rewriting-an-interactive-map-editor-fabricjs-cors-and-20000-lines-of-legacy-2njb</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;A story about how migrating an interactive office map editor turned into an engineering investigation involving Fabric.js, &lt;code&gt;tainted canvas&lt;/code&gt;, and an architecture that's finally easy to extend.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In most software projects, one sentence usually makes every developer nervous:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Let's rewrite this module from scratch."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It often means months of development, regression risks, and endless architecture discussions.&lt;/p&gt;

&lt;p&gt;Our project was no different.&lt;/p&gt;

&lt;p&gt;We develop, a workspace management platform that allows companies to manage office spaces and book desks. One of its core features is an interactive office map editor, where administrators upload floor plans, place desks and meeting rooms, and publish maps for employees.&lt;/p&gt;

&lt;p&gt;Over the years, this editor slowly evolved into a real monolith.&lt;/p&gt;

&lt;p&gt;And the problem wasn't simply the number of lines of code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where It All Started
&lt;/h2&gt;

&lt;p&gt;The editor dated back to the AngularJS era.&lt;/p&gt;

&lt;p&gt;The main component had gradually grown into a single file responsible for almost everything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;loading maps&lt;/li&gt;
&lt;li&gt;working with Fabric.js&lt;/li&gt;
&lt;li&gt;CRUD operations&lt;/li&gt;
&lt;li&gt;keyboard shortcuts&lt;/li&gt;
&lt;li&gt;dialogs&lt;/li&gt;
&lt;li&gt;saving&lt;/li&gt;
&lt;li&gt;event handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The main editor component alone contained nearly &lt;strong&gt;2,270 lines of code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Behind it lived another codebase — the map engine itself.&lt;/p&gt;

&lt;p&gt;Almost &lt;strong&gt;20,000 lines of TypeScript&lt;/strong&gt; spread across more than 230 files.&lt;/p&gt;

&lt;p&gt;One of the biggest architectural issues was an infinite rendering loop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fabric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;util&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;requestAnimFrame&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even when the user wasn't interacting with the editor, rendering continued forever.&lt;/p&gt;

&lt;p&gt;It worked.&lt;/p&gt;

&lt;p&gt;But every new feature became more expensive to build.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why We Decided to Rewrite It
&lt;/h2&gt;

&lt;p&gt;The motivation wasn't AngularJS itself.&lt;/p&gt;

&lt;p&gt;The real reason was business requirements.&lt;/p&gt;

&lt;p&gt;The product needed completely new capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;map drafts&lt;/li&gt;
&lt;li&gt;safe publishing&lt;/li&gt;
&lt;li&gt;high-quality printing&lt;/li&gt;
&lt;li&gt;multiple workspace modes&lt;/li&gt;
&lt;li&gt;easier support for new object types&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every new feature pushed harder against the existing architecture.&lt;/p&gt;

&lt;p&gt;Eventually it became obvious:&lt;/p&gt;

&lt;p&gt;We weren't fighting individual bugs anymore.&lt;/p&gt;

&lt;p&gt;We were fighting the architecture itself.&lt;/p&gt;

&lt;p&gt;Instead of performing a risky Big Bang migration, we decided to build an entirely new administration module alongside the existing viewer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building a New Architecture
&lt;/h2&gt;

&lt;p&gt;We kept Fabric.js.&lt;/p&gt;

&lt;p&gt;Everything around it changed.&lt;/p&gt;

&lt;p&gt;Instead of one massive controller, we introduced clear responsibilities.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Map Editor
        │
        ▼
   Map Engine
        │
 ┌──────┼─────────┐
 │      │         │
 ▼      ▼         ▼
Viewport Registry Changes
                Tracker
        │
        ▼
     Fabric.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each subsystem became responsible for exactly one concern.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Viewport&lt;/strong&gt; controls camera movement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Object Registry&lt;/strong&gt; manages map entities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Changes Tracker&lt;/strong&gt; knows only about modifications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Map Engine&lt;/strong&gt; exposes a single API for the editor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most pleasant surprise came later.&lt;/p&gt;

&lt;p&gt;Adding new functionality no longer required touching half of the application.&lt;/p&gt;




&lt;h2&gt;
  
  
  Moving the Camera Instead of Moving Objects
&lt;/h2&gt;

&lt;p&gt;One architectural decision simplified much more than we expected.&lt;/p&gt;

&lt;p&gt;Instead of physically moving every desk on the canvas, we move the camera using Fabric's &lt;code&gt;viewportTransform&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Objects always stay in their original coordinates.&lt;/p&gt;

&lt;p&gt;This dramatically simplified:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;zooming&lt;/li&gt;
&lt;li&gt;panning&lt;/li&gt;
&lt;li&gt;exporting&lt;/li&gt;
&lt;li&gt;printing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes one architectural decision solves several future problems at once.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Hardest Problem Wasn't Angular
&lt;/h1&gt;

&lt;p&gt;When the migration started, we believed rewriting nearly 20,000 lines of TypeScript would be the hardest challenge.&lt;/p&gt;

&lt;p&gt;It wasn't.&lt;/p&gt;

&lt;p&gt;The most difficult part looked completely harmless.&lt;/p&gt;

&lt;p&gt;We simply needed to print the office map.&lt;/p&gt;




&lt;h2&gt;
  
  
  Attempt #1
&lt;/h2&gt;

&lt;p&gt;The obvious solution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately, browser printing renders the DOM at roughly screen resolution.&lt;/p&gt;

&lt;p&gt;For large office maps, the result was blurry.&lt;/p&gt;

&lt;p&gt;Even worse, parts of the editor UI appeared in the printed document.&lt;/p&gt;

&lt;p&gt;Not acceptable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Attempt #2
&lt;/h2&gt;

&lt;p&gt;The next idea looked much better.&lt;/p&gt;

&lt;p&gt;Export the Fabric canvas as a high-resolution image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDataURL&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, the browser answered with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SecurityError:
The canvas has been tainted by cross-origin data.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;The floor plan image was stored on Amazon S3.&lt;/p&gt;

&lt;p&gt;Although it rendered perfectly inside the browser, exporting the canvas became impossible because the background image wasn't available with the required CORS configuration.&lt;/p&gt;

&lt;p&gt;The browser was doing exactly what it was supposed to do.&lt;/p&gt;




&lt;h2&gt;
  
  
  Attempt #3
&lt;/h2&gt;

&lt;p&gt;This one finally worked.&lt;/p&gt;

&lt;p&gt;Instead of exporting a single PNG, we split printing into two independent layers.&lt;/p&gt;

&lt;p&gt;The background image remained untouched.&lt;/p&gt;

&lt;p&gt;The Fabric objects were exported separately without the background.&lt;/p&gt;

&lt;p&gt;Conceptually, the pipeline became:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Background Image
        +
Objects Layer
        =
Printable Document
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The implementation looked roughly like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;objectsDataUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;exportCanvasRegion&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;hideBackground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&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;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;backgroundUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;objectsDataUrl&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;p&gt;The solution looked more complicated.&lt;/p&gt;

&lt;p&gt;In reality, it proved to be much more reliable.&lt;/p&gt;




&lt;h2&gt;
  
  
  One More Unexpected Problem
&lt;/h2&gt;

&lt;p&gt;After solving the &lt;code&gt;SecurityError&lt;/code&gt;, another issue appeared.&lt;/p&gt;

&lt;p&gt;Objects slowly drifted away from their correct positions during printing.&lt;/p&gt;

&lt;p&gt;The reason turned out to be surprisingly subtle.&lt;/p&gt;

&lt;p&gt;The background image was positioned in pixels.&lt;/p&gt;

&lt;p&gt;The overlay objects were positioned using percentages.&lt;/p&gt;

&lt;p&gt;When the browser recalculated layout for printing, the two layers no longer aligned.&lt;/p&gt;

&lt;p&gt;The final fix was surprisingly simple.&lt;/p&gt;

&lt;p&gt;We switched background positioning to percentage-based coordinates as well.&lt;/p&gt;

&lt;p&gt;Immediately both layers aligned perfectly again.&lt;/p&gt;

&lt;p&gt;Problems like this are often the hardest to debug.&lt;/p&gt;

&lt;p&gt;Not because the code is wrong.&lt;/p&gt;

&lt;p&gt;But because the coordinate model itself is wrong.&lt;/p&gt;




&lt;h1&gt;
  
  
  What Changed After the Migration
&lt;/h1&gt;

&lt;p&gt;Interestingly, success wasn't measured by fewer lines of code.&lt;/p&gt;

&lt;p&gt;The new implementation actually introduced new functionality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;draft support&lt;/li&gt;
&lt;li&gt;printing&lt;/li&gt;
&lt;li&gt;safe publishing&lt;/li&gt;
&lt;li&gt;multiple workspace modes&lt;/li&gt;
&lt;li&gt;a much cleaner architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The number of lines became a meaningless metric.&lt;/p&gt;

&lt;p&gt;The important improvement was something else.&lt;/p&gt;

&lt;p&gt;Adding new features no longer felt dangerous.&lt;/p&gt;




&lt;h1&gt;
  
  
  What We Learned
&lt;/h1&gt;

&lt;p&gt;Projects like this remind you that the hardest engineering challenges rarely belong to a particular framework.&lt;/p&gt;

&lt;p&gt;Angular evolves.&lt;/p&gt;

&lt;p&gt;Fabric.js evolves.&lt;/p&gt;

&lt;p&gt;TypeScript evolves.&lt;/p&gt;

&lt;p&gt;But the real complexity usually appears somewhere between these technologies.&lt;/p&gt;

&lt;p&gt;Sometimes rewriting twenty thousand lines of code isn't the hardest part of the project.&lt;/p&gt;

&lt;p&gt;Sometimes it's the seemingly innocent &lt;strong&gt;Print&lt;/strong&gt; button.&lt;/p&gt;

&lt;p&gt;That single feature forced us to better understand browser rendering, CORS, Canvas security, coordinate systems, and software architecture than any framework migration ever could.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Looking back, the migration wasn't really about Angular.&lt;/p&gt;

&lt;p&gt;It was about making the product easier to evolve.&lt;/p&gt;

&lt;p&gt;The new architecture didn't dramatically reduce the amount of code.&lt;/p&gt;

&lt;p&gt;Instead, it reduced the cost of future changes.&lt;/p&gt;

&lt;p&gt;Sometimes that's a far more valuable metric than lines of code.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;If this story is interesting, I'd be happy to write a follow-up article explaining how we designed our &lt;code&gt;MapEngine&lt;/code&gt;, why we decided to keep Fabric.js, and how we migrated the administration module without stopping product development.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article is based on our experience building and maintaining an enterprise workspace management platform. Code samples have been simplified, and implementation details have been generalized to respect product confidentiality while preserving the engineering decisions and lessons learned.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  angular #typescript #webdev #architecture
&lt;/h1&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Should Angular Apps Still Rely on RxJS in 2026?</title>
      <dc:creator>Aleksandr Gusev</dc:creator>
      <pubDate>Fri, 22 May 2026 17:09:09 +0000</pubDate>
      <link>https://dev.to/aleksandr_gusev_it/should-angular-apps-still-rely-on-rxjs-in-2025-92p</link>
      <guid>https://dev.to/aleksandr_gusev_it/should-angular-apps-still-rely-on-rxjs-in-2025-92p</guid>
      <description>&lt;p&gt;Angular is going through a quiet but important shift in how reactivity is handled. With the introduction of Signals, many developers are starting to ask a simple question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do we still need RxJS in Angular applications in 2026?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The short answer is: yes — but not everywhere.&lt;/p&gt;

&lt;p&gt;The real answer is more interesting, and it’s about architecture, not preference.&lt;/p&gt;




&lt;h2&gt;
  
  
  Two different mental models
&lt;/h2&gt;

&lt;p&gt;To understand the discussion, it helps to separate two fundamentally different models of reactivity.&lt;/p&gt;

&lt;h3&gt;
  
  
  RxJS: asynchronous streams
&lt;/h3&gt;

&lt;p&gt;RxJS is built around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;event streams&lt;/li&gt;
&lt;li&gt;asynchronous composition&lt;/li&gt;
&lt;li&gt;time-based operations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It shines when dealing with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP requests&lt;/li&gt;
&lt;li&gt;WebSockets&lt;/li&gt;
&lt;li&gt;complex async workflows&lt;/li&gt;
&lt;li&gt;event orchestration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;RxJS is about &lt;strong&gt;time and events&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Signals: local reactive state
&lt;/h3&gt;

&lt;p&gt;Signals represent a different idea:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;synchronous reactivity&lt;/li&gt;
&lt;li&gt;local state tracking&lt;/li&gt;
&lt;li&gt;explicit dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They are best suited for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UI state&lt;/li&gt;
&lt;li&gt;derived state&lt;/li&gt;
&lt;li&gt;component-level reactivity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Signals are about &lt;strong&gt;state and UI consistency&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Code comparison
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Signals example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doubled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&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;p&gt;Signals make state and dependencies explicit. No subscriptions, no hidden wiring.&lt;/p&gt;




&lt;h3&gt;
  
  
  RxJS example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BehaviorSubject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rxjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BehaviorSubject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doubled$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;count$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;count$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&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;p&gt;RxJS introduces a stream-based model where everything flows through observables.&lt;/p&gt;




&lt;h2&gt;
  
  
  The real problem is not technology, but mixing models
&lt;/h2&gt;

&lt;p&gt;The biggest architectural issue in modern Angular applications is not choosing between RxJS and Signals.&lt;/p&gt;

&lt;p&gt;It is &lt;strong&gt;mixing them without clear boundaries&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When both are used everywhere:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;state becomes duplicated&lt;/li&gt;
&lt;li&gt;logic becomes scattered&lt;/li&gt;
&lt;li&gt;it becomes unclear where the “source of truth” lives&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Where RxJS is still the right tool
&lt;/h2&gt;

&lt;p&gt;Even in 2026, RxJS is still essential:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP request pipelines&lt;/li&gt;
&lt;li&gt;cancellation and retry logic&lt;/li&gt;
&lt;li&gt;real-time data streams&lt;/li&gt;
&lt;li&gt;coordination of multiple async sources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the problem involves &lt;strong&gt;time, concurrency, or event composition&lt;/strong&gt;, RxJS is still the better abstraction.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where Signals are a better fit
&lt;/h2&gt;

&lt;p&gt;Signals work better when the problem is local and state-driven:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;component state&lt;/li&gt;
&lt;li&gt;derived UI values&lt;/li&gt;
&lt;li&gt;form state&lt;/li&gt;
&lt;li&gt;simple reactive bindings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Signals reduce unnecessary complexity and make data flow more explicit.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architectural boundary
&lt;/h2&gt;

&lt;p&gt;A simple rule:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;RxJS handles the outside world.&lt;br&gt;
Signals handle the UI world.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;RxJS = integration layer&lt;/li&gt;
&lt;li&gt;Signals = presentation layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When this boundary is respected, Angular applications become significantly easier to maintain.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;In 2026, RxJS is not obsolete in Angular — it is simply no longer the only reactive model.&lt;/p&gt;

&lt;p&gt;Signals introduce a second layer that allows developers to simplify UI logic without abandoning reactive power.&lt;/p&gt;

&lt;p&gt;The best Angular applications are not those that choose one over the other, but those that clearly define when to use each.&lt;/p&gt;

&lt;p&gt;Architecture is not about tools.&lt;br&gt;
It is about boundaries.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>angular</category>
      <category>signals</category>
      <category>rxjs</category>
    </item>
    <item>
      <title>Angular Signals</title>
      <dc:creator>Aleksandr Gusev</dc:creator>
      <pubDate>Fri, 24 Apr 2026 18:34:08 +0000</pubDate>
      <link>https://dev.to/aleksandr_gusev_it/angular-signals-2bd2</link>
      <guid>https://dev.to/aleksandr_gusev_it/angular-signals-2bd2</guid>
      <description>&lt;h1&gt;
  
  
  Angular Signals — A Shift in Angular Reactivity
&lt;/h1&gt;

&lt;p&gt;Angular has changed significantly over the past few years. What was once often perceived as a heavy framework with complex change detection and a strong reliance on Zone.js is gradually moving toward a more explicit and predictable reactivity model.&lt;/p&gt;

&lt;p&gt;One of the key steps in this direction is &lt;strong&gt;Signals&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Signals?
&lt;/h2&gt;

&lt;p&gt;Signals in Angular introduce a new way of handling state that makes reactivity more explicit.&lt;/p&gt;

&lt;p&gt;In simple terms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Angular used to rely heavily on Zone.js and implicit change detection&lt;/li&gt;
&lt;li&gt;Now it introduces a model where state and dependencies are explicitly defined&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A Signal is a reactive primitive that holds a value and notifies the system when that value changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;One of the long-standing challenges in Angular was not complexity itself, but &lt;strong&gt;implicit reactivity&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Developers often had to deal with questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What exactly triggered a UI update?&lt;/li&gt;
&lt;li&gt;Why did this component re-render?&lt;/li&gt;
&lt;li&gt;Where does change detection actually stop?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Signals make this behavior more explicit and predictable.&lt;/p&gt;

&lt;p&gt;Now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dependencies are directly readable&lt;/li&gt;
&lt;li&gt;updates are more granular&lt;/li&gt;
&lt;li&gt;less framework-level “magic” is involved&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A simple mindset shift
&lt;/h2&gt;

&lt;p&gt;Before Signals:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Angular will figure out what needs to update.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With Signals:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I explicitly define what depends on what.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is not just a technical change — it’s a conceptual shift in how we think about UI reactivity.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changes in practice
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. More predictable state management
&lt;/h3&gt;

&lt;p&gt;Signals move Angular closer to simple reactive primitives instead of relying on global change detection mechanisms.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Reduced reliance on Zone.js
&lt;/h3&gt;

&lt;p&gt;Angular is gradually moving toward a model where Zone.js is no longer the central piece of reactivity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Note: What is Zone.js?
&lt;/h2&gt;

&lt;p&gt;Zone.js is a library that was historically at the core of Angular’s change detection system.&lt;/p&gt;

&lt;p&gt;In simple terms, it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tracks asynchronous operations (setTimeout, HTTP requests, events)&lt;/li&gt;
&lt;li&gt;and notifies Angular when it should check for UI updates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allowed Angular to automatically update the UI without explicit developer intervention.&lt;/p&gt;

&lt;p&gt;However, this convenience comes with a trade-off: behavior becomes less transparent, since it is not always clear what triggered a re-render.&lt;/p&gt;

&lt;p&gt;Signals address part of this by making reactivity more explicit and controlled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Signals vs RxJS
&lt;/h2&gt;

&lt;p&gt;Signals do not replace RxJS — they serve different purposes.&lt;/p&gt;

&lt;p&gt;RxJS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;streams and events&lt;/li&gt;
&lt;li&gt;asynchronous workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Signals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;local state&lt;/li&gt;
&lt;li&gt;synchronous reactivity&lt;/li&gt;
&lt;li&gt;UI-driven updates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They complement each other rather than compete.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Signals shine
&lt;/h2&gt;

&lt;p&gt;Signals are especially useful in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;complex UI state&lt;/li&gt;
&lt;li&gt;forms and interactive interfaces&lt;/li&gt;
&lt;li&gt;applications where predictability matters&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Signals are not just a new API in Angular.&lt;/p&gt;

&lt;p&gt;They represent a shift toward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;more explicit reactivity&lt;/li&gt;
&lt;li&gt;more predictable UI behavior&lt;/li&gt;
&lt;li&gt;a simpler mental model for developers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s one of the most meaningful evolutions in Angular in recent years — aimed at reducing hidden complexity without sacrificing power.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>angular</category>
      <category>signals</category>
    </item>
    <item>
      <title>Why Being a Senior Developer Is Less About Tech Stack and More About Thinking</title>
      <dc:creator>Aleksandr Gusev</dc:creator>
      <pubDate>Tue, 20 Jan 2026 18:24:41 +0000</pubDate>
      <link>https://dev.to/aleksandr_gusev_it/why-being-a-senior-developer-is-less-about-tech-stack-and-more-about-thinking-267l</link>
      <guid>https://dev.to/aleksandr_gusev_it/why-being-a-senior-developer-is-less-about-tech-stack-and-more-about-thinking-267l</guid>
      <description>&lt;p&gt;After nearly a decade in professional web development, I’ve noticed that many discussions about seniority focus on the wrong things. People ask which tech stack you need to learn or how many years it takes to become a senior. In my experience, those questions miss the point.&lt;/p&gt;

&lt;p&gt;Being a senior developer is not about specific technologies or job titles. It’s about the way you think and the responsibility you take.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Tech Stack Is a Tool, Not a Level
&lt;/h2&gt;

&lt;p&gt;Throughout my career, I’ve worked with different frameworks and approaches. Some were trendy, others were already considered outdated when they were introduced. Almost all of them eventually changed.&lt;/p&gt;

&lt;p&gt;What didn’t change was the level of responsibility.&lt;/p&gt;

&lt;p&gt;A junior developer worries about &lt;em&gt;how to write code&lt;/em&gt;.&lt;br&gt;
A mid-level developer worries about &lt;em&gt;how to write correct code&lt;/em&gt;.&lt;br&gt;
A senior developer worries about &lt;em&gt;why this code should exist at all&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Responsibility Comes Before the Title
&lt;/h2&gt;

&lt;p&gt;Senior-level thinking often appears long before the official title:&lt;br&gt;
— when you think about maintainability, not just delivery;&lt;br&gt;
— when you question requirements instead of blindly implementing them;&lt;br&gt;
— when you understand that there is no perfect solution, only trade-offs.&lt;/p&gt;

&lt;p&gt;At some point, you stop writing code for machines and start writing it for people who will read and maintain it months or years later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Is Not About Diagrams
&lt;/h2&gt;

&lt;p&gt;Architecture is often associated with clean diagrams and well-known patterns. In reality, architecture is more about:&lt;br&gt;
— where the system can break;&lt;br&gt;
— how expensive changes will be;&lt;br&gt;
— who will maintain it and how.&lt;/p&gt;

&lt;p&gt;Sometimes the best architectural decision is the most boring one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Experience Is Not the Number of Projects
&lt;/h2&gt;

&lt;p&gt;Experience doesn’t come from the number of projects or lines of code. It comes from situations where you:&lt;br&gt;
— had to fix someone else’s mistakes;&lt;br&gt;
— rolled back your own wrong decisions;&lt;br&gt;
— supported a product for years instead of shipping it and moving on.&lt;/p&gt;

&lt;p&gt;These moments are what actually shape professional judgment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Being a senior developer is not a goal or a status. It’s a side effect of long-term work on real products and taking responsibility for the consequences of your decisions.&lt;/p&gt;

&lt;p&gt;You can learn a tech stack.&lt;br&gt;
Professional thinking takes time to earn.&lt;/p&gt;

&lt;p&gt;This way of thinking has helped me make better long-term decisions in real-world products.&lt;/p&gt;

</description>
      <category>career</category>
      <category>discuss</category>
      <category>softwaredevelopment</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
