<?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: Artur Ampilogov</title>
    <description>The latest articles on Forem by Artur Ampilogov (@arturampilogov).</description>
    <link>https://forem.com/arturampilogov</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%2F1145505%2Fee53e8c0-dca8-4899-a55e-6c43addc1cb4.jpeg</url>
      <title>Forem: Artur Ampilogov</title>
      <link>https://forem.com/arturampilogov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/arturampilogov"/>
    <language>en</language>
    <item>
      <title>How to Judge Solutions Like an Engineer</title>
      <dc:creator>Artur Ampilogov</dc:creator>
      <pubDate>Mon, 26 Jan 2026 23:45:53 +0000</pubDate>
      <link>https://forem.com/arturampilogov/how-to-judge-solutions-like-an-engineer-352i</link>
      <guid>https://forem.com/arturampilogov/how-to-judge-solutions-like-an-engineer-352i</guid>
      <description>&lt;p&gt;When we face a problem, often there are several solutions. Which one is just good enough, and which one is ideal?&lt;/p&gt;

&lt;h2&gt;
  
  
  Ideal solution criteria 🎯
&lt;/h2&gt;

&lt;p&gt;As a solution indicator test, I often use a powerful idea from the Theory of Inventive Problem Solving (TRIZ). &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ideal final result&lt;/strong&gt; is achieved when the contradiction disappears through a change in approach, or when the function works without the initial system, or when the object (system) automatically removes the contradiction. No system deterioration. No compromises.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: Airbus 330 sidestick function ✈️
&lt;/h2&gt;

&lt;p&gt;The drama happened in 2009, when Air France Flight 447 was en route from Brazil to France.&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%2Fsi638jcxnfd3wkf3lof9.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%2Fsi638jcxnfd3wkf3lof9.png" alt="Flight derbis" width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During mid-flight, ice crystals began to accumulate in the pitot tubes, affecting the speed measurement. The autopilot turned itself off. The pilots took manual control.&lt;/p&gt;

&lt;p&gt;Historically, to maneuver an airplane, US and Russian manufacturers use control yokes (left picture), while the European concern Airbus uses sidesticks (right picture).&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%2Fwwl7cc7w58282mp8euco.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%2Fwwl7cc7w58282mp8euco.png" alt="Yoke vs sidestick" width="800" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During the pilot's manual control, the copilot abruptly pulled back on his side stick without notice, raising the plane's nose. After some time, the wings lost lift, and the aircraft began to stall, loosing the hight. To overcome the stall and gain speed, the pilot followed the routine steps: pushed forward the side stick to temporarily lower the nose.&lt;/p&gt;

&lt;p&gt;The dual sidesticks on Airbus planes work as follows. They are physically independent, and the program calculates the result. There are basically three conditions of a sidestick related to horizon tilt: neutral gives full control to the other side stick, forward, and backward. When both sidesticks are not in the neutral position, their result is some up. This can be presented as a simple function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function getStickLevel(left: number, right: number) {
   // when left is neutral
   if (left == 0) { 
     return right; // full control to the right
   }
   // when right is neutral
   else if (right == 0) {
     return left; // full control to the left
   }
   // otherwise, average the levels
   else {
     return (left + right) / 2;
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Problem 🤔
&lt;/h3&gt;

&lt;p&gt;The copilot accidentally pulled back their sidestick, cancelling the pilot's sidestick's forward level. There were system warnings about both sticks being in use at the same time, but during a stressful situation, the pilots' attention was elsewhere. The recording showed the copilot speaking, "I don't have control of the aircraft anymore now," and "But I've been at maximum nose-up for a while!" when the copilot realized the issue. Ultimately, the airplane crashed into the ocean.&lt;/p&gt;

&lt;p&gt;What is the contradiction from the program perspective? The function must sum any given non-zero numbers and not return 0. The mathematical module cannot be used. This is impractical when you have input values, say, &lt;code&gt;-1&lt;/code&gt; and &lt;code&gt;+1&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution 💡
&lt;/h3&gt;

&lt;p&gt;Let's move the problem on the physical level out of code. The copilot’s control input must exist so they can instantly assist, and must not exist so it does not interfere invisibly. &lt;/p&gt;

&lt;p&gt;One solution is widely used in US and Russian airplanes. The sticks are physically connected and are in sync. You move the left stick, and the right stick immediately mirrors those movements.&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%2Fknq62epz0ig1n95maq00.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%2Fknq62epz0ig1n95maq00.png" alt="Double contole yoke" width="800" height="562"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That upper-level solution essentially eliminated the problem. Moreover, the best part is zero code. There is no need for a computer controller.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: Abu Dhabi speed cameras 📸
&lt;/h2&gt;

&lt;p&gt;Placing many speed limit cameras on a long highway requires a large budget.&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%2Ftvq74puor9cprquv24t0.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%2Ftvq74puor9cprquv24t0.png" alt="Speed limit cameras" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 🤔
&lt;/h3&gt;

&lt;p&gt;The contradiction can be stated as follows. A highway is long and requires many expensive cameras. To measure a car's speed at any point, there should be a camera, and at the same time, there should not be a camera.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution 1 💡
&lt;/h3&gt;

&lt;p&gt;Abu Dhabi's government experiments with average car speed. The first camera records the time of highway entrance, and the second records the time of exit. The distance is known, so the average car speed can be calculated. If it exceeds the limit, the vehicle definitely sped up too much at least once along the route. You can also drive very fast, half the route, but then you will have to drive the second part slowly. The solution drastically reduces the number of cameras.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution 2 💡
&lt;/h3&gt;

&lt;p&gt;In clear weather, from a height of 30 meters (100 feet), the horizon is visible up to 20 km. To locate a phone, cell towers use triangulation. Knowing three radii to the phone, the circle intersections will reveal the exact position.&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%2Fer95k0qdog8olwdqmbdt.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%2Fer95k0qdog8olwdqmbdt.png" alt="Cell triangulation" width="450" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today, almost every highway works with transponders in cars. A transponder can be extended with a minimal phone SIM card functionality, so that cell providers can track car speeds. Highways already have cell towers around. Transponders are widely used. &lt;/p&gt;

&lt;p&gt;This solution completely eliminates cameras, and the speed limit system continues to function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: ML learning (AI) 🧠
&lt;/h2&gt;

&lt;p&gt;Today, Machine Learning approximates a function that maps millions of given inputs to their expected outputs. Input can be an image, and output can be text describing the image object. This process is called "labelling" and requires an enormous number of examples for the model to create a very good approximation for almost any unseen image. Historically, developers created huge databases with &lt;code&gt;input&lt;/code&gt; -&amp;gt; &lt;code&gt;correct answer&lt;/code&gt; examples created by hand. Each image is manually highlighted with polygons showing the exact object positions. Just elephant images could require tens of thousands of examples. This is a trunk, this is a leg, this is an ear, and as a whole, this is an elephant.&lt;/p&gt;

&lt;p&gt;Such learning, with carefully curated examples of inputs and expected outputs, is called supervised learning.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 🤔
&lt;/h3&gt;

&lt;p&gt;An AI model should learn patterns for object relationships. If we see an elephant trunk, there is likely an elephant head and a body with legs. It is not related to a bird or a table. &lt;/p&gt;

&lt;p&gt;From one point of view, there should be a polygon for each image object; from another, there should not be a polygon. Contradiction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution 💡
&lt;/h3&gt;

&lt;p&gt;The following modern approach, called self-supervised learning, does not completely eliminate human labelling but drastically reduces it.&lt;/p&gt;

&lt;p&gt;At the first stage, each image is randomly divided into blocks, for example, 3x3, and some blocks are hidden. An AI model trains to guess the hidden parts. By doing so, the model learns patterns between the objects. Like an elephant should have a trunk. It learns relationships on its own without a human manually highlighting all the objects in the image.&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%2Fua65hg09ogd773w4oekb.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%2Fua65hg09ogd773w4oekb.png" alt="Elephant" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The model does not know how elephant objects are called in different languages. The second part is to show prepared, labeled images. This time, we need much less image labelling, as the AI model has already built object relationship patterns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Note about TRIZ 🧬
&lt;/h2&gt;

&lt;p&gt;Altshuller, author of TRIZ, was a famous inventor who reviewed 40 000 engineering patents and developed algorithms to resolve technical contradictions. The algorithms have been used by research centers worldwide, including companies such as NASA, Boeing, Siemens, GE, Ford, Intel, Samsung, and Apple.&lt;/p&gt;

&lt;p&gt;The genius of Altshuller is that he built the invention machine in the physical area.&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%2Fp7lgc3ekkcw4ahdalu2a.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%2Fp7lgc3ekkcw4ahdalu2a.png" alt="Altshuller" width="404" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The given examples do not comply with TRIZ, and there was no intent to do so. &lt;/p&gt;

&lt;p&gt;First, TRIZ was created to resolve physical problems. To state the right contradiction, you should have a very good experience with it, and also specify what system quality you want to improve, and what the constraints are.&lt;/p&gt;

&lt;p&gt;Second, there are strict algorithms and a list of known physical and chemical approaches to apply to each specific type of contradiction and system quality improvement. The solution is not known, but you likely be able to find the optimal one. Instead, I picked examples of already-known solutions, which is totally counter to TRIZ. &lt;/p&gt;

&lt;p&gt;There are many attempts to apply TRIZ in business, the arts, public relations, and even IT. None of them has been endorsed by the TRIZ community without dissent. One reason is that such work requires enormous intellectual resources and perseverance, which is hard to find nowadays. For example, Vikentyev, also a former Alshuller student, analyzes 4-8 kg of scientific books daily (!) for the research database on creativity. Also, there is no guarantee that a similar algorithm exists in a non-physical area.&lt;/p&gt;

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

&lt;p&gt;The concept, when the initial problem disappears while the system continues to function, is very powerful. Also, during programming, I often found that the ideal solution had no code and that systems were improved by other means, such as redefining business tasks or switching to a different service platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Air_France_Flight_447" rel="noopener noreferrer"&gt;Air France Flight 447, Wikipedia&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.itsinternational.com/its2/news/abu-dhabi-opts-average-speed-cameras" rel="noopener noreferrer"&gt;Average car speed in Abu Dhabi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.altshuller.ru/world/eng/index.asp" rel="noopener noreferrer"&gt;TRIZ site&lt;/a&gt;, supported by Altshuller's family and friends. As a bonus, fiction fans can find the list of all fiction ideas of all time.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.altshuller.ru/e-books/" rel="noopener noreferrer"&gt;Introduction to TRIZ. Basic concepts and approaches&lt;/a&gt;, v 3.0, the original e-book.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vikent.ru/" rel="noopener noreferrer"&gt;Vikent.ru&lt;/a&gt; by Vikentyev I.L., contains the largest world research database about creativity.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://effectivetypescript.com/" rel="noopener noreferrer"&gt;Effective TypeScript: 83 Specific Ways to Improve Your TypeScript&lt;/a&gt;, 2nd edition, 2024, by Dan Vanderkam, where I initially met the Air France Flight 447 example.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aima.cs.berkeley.edu/" rel="noopener noreferrer"&gt;Artificial Intelligence: A Modern Approach&lt;/a&gt;, 4th Global edition, 2022, by Stuart Russell and Peter Norvig. The classic book on AI.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.bardehle.com/europeansoftwarepatents/" rel="noopener noreferrer"&gt;European software patent examples&lt;/a&gt; by Bardehle Pagenberg.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>science</category>
      <category>beginners</category>
      <category>theory</category>
    </item>
    <item>
      <title>Concurrency and API Protection - Part 3</title>
      <dc:creator>Artur Ampilogov</dc:creator>
      <pubDate>Thu, 16 Oct 2025 06:41:41 +0000</pubDate>
      <link>https://forem.com/arturampilogov/concurrency-and-api-protection-24kc</link>
      <guid>https://forem.com/arturampilogov/concurrency-and-api-protection-24kc</guid>
      <description>&lt;p&gt;This article is part of a series that explores practical patterns for protecting your systems.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/arturampilogov/concurrency-and-row-versioning-part-1-39hn"&gt;Concurrency and Row Versioning - Part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/arturampilogov/concurrency-and-transactional-row-versioning-part-2-2cbn"&gt;Concurrency and Transactions - Part 2&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Concurrency and API Protection - Part 3 ⭐&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  ❓ Concurrent requests and external services
&lt;/h2&gt;

&lt;p&gt;Occasionally, applications encounter broken state errors that are difficult to debug, especially when the issue affects only a small subset of resources. Investigation often reveals that the root cause is a UI that fails to disable the submit button, allowing users to double-click and send multiple requests to the same REST API.&lt;/p&gt;

&lt;p&gt;In the previous series, we explored how to protect against such cases using our internal services. Today, modern applications almost always rely on third-party services, with in-house teams focusing primarily on core functionality. That approach enhances both security and development efficiency, but it also introduces a new challenge.&lt;/p&gt;

&lt;p&gt;For example, &lt;a href="https://percihealth.com/" rel="noopener noreferrer"&gt;Perci Health&lt;/a&gt; uses a famous service for Fast Healthcare Interoperability Resources (FHIR). Transactions are very limited, and conditional row versions are not supported. During testing, we found that a nurse can double-click on a submit button to update an appointment. This could lead to a broken state: while only one appointment encounter should exist, two or three resources appear with incorrect statuses.&lt;/p&gt;

&lt;p&gt;A similar case was found during the contract work at &lt;a href="https://www.checkatrade.com/" rel="noopener noreferrer"&gt;Checkatrade&lt;/a&gt;. Multi-clicking on the Salesforce button led to two or three modification requests with a slight sub-second difference.&lt;/p&gt;

&lt;p&gt;To eliminate or at least reduce such issues, we can move resource protection from the DB to the upper level—the REST API. This idea was initially implemented at Checkatrade with database transactions. This article shows the improved transactionless version. &lt;/p&gt;

&lt;h3&gt;
  
  
  🚫 No out-of-the-box solutions
&lt;/h3&gt;

&lt;p&gt;At the time of writing, none of the major cloud providers offer a built-in solution to protect REST APIs from concurrent modification requests. Services like Amazon API Gateway, Google Cloud API Gateway, and Azure API Management Gateway provide only basic rate-limiting capabilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  💡 REST API protection idea
&lt;/h3&gt;

&lt;p&gt;Here is the idea of API protection against concurrent requests.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Consider only modification methods: &lt;code&gt;POST&lt;/code&gt;, &lt;code&gt;PUT&lt;/code&gt;, &lt;code&gt;PATCH&lt;/code&gt;, and &lt;code&gt;DELETE&lt;/code&gt;. Do not protect &lt;code&gt;GET&lt;/code&gt; requests.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Protect APIs requiring authentication, so we do not touch &lt;code&gt;/auth/sign-in&lt;/code&gt; and other public methods.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the request path has a parameter, then it is the exact resource modification, and we must protect it, for example, &lt;code&gt;DELETE "/appointments/:appointmentId"&lt;/code&gt;. Then, if there is no parameter and a user is authenticated, we also need to protect the API, and we do it by adding the user ID prefix, so &lt;code&gt;PUT /me&lt;/code&gt; becomes &lt;code&gt;PUT /:userId/me&lt;/code&gt;, &lt;code&gt;POST /appointments&lt;/code&gt; becomes &lt;code&gt;POST /:userId/appointmetns&lt;/code&gt;. Otherwise, it is a public API without a parameter, such as &lt;code&gt;POST /auth/sign-in&lt;/code&gt;, and there is no need for protection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Group API parametrized paths per single parent resource, for example, all the following modification requests &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;PUT /appointments/100&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /appointments/100/end-call&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DELETE /appointments/100&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;have one parent resource: &lt;code&gt;"/appointments/100".&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mark in a database that the request for a special resource is in process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If another resource tries to own the modification, return the &lt;code&gt;HTTP 409 Conflict&lt;/code&gt; status code (or &lt;code&gt;HTTP 423 Locked&lt;/code&gt;). A UI client can fetch fresh data and notify a user what to do with a conflict.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The owner completes the request and unlocks the modification resource.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🎯 REST API protection with Firestore DB
&lt;/h3&gt;

&lt;p&gt;Here, we consider a NodeJS ExpressJS example with Firestore DB. A similar one can be built with almost any REST API framework, like NodeJS Fastify, ASP.NET, Python Jango/FastAPI, Java Vert.x/Spring Boot, Go Gin/Fiber, etc. Any database that supports conditional updates with row versioning, transactions, or a lock mechanism can be used: key-value RedisDB or KeyDB, document-oriented Fistore, Supabase, or MongoDB, a modern SQL database, such as Postgres, MS SQL, Oracle, MySQL, etc.&lt;/p&gt;

&lt;p&gt;Now, let us write our Express and Firestore implementation step by step in TypeScript.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Introduce the acquire lock function returning a type result and an optional release lock function. The type result can be &lt;code&gt;skipped&lt;/code&gt; - lock is not applicable, &lt;code&gt;locked&lt;/code&gt; - lock was successfully applied, &lt;code&gt;conflict&lt;/code&gt; - not used due to the resource conflict.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const acquireLock = async (req: Request, res: Response): 
    Promise&amp;lt;{ type: 'skipped' } | 
            { type: 'locked'; release: () =&amp;gt; Promise&amp;lt;void&amp;gt; } |
            { type: 'conflict' } &amp;gt; =&amp;gt; {

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

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create an ExpressJS middleware that can be reused with multiple APIs&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Request, Response, NextFunction } from 'express';

export const lockMiddleware = async (
    req: Request,
    res: Response,
    next: NextFunction,
  ) =&amp;gt; {        
  const lockResult = await acquireLock(req, res);

  if (lockResult.type === 'conflict') {
      // send HTTP 409 Conflict or 423 Locked code
      res.sendStatus(409); 
      return;
  }

  try {
    next(); // API request handler        
  } finally {
    if (lockResult.type === 'locked') {
      await lockResult.release();
    }
  }
}; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Protect only for modification methods.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const PROTECTED_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE']);

if (!PROTECTED_METHODS.has(req.method)) {
  // Not a modification, no need to lock
  return { type: 'skipped' };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assume there is an auth &lt;a href="https://expressjs.com/en/guide/using-middleware.html" rel="noopener noreferrer"&gt;middleware&lt;/a&gt;. It is out of the scope of this article to fully implement it, for example, by inspecting the &lt;code&gt;Authorization: Bearer &amp;lt;token&amp;gt;&lt;/code&gt; header. One practice is to store the authentication results in the &lt;code&gt;res.locals&lt;/code&gt; object. We assume that if &lt;code&gt;res.locals.userId&lt;/code&gt; is not empty, the user is authenticated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ignore public endpoints, such as &lt;code&gt;/auth/sign-in&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (!res.locals.userId) {
  // Public endpoint, no need to lock
  return { type: "skipped" };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create two helper functions. First, canonicalize the path so that the action endpoints &lt;code&gt;/resource/:id/action&lt;/code&gt; and lock on &lt;code&gt;/resource/:id&lt;/code&gt; and &lt;code&gt;/me&lt;/code&gt; on &lt;code&gt;/:userId/me&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const canonicalizePath = (
  path: string,
  params: Record&amp;lt;string, string&amp;gt;,
  userId: string,
): string =&amp;gt; {
  // clean up the request path from query parameters,
  // so /appointments/1/cancel?abc=1&amp;amp;def=some_value becomes /appointments/1/cancel
  path = path.split('?')[0];
  path = path.length === 0 ? '/' : path;

  // remove double slashes and trim trailing slash (except root)
  path = path.replace(/\/+/g, '/');
  if (path.length &amp;gt; 1 &amp;amp;&amp;amp; path.endsWith('/')) {
    path = path.slice(0, -1);
  }

  // If any segment matches a param, keep only the collection path + id
  // e.g. /resource/:id/subresource/:subId/action becomes /resource/:id
  // e.g. /prefix/resource/:id/action becomes /prefix/resource/:id
  const segments = path.split('/').filter(Boolean);
  if (segments.length &amp;gt;= 2) {
    // Iterate through segments; stop when a param value appears
    for (let i = 0; i &amp;lt; segments.length; i++) {
      const segment = segments[i];
      const isParamSegment = Object.values(params).includes(segment);

      if (isParamSegment &amp;amp;&amp;amp; i &amp;gt; 0) {
        // Keep prefix up to this param
        const normalized = `/${segments.slice(0, i + 1).join('/')}`;
        return normalized;
      }
    }
  }

  // No params matched in path.
  // Prefix with userId to avoid clashes between different users
  // e.g. /learn/articles/saved becomes /:userId/learn/articles/saved
  // e.g. POST /appointments becomes /:userId/appointments
  return `/${userId}${path}`;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The path can be too long for a Firebase collection or have unsupported symbols, so we can hash it.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import crypto from 'crypto';

const buildLockId = (canonicalPath: string) =&amp;gt; {
  // path may contain special symbols or be too long, hash it
  return crypto.createHash('sha256').update(canonicalPath).digest('hex');
};
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Our &lt;code&gt;acquireLock&lt;/code&gt; function becomes&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const acquireLock = async (
  req: Request,
  res: Response
): Promise&amp;lt;
  | { type: "skipped" }
  | { type: "locked"; release: () =&amp;gt; Promise&amp;lt;void&amp;gt; }
  | { type: "conflict" }
&amp;gt; =&amp;gt; {
  if (!PROTECTED_METHODS.has(req.method)) {
    // Not a modification, no need to lock
    return { type: "skipped" };
  }

  if (!res.locals.userId) {
    // Public endpoint, no need to lock
    return { type: "skipped" };
  }

  const canonicalPath = canonicalizePath(
    req.path,
    res.params,
    res.locals.userId
  );
  const lockId = buildLockId(canonicalPath);

  // FOLLOWING IMPLEMENTATION
}
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;For brevity, the following code snippets will be part of the &lt;code&gt;// FOLLOWING IMPLEMENTATION&lt;/code&gt; body section.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A cloud provider can unexpectedly destroy a running application instance for many reasons. Our lock cannot be released and gets stuck forever. The first thing to do is check whether the request is stale and, if so, delete the stuck lock.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// How long a single request may hold the lock before it’s considered stale
const LOCK_TTL_SECONDS = 5;

const db = getFirestore();
const lockRef = db.collection('request-locks').doc(lockId);

const staleLockDoc = await lockRef.get();
if (
    staleLockDoc.updateTime &amp;amp;&amp;amp;
    staleLockDoc.updateTime.toMillis() + LOCK_TTL_SECONDS * 1000 &amp;lt;
      Timestamp.now().toMillis()
) {
  try {
    await lockRef.delete({
      lastUpdateTime: staleLockDoc.updateTime,
    });
  } catch {
    // ignore delete error
  }
}
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The &lt;code&gt;lastUpdateTime&lt;/code&gt; precondition prevents the accidental removal of a concurrently updated version, which is covered in &lt;a href="https://dev.to/arturampilogov/concurrency-and-transactional-row-versioning-part-2-2cbn"&gt;Concurrency and Row Versioning—Part 1&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The next step is to check for ongoing processing and mark the conflict.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const existingLockDoc = await lockRef.get();
if (existingLockDoc.exists) {
  // Someone else holds a fresh lock
  return { type: 'conflict' };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now it's time to insert a row lock indicator. If another processor did it before us, the row insert will fail, indicating the conflict.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let createdLockDoc: FirebaseFirestore.DocumentSnapshot&amp;lt;
  FirebaseFirestore.DocumentData,
  FirebaseFirestore.DocumentData
&amp;gt;;
try {
  await lockRef.create({
    method: req.method,
    path: req.path,
    canonicalPath,
  });

  createdLockDoc = await lockRef.get();
} catch (error) {
  const firebaseError = error as { code?: string | number; message?: string };
  // error code `6` - the document already exists
  if (firebaseError.code === 6) {
    // Someone else created a lock
    return { type: 'conflict' };
  } else {
    throw error; // rethrow unexpected error
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The last function part is to return the release lock function.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const release = async () =&amp;gt; {
  const logger = new Logger(`${appName}:lockMiddleware`);
  try {
    // Only delete if we still own it (avoid nuking a refreshed lock)
    await createdLockDoc.ref.delete({
      lastUpdateTime: createdLockDoc.updateTime,
    });
  } catch {
    // skip release error
  }
};

return { type: 'locked', release };
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To use the lock mechanism in multiple requests, apply the &lt;code&gt;lockMiddleware&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  import { default as express } from 'express';
  import { lockMiddleware } from '../path-to/lockMiddleware';
  import { yourRouterOne } from '../path-to/yourRouterOne';

  const api = express();
  api.use(lockMiddleware); // applied to all routers below
  api.use(yourRouterOne);
  // rest of the routers
&lt;/code&gt;&lt;/pre&gt;

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

&lt;h3&gt;
  
  
  Full middleware version
&lt;/h3&gt;

&lt;p&gt;The complete middleware example can be found at &lt;a href="https://gist.github.com/ArturAmpilogov/d82b544eff208d5544538f3af3a4d6e5" rel="noopener noreferrer"&gt;lockMiddleware.ts&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;To test concurrent requests, run &lt;code&gt;curl&lt;/code&gt; commands almost simultaneously, for example, a POST request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seq 20 | xargs -n1 -P5 curl -X POST -s -o /dev/null -w "%{http_code} %{errormsg}\n" \
--data-raw '{ "id": "abcde" }' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer &amp;lt;TOKEN&amp;gt;' \
https://your-api-path
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🚀 Result
&lt;/h2&gt;

&lt;p&gt;With this protection in place, concurrent API requests no longer cause invalid resource states. The best part is that it achieves this without Firestore transactions, keeping it "blazingly" fast. &lt;/p&gt;

</description>
      <category>database</category>
      <category>restapi</category>
      <category>apigateway</category>
      <category>concurrency</category>
    </item>
    <item>
      <title>Concurrency and Transactions - Part 2</title>
      <dc:creator>Artur Ampilogov</dc:creator>
      <pubDate>Mon, 13 Oct 2025 21:22:29 +0000</pubDate>
      <link>https://forem.com/arturampilogov/concurrency-and-transactional-row-versioning-part-2-2cbn</link>
      <guid>https://forem.com/arturampilogov/concurrency-and-transactional-row-versioning-part-2-2cbn</guid>
      <description>&lt;p&gt;This is a part of a series that explores practical patterns to protect your system:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/arturampilogov/concurrency-and-row-versioning-part-1-39hn"&gt;Concurrency and Row Versioning - Part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Concurrency and Transactions - Part 2 ⭐&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/arturampilogov/concurrency-and-api-protection-24kc"&gt;Concurrency and API Protection - Part 3&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  💭 Why is a transaction needed?
&lt;/h2&gt;

&lt;p&gt;In some cases, you need to modify several resources within a single operation. A transaction ensures that these updates are treated as one atomic unit — either all changes succeed together, or none are applied (they are rolled back).&lt;/p&gt;

&lt;h2&gt;
  
  
  SQL transaction
&lt;/h2&gt;

&lt;p&gt;Most modern SQL servers support transactions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BEGIN;

# Step 1 - read
SELECT * FROM users where id = 42
SELECT * FROM subscriptions where user_id = 42

# Step 2 - your logic

# Step 3 - modify resources
UPDATE users
  SET name = 'Albert', version = version + 1
  WHERE id = 42 AND version = 7;

UPDATE subscriptions
  SET plan = 'pro', version = version + 1
  WHERE id = $SUBSCRIPTION_ID AND version = 3;

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

&lt;/div&gt;



&lt;p&gt;The user row modification will be automatically rolled back if the subscription update fails, and vice versa.&lt;/p&gt;

&lt;h3&gt;
  
  
  🪶 Is SQL transaction heavy?
&lt;/h3&gt;

&lt;p&gt;A decade ago, SQL transactions would immediately downgrade the server's performance. The highest isolation level, &lt;code&gt;SERIALIZABLE,&lt;/code&gt; provides consistent checks for concurrent reads and writes but adds locks on rows and tables. Table locks are cumbersome, especially for &lt;code&gt;READ&lt;/code&gt; locks, when other concurrent fetch queries should wait until the table is unlocked.&lt;/p&gt;

&lt;p&gt;Today, SQL servers represent the art of engineering and have gained huge performance in all aspects.&lt;/p&gt;

&lt;p&gt;First, databases improved their algorithms to use a snapshot of data per transaction based on the "Multiversion Concurrency Control (MVCC)" idea introduced in 1981 by Philip A. Bernstein and Nathan Goodman. All queries and modifications run against the database snapshot inside the transaction (requires DB snapshot isolation setting). Concurrent requests do not introduce changed records, and no locks are required.&lt;/p&gt;

&lt;p&gt;Second, in 2008, Cahill, Röhm, and Fekete published a revolutionary idea in the article &lt;a href="https://dl.acm.org/doi/10.1145/1620585.1620587" rel="noopener noreferrer"&gt;"Serializable isolation for snapshot databases."&lt;/a&gt;. It is possible to build an execution graph of all concurrent transactions. If there is a cycle in the graph, there is a resource conflict, and transactions should be cancelled except for one. The beauty is that there is no need for heavy locks.&lt;/p&gt;

&lt;p&gt;Moreover, the algorithm provides complete Serializable Snapshot Isolation (SSI). For example, one transaction calculates the user's credit balance and then wants to write a fact of a 50 USD item purchase. Meanwhile, the second transaction adds a new ledger record of &lt;code&gt;-1000 USD&lt;/code&gt; in the middle, making the balance and new payment unavailable. For decades, this kind of scenario was almost impossible to track in databases. A new record was added to or deleted from the table you recently queried in a transaction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BEGIN;

# Step 1
SELECT SUM(value) as balance FROM ledger_entries
 where user_id = 42;

# Concurrent Step 2 by another transaction
# INSERT INTO ledger_entries VALUES(-1000, 'USD');

# Step 3 - add purchase 
# Does `balance` have the right value?
IF balance &amp;gt;= 50 THEN
  INSERT INTO ledger_entries VALUES(-50, 'USD');
  # INSERT INTO purchased ...
END IF;

COMMIT;

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

&lt;/div&gt;



&lt;p&gt;This is no longer the issue with modern SQL servers implementing Cahill, Röhm, and Fekete's algorithm. With special settings, the database tracks whether the table query result &lt;code&gt;SELECT SUM(value) as balance FROM ledger_entries where user_id = 42&lt;/code&gt; has been changed by another transaction during the execution. It rolls it back if needed without any lock mechanism. &lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡ Firestore DB transaction
&lt;/h2&gt;

&lt;p&gt;The SQL algorithm performs efficiently on a single server. However, it does not scale effectively in highly distributed databases like Firestore. &lt;/p&gt;

&lt;p&gt;Firestore supports transaction isolation, but only at some level. It cannot handle the new row anomaly example. This is still a fascinating fact because &lt;code&gt;document databases&lt;/code&gt; were created without transactions in mind: store unstructured data per document and support distributed storage.&lt;/p&gt;

&lt;p&gt;Let us review a Firestore transaction example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;await db.runTransaction(async t =&amp;gt; {
    // Step 1 - read
    const userRef = db.collection('users').doc('42');
    const userDoc = await t.get(userRef);

    const subscriptionRef = db.collection('subscriptions').doc(userDoc.data.subscriptionId);
    const subscriptionDoc = await t.get(subscriptionRef);

    const ledgerEntries = await db.collection('ledger').where('status', '==', 'success').get();

    // Step 2
    // your logic

    // Step 3
    await t.update(userRef, {
      name: 'Albert'
    });
    await t.update(subscriptionRef, {
      plan: 'pro'
    });   
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, Firestore works against a snapshot per transaction, implementing the MVCC principle.&lt;/p&gt;

&lt;p&gt;Second, it automatically tracks all fetched document timestamps (versions) against concurrent changes. Similar to what we did in &lt;a href="https://dev.to/arturampilogov/concurrency-and-row-versioning-part-1-39hn"&gt;Concurrency and Row Versioning - Part 1&lt;/a&gt; with &lt;code&gt;lastUpdateTime&lt;/code&gt;, it just works out of the box, so no need to specify it explicitly. In this example, we initially fetched &lt;code&gt;userDoc&lt;/code&gt;, &lt;code&gt;subscriptionRef&lt;/code&gt;, and &lt;code&gt;ledgerEntries&lt;/code&gt;. Firestore will check if another update has changed them concurrently during the transaction application. This is also true for all fetched &lt;code&gt;ledgerEntries&lt;/code&gt;; even though we do not modify them in the transaction. Firetore, on the other hand, as mentioned, cannot track transactionally new inserts or deletes.&lt;/p&gt;

&lt;p&gt;There is a main limitation for a Firestore transaction code: all fetch operations should go before modifications. The following is incorrect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;await db.runTransaction(async t =&amp;gt; {
    // ❌ wrong, modification should go at the end of Firestore transactions
    await t.update(subscriptionRef, {
      plan: 'pro'
    }

    // ❌ wrong, read operations should go before modifications
    const doc = await db.collection('users').doc('42').get();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🏋️‍♂️ Does Firestore use locks in transactions?
&lt;/h3&gt;

&lt;p&gt;Firebase has two common scenarios in mind. &lt;/p&gt;

&lt;p&gt;The first occurs when users update the Firestore DB directly from devices via mobile and web applications. Users are expected to likely update only their data and rarely have concurrent conflicts. For mobile clients, Firestore uses a lockless optimistic concurrency approach. All fetched row versions are tracked for changes. Locking documents in a high-latency environment would cause too many data contention failures.&lt;/p&gt;

&lt;p&gt;Another scenario is when a backend updates the database. In this case, transaction conflicts can occur very often. It is unwise to make a lot of retries with row versioning. The standard mode (default) &lt;a href="https://cloud.google.com/firestore/native/docs/transaction-data-contention" rel="noopener noreferrer"&gt;uses&lt;/a&gt; a pessimistic concurrency approach with read document locks. &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%2F6mn9vbfrr4uow45u6wyn.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%2F6mn9vbfrr4uow45u6wyn.png" alt="Firstore DB standard mode" width="800" height="136"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When a transaction locks a document, it prevents other transactions, batched writes, and regular (non-transactional) writes from modifying that document. Any concurrent write operations must wait in a queue until the transaction releases its lock. If we &lt;a href="https://cloud.google.com/firestore/native/docs/resolve-latency" rel="noopener noreferrer"&gt;do not&lt;/a&gt; update the same document too frequently, this approach drastically eliminates the number of transaction retries compared to optimistic concurrency.&lt;/p&gt;

&lt;p&gt;A transaction is a powerful concept that should be used carefully. &lt;br&gt;
In the following article, we consider a solution for REST APIs to protect third-party service states against concurrent requests.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>database</category>
      <category>firebase</category>
      <category>concurrency</category>
    </item>
    <item>
      <title>Concurrency and Row Versioning - Part 1</title>
      <dc:creator>Artur Ampilogov</dc:creator>
      <pubDate>Sun, 12 Oct 2025 20:17:02 +0000</pubDate>
      <link>https://forem.com/arturampilogov/concurrency-and-row-versioning-part-1-39hn</link>
      <guid>https://forem.com/arturampilogov/concurrency-and-row-versioning-part-1-39hn</guid>
      <description>&lt;p&gt;Throughout my career, I’ve occasionally encountered a particularly tricky issue: debugging a broken application state for only a few resources. It often occurs when a user double-clicks a button, unintentionally sending multiple modification requests to the same resource. In other cases, two users might update the same record almost simultaneously.&lt;/p&gt;

&lt;p&gt;Modern APIs are designed for scale, but when multiple clients modify the same data concurrently, you inevitably face the classic problem of &lt;strong&gt;concurrent updates&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;These series will explore practical patterns to protect your system:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Concurrency and Row Versioning - Part 1 ⭐&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/arturampilogov/concurrency-and-transactional-row-versioning-part-2-2cbn"&gt;Concurrency and Transactions - Part 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/arturampilogov/concurrency-and-api-protection-24kc"&gt;Concurrency and API Protection - Part 3&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Database row versioning (optimistic concurrency)
&lt;/h2&gt;

&lt;p&gt;Each row in a database table that needs protection carries a version value. When you update a database row, you check that the version you read is current and that no one has modified it.&lt;/p&gt;

&lt;p&gt;All modern databases include a &lt;a href="https://www.postgresql.org/docs/current/datatype-datetime.html" rel="noopener noreferrer"&gt;timestamp&lt;/a&gt; or a &lt;a href="https://dev.tourl"&gt;rowversion&lt;/a&gt; column type out of the box: Postgres, MS SQL, Oracle DB, MySQL. Moreover, timestamps are also supported natively in document databases, such as MongoDB, GCP Firestore, and Supabase.&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 Row versioning in steps
&lt;/h2&gt;

&lt;p&gt;Here are the steps with an SQL example to protect a row against concurrent updates.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Read record data, including the row version&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT version as OLD_VERSION FROM users WHERE ID=1
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement the required logic to prepare the updated data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update the record only if the version has not changed.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UPDATE users
SET firstname = 'Edgar', lastname = 'Codd', version = $NEW_VERSION 
WHERE id = 1 AND version = $OLD_VERSION;
&lt;/code&gt;&lt;/pre&gt;

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

&lt;p&gt;If another concurrent request updated the same row during step 2, then step 3 will fail. The database will reject it due to the condition conflict &lt;code&gt;WHERE version = $OLD_VERSION&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This technique, also known as &lt;em&gt;Optimistic Concurrency&lt;/em&gt;, has the main benefit of &lt;em&gt;not requiring a database resource lock&lt;/em&gt; and being very light. I remember developers actively using this principle in SQL databases 15 years ago.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡ Firestore DB row versioning
&lt;/h2&gt;

&lt;p&gt;Firestore DB, an example of a NoSQL database, supports row versioning using the special metadata.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Step 1 - read
const userRef = db.collection('users').doc('1');
const doc = await userRef.get();
const oldVersion = doc.updateTime; // &amp;lt;-- get version metadata

// Step 2 - your logic

// Step 3 - conditional update
await userRef.update({
  firstname: 'Edgar',
  lastname: 'Codd'
},
{ 
  lastUpdateTime: oldVersion // &amp;lt;-- conditional update
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important things here are to recognize:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Firestore automatically sets unique &lt;code&gt;updateTime&lt;/code&gt; metadata during a document update, so we do not set it manually.&lt;/li&gt;
&lt;li&gt;Firestore allows conditional update via the special &lt;a href="https://googleapis.dev/nodejs/firestore/latest/global.html#Precondition" rel="noopener noreferrer"&gt;lastUpdateTime precondition&lt;/a&gt; check, which can be read as: &lt;code&gt;WHERE lastUpdateTime = $oldVersion&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🌍 Broad Compatibility
&lt;/h2&gt;

&lt;p&gt;Custom row versions can be used even if a database does not natively support &lt;code&gt;timestamp&lt;/code&gt; or &lt;code&gt;rowversion&lt;/code&gt; types. The only requirement is a conditional update.&lt;/p&gt;

&lt;p&gt;Timestamp can be stored as an ISO string. That is how &lt;a href="https://aws.amazon.com/blogs/database/working-with-date-and-timestamp-data-types-in-amazon-dynamodb/" rel="noopener noreferrer"&gt;Amazon DynamoDB&lt;/a&gt; manages to handle it.&lt;/p&gt;

&lt;p&gt;For optimization and fewer bits storage, it is also common to use a small integer version, incrementing it by one during a row update: &lt;code&gt;version = version + 1&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>database</category>
      <category>firebase</category>
      <category>concurrency</category>
    </item>
    <item>
      <title>Is DeepSeek’s Influence Overblown?</title>
      <dc:creator>Artur Ampilogov</dc:creator>
      <pubDate>Fri, 31 Jan 2025 13:02:17 +0000</pubDate>
      <link>https://forem.com/arturampilogov/examining-deepseeks-disruptive-influence-19hd</link>
      <guid>https://forem.com/arturampilogov/examining-deepseeks-disruptive-influence-19hd</guid>
      <description>&lt;p&gt;At the beginning of this week, the tech stock market crashed after the appearance of a new AI model called "DeepSeek." Nvidia's stock (NVDA) fell by 17%.&lt;/p&gt;

&lt;p&gt;According to the &lt;a href="https://github.com/deepseek-ai/DeepSeek-V3/blob/main/DeepSeek_V3.pdf" rel="noopener noreferrer"&gt;official paper&lt;/a&gt;, DeepSeek took only $5.6 mln to train with impressive results. This is a remarkable achievement for a large language model (LLM). In comparison, OpenAI's CEO Sam Altman &lt;a href="https://www.wired.com/story/openai-ceo-sam-altman-the-age-of-giant-ai-models-is-already-over/" rel="noopener noreferrer"&gt;admitted&lt;/a&gt; that training OpenAI GPT-4 took over $100 mln, not saying how much more.&lt;br&gt;
Some AI specialists assume that the estimation of the DeepSeek training expense is &lt;a href="https://www.wired.com/story/openai-ceo-sam-altman-the-age-of-giant-ai-models-is-already-over/" rel="noopener noreferrer"&gt;underreported&lt;/a&gt;. Nevertheless, the hidden gem is not how much it cost to train but how drastically it improved runtime requirements.&lt;/p&gt;

&lt;p&gt;Modern LLMs present a complex structure, but the number of &lt;em&gt;parameters&lt;/em&gt; is an essential metric for all deep-learning models. &lt;/p&gt;
&lt;h2&gt;
  
  
  What are AI model parameters?
&lt;/h2&gt;

&lt;p&gt;Consider the video of a snow leopard wearing a red coat on a fashion show I generated using Pika 2.1&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/39KFf_Q-B2Q"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  How does AI know what "red" is?
&lt;/h3&gt;

&lt;p&gt;Imagine creating a small neural network to say whether a given pixel is red. For programs, it is usual to present an arbitrary color with three mixed values: red, green, and blue, also known as RGB, where each value ranges from 0 to 255. For example, &lt;code&gt;(0,0,0)&lt;/code&gt; is black, &lt;code&gt;(0,204,102)&lt;/code&gt; is green, &lt;code&gt;(204, 0, 0)&lt;/code&gt; is red.&lt;/p&gt;

&lt;p&gt;For output, we will use the formula:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input 1 (red) * Weight 1 + 
Input 2 (green) * Weight 2 + 
Input 3 (blue) * Weight 3 = Output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The weights are unknown. The output should be 0 to 100, where 100 means it is definitely red, 80 is likely red, and 0 is not red at all. During training, the neural network will be passed a million examples with the expected result. The model should figure out the constant weight values that return successful results for at least 95% of the training data.&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%2F0vfyjhcwdajtmuhjkxxo.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%2F0vfyjhcwdajtmuhjkxxo.png" alt="Image description" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, the output neuron can be connected further with the following neurons, becoming an input with the pixel "redness" notion.&lt;/p&gt;

&lt;p&gt;Imagine having millions of input values for such a network, for example, representing text characters in a big PDF file, pixels of a large image, or a user prompt. A trained neural network with numerous connections between neurons and the determined weights, representing the strength of a signal, can calculate various results: understand the prompt requirements, generate a photo or text, derive a logical response, or modify a video.&lt;/p&gt;

&lt;p&gt;The actual formula is slightly more sophisticated. In addition to weights, bias variables are added to tilt the output, and the output is finally normalized to a fraction between 0 and 1. &lt;/p&gt;

&lt;p&gt;The derived constant weights and bias values are the &lt;em&gt;model parameters&lt;/em&gt;. They represent actual AI "brain" patterns.&lt;/p&gt;

&lt;h2&gt;
  
  
  How big are modern LLMs?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Open AI GPT-3, created in 2020, has 175 billion parameters. GPT-4 was never disclosed but is estimated to have 1.8 trillion parameters, with multiple models inside, about 220 billion each.&lt;/li&gt;
&lt;li&gt;Google PaLM 2, released in 2023, &lt;a href="https://www.cnbc.com/2023/05/16/googles-palm-2-uses-nearly-five-times-more-text-data-than-predecessor.html" rel="noopener noreferrer"&gt;allegedly&lt;/a&gt; has 340 billion parameters, while the modern Google Flex models might be much more significant.&lt;/li&gt;
&lt;li&gt;Meta Llama 3.2 is an open-sourced model with 90 billion parameters, but its results are not as good as those of contemporary Open AI and Google models.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most LLMs store each parameter as a floating-point number of 2 or 4 Bytes. The full GPT-4 model with an estimated 1.8 trillion parameters requires at least 3.6TB RAM to be able to run! It is the minimum theoretical requirement; additional memory is also needed for input parameters, output storage at each neuron, and some technical space.&lt;/p&gt;

&lt;p&gt;Just think of it. The model requires a cluster of expensive GPUs with lots of RAM not only to train it but also just to produce a response at runtime.&lt;/p&gt;

&lt;p&gt;Calculating massive amounts of neuron outcomes is very slow, often with many steps running repeatedly over and over. GPT-4 output speed is about 30 words per second, and the GPT-o1 reasoning model is even slower. So, when you send a request to ChatGPT, it uses a massive GPU cluster behind the scenes to process only one input. Imagine how many clusters Open AI, Google, Microsoft, xAI, Anthropic, and other AI leaders have to own or lease to process requests globally.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is about DeepSeek?
&lt;/h2&gt;

&lt;p&gt;DeepSeek made three noteworthy transformations in the AI world:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A parameter of 1 Byte reduces the main memory part requirement by half while still producing exceptional results.&lt;/li&gt;
&lt;li&gt;The model has 671 billion parameters, but only 37 billion, 1/18th of the whole network, are used during processing. The network decides which path and neuron groups to take, resulting in faster responses. Think of a real-life analog: whether a doctor, pilot, or physical scientist is better to answer the question, and not all of them at once.&lt;/li&gt;
&lt;li&gt;Being fully open-sourced.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With 671 billion parameters, DeepSeek still requires a lot of memory, more than 700 GB of RAM, to run, but it is the first open-source model to produce outcomes almost as good as the most expensive, sophisticated, and private LLMs. Some people started experimenting with local DeepSeek hosting, for example, by grouping Mac Minis into a home cluster.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1872444906851229814-195" src="https://platform.twitter.com/embed/Tweet.html?id=1872444906851229814"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1872444906851229814-195');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1872444906851229814&amp;amp;theme=dark"
  }



&lt;/p&gt;

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

&lt;p&gt;Hearing about the claimed lower model training cost, did people correctly produce the selling panic in the stock market, thinking there would be no need for so many GPU chips and clusters? Not at all.&lt;/p&gt;

&lt;p&gt;First, now that enthusiasts and businesses know running a local and private ChatGPT analog is possible, they will likely order new and small Nvidia clusters created &lt;a href="https://blogs.nvidia.com/blog/2024-gtc-keynote/" rel="noopener noreferrer"&gt;specifically&lt;/a&gt; for these needs.&lt;/p&gt;

&lt;p&gt;Second, more sophisticated patterns require more model parameters, which, as shown above, demand enormous computer resources. A human brain has about 100 trillion connections between neurons, while the most significant AI models now operate with only a couple of trillion. Future models will require much more RAM to operate. Also, individuals and businesses are increasingly embracing AI benefits.&lt;/p&gt;

&lt;p&gt;It is not going to change, and the AI chip market is only going to grow.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>deepseek</category>
      <category>nvidia</category>
      <category>openai</category>
    </item>
    <item>
      <title>React is not about performance</title>
      <dc:creator>Artur Ampilogov</dc:creator>
      <pubDate>Wed, 31 Jan 2024 20:57:35 +0000</pubDate>
      <link>https://forem.com/arturampilogov/react-is-not-about-performance-16bg</link>
      <guid>https://forem.com/arturampilogov/react-is-not-about-performance-16bg</guid>
      <description>&lt;p&gt;Key Takeaways&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React is the most popular JavaScript rendering framework.&lt;/li&gt;
&lt;li&gt;React full-stack frameworks, like Next.JS and Remix, are recommended for usage by the React team.&lt;/li&gt;
&lt;li&gt;React full-stack frameworks cannot work without JavaScript which violates REST principles and affects devices performance.&lt;/li&gt;
&lt;li&gt;HTML duplicated data appears when React Server Components are in use.&lt;/li&gt;
&lt;li&gt;By default React adds extra loading to user devices with unnecessary re-rendering.&lt;/li&gt;
&lt;li&gt;Optimizing React code is a manual procedure and that is error prone.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Facebook presented React to the public in &lt;a href="https://github.com/facebook/react/releases/tag/v0.3.0"&gt;2013&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The project immediately gained popularity, simplifying web application development with the next core ideas:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UI components are written in the &lt;a href="https://legacy.reactjs.org/docs/introducing-jsx.html"&gt;JSX syntax&lt;/a&gt;, which is similar to the conventional HTML.&lt;/li&gt;
&lt;li&gt;Usual JavaScript statements (if, switch, &amp;amp;&amp;amp;, etc) and expressions can be used inside UI components declaration. A developer does not need to learn new attributes, like "ngIf" in Angular, "v-if" in Vue.JS, "{#if} {:else if …}" in HandleBars and Svelte.&lt;/li&gt;
&lt;li&gt;The data flow implements the &lt;a href="https://legacy.reactjs.org/blog/2014/05/06/flux.html"&gt;Flux architecture&lt;/a&gt; and is unidirectional: changes are populated from top components to their children.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After more than 10 years, React still has the &lt;a href="https://npmtrends.com/@angular/core-vs-lit-vs-react-vs-solid-js-vs-svelte-vs-vue"&gt;highest number of downloads&lt;/a&gt; among JavaScript web libraries. It is the &lt;a href="https://insights.stackoverflow.com/trends?tags=reactjs%2Cvue.js%2Cangular%2Csvelte%2Cangularjs%2Cvuejs3"&gt;most discussed web framework&lt;/a&gt; in StackOverflow and is used in &lt;a href="https://w3techs.com/technologies/details/js-react#:~:text=React%20is%20used%20by%204.3,is%203.5%25%20of%20all%20websites"&gt;3.5% of all websites&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ferfpyh3o2x1zfwvrdpxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ferfpyh3o2x1zfwvrdpxg.png" alt="Image description" width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is, though, a negative point. All this time, React websites produce overhead on client devices.&lt;/p&gt;

&lt;p&gt;This is still true, even after introducing such optimizations as improving the React engine speed and page interactions with the &lt;a href="https://www.youtube.com/watch?v=ZCuYPiUIONs&amp;amp;t=71s"&gt;Fiber&lt;/a&gt; algorithm, reducing JavaScript file sizes, code splitting, and implementation of &lt;a href="https://deno.com/blog/intro-to-islands"&gt;islands&lt;/a&gt; using component streaming and selective hydration.&lt;/p&gt;

&lt;p&gt;Moreover, the recent optimizations were done with high competition pressure from other projects (&lt;a href="https://dev.tourl"&gt;Angular&lt;/a&gt;, Svelte, VueJS, Marko), and especially from those either supporting JSX syntax or optimizing the work with the React library (Preact, Qwik, Remix, Astro). &lt;/p&gt;

&lt;p&gt;Let me describe React performance issues from an end-user perspective.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript dependency
&lt;/h2&gt;

&lt;p&gt;Representational State Transfer, or REST for short, states that Code-on-Demand (JavaScript) should be &lt;a href="https://ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm"&gt;optional&lt;/a&gt; in web pages and applications. This concept is important for many devices working without JavaScript or having low processing power, as well as for search engine website crawlers.&lt;/p&gt;

&lt;p&gt;React always supported rendering JSX components to HTML via the &lt;a href="https://github.com/facebook/react/releases/tag/v0.12.0"&gt;renderToString&lt;/a&gt; method.  So, it is possible to render a React page on the server and return a response to the devices with a lack of JavaScript. Then, it is feasible to add interactivity to the client side supporting JavaScript with the “render” method (now separated into “renderRoot” and “hydrateRoot”). The problem with that approach is that the whole flow implementation was solely put on developers. This led to the point where many programmers skipped the backend HTML generation and built pure Client JavaScript React applications using the recommended &lt;a href="https://www.npmjs.com/package/create-react-app"&gt;crate-react-app&lt;/a&gt; package.&lt;/p&gt;

&lt;p&gt;When JavaScript was disabled in a browser, users usually saw a blank page.The reason is that the React NPM package has always been just a library, not a full framework. Only 10 years after the React release, the team added the &lt;a href="https://twitter.com/acdlite/status/1617611126514266112"&gt;recommendation&lt;/a&gt; to the official documentation to use one of the frameworks with React Server Side Rendering support, like Next.JS or Remix.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg5r2kjhz3oic5j86yr5n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg5r2kjhz3oic5j86yr5n.png" alt="Image description" width="800" height="276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Though it might look like the JavaScript dependency problem is finally resolved in the development community, this is not the case at the time of writing. React recently introduced the ability to &lt;a href="https://react.dev/reference/react-dom/server/renderToPipeableStream"&gt;stream the page content&lt;/a&gt; from the server to a client’s browser in parts, and it requires JavaScript to work.&lt;/p&gt;

&lt;p&gt;The added streaming optimization resolves the next problem. Some components require data to be fetched from external resources like a database, and it delays rendering. The solution, introduced in &lt;a href="https://dev.to/ryansolid/server-rendering-in-javascript-optimizing-performance-1jnk"&gt;MarkoJS&lt;/a&gt; in 2014, is to separate “immediately” rendered components, with static data, from “suspended” components waiting for dynamic data from external resources. The page layout with “immediate” components will be streamed to the browser, while placeholders (usually with spinners or skeletons) will be preserved for “suspended” components.&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;main&amp;gt;
  &amp;lt;aside&amp;gt;
    &amp;lt;!--Sidebar --&amp;gt;
   &amp;lt;/aside&amp;gt;

  &amp;lt;!-- Suspense PLACEHOLDER--&amp;gt;
  &amp;lt;div id="post_placeholder"&amp;gt;
    &amp;lt;!-- Spinner --&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/main&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once a “suspended” component is ready, it is streamed back to the client in the same page request (long HTTP connection).&lt;/p&gt;

&lt;p&gt;How is it possible to post-stream and update HTML in the middle of the page without JavaScript? Currently, it is not supported. React sends HTML code for the suspended component with a small &lt;a href="https://github.com/reactwg/react-18/discussions/37"&gt;script code&lt;/a&gt; to find the placeholder and replace it:&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;!-- New component --&amp;gt;
&amp;lt;article hidden id="post"&amp;gt;
  &amp;lt;h1&amp;gt;Post header&amp;lt;/h1&amp;gt;
  &amp;lt;p&amp;gt;Post text&amp;lt;/p&amp;gt;
&amp;lt;/article&amp;gt;

&amp;lt;!-- Script to replace the placeholder with the new component --&amp;gt;
&amp;lt;script&amp;gt;
  const laterStreamedComponent = document.getElementById('post');
  document.getElementById('post_placeholder').replaceChildren(laterStreamedComponent);
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once all suspended components are sent, the connection with the client can be terminated.&lt;/p&gt;

&lt;p&gt;The idea looks good, but what happens when a browser without JavaScript support requests such a page? The infinite spinner or a placeholder skeleton will be displayed for the suspended components. This is a reality for the latest Next.JS version at the time of writing (v14.0.3). Here is the &lt;a href="https://react-drawbacks.vercel.app/"&gt;Suspense demo&lt;/a&gt; deployed to Vercel (&lt;a href="https://github.com/ArturAmpilogov/react-drawbacks/tree/main/nextjs-v14/src/app/suspense"&gt;source code)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsk6bz3v9iyhy9er0ox8x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsk6bz3v9iyhy9er0ox8x.png" alt="Image description" width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the default behavior of the current Next.JS implementation, where all components are server components by &lt;a href="https://nextjs.org/docs/app/building-your-application/rendering/server-components#using-server-components-in-nextjs"&gt;default&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It will be better to care about devices with a lack of JavaScript support. For example, during almost every big presentation, Rich Harris, the creator of Svelte, &lt;a href="https://youtu.be/0bog8-Ay7CU?t=12759"&gt;shows&lt;/a&gt; how Svelte will work without JavaScript.&lt;/p&gt;

&lt;p&gt;Suspense also cannot improve slow server responses. The Vercel site, which is built on its main product - Next.JS, often shows bad user experience with slow data fetching.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1734615967630536746-429" src="https://platform.twitter.com/embed/Tweet.html?id=1734615967630536746"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1734615967630536746-429');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1734615967630536746&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  Web page size
&lt;/h2&gt;

&lt;p&gt;For many years React code by default was bundled into a huge delivery package resulting in a thick web client application. When a user opened any page, the whole JavaScript application was downloaded, and then based on the URL React rendered a specific branch (page). Often these applications took several megabytes to download before rendering could start.&lt;/p&gt;

&lt;p&gt;In 2018, the React team added in-box support for code splitting with the &lt;a href="https://github.com/reactjs/rfcs/blob/gaearon-patch-2/text/0000-lazy.md"&gt;lazy&lt;/a&gt; function, which developers should manually call. &lt;/p&gt;

&lt;p&gt;This approach was also used in routing frameworks like &lt;a href="https://reactrouter.com/"&gt;react-router-dom&lt;/a&gt;, created by Remix authors, and allowed an application to be split into smaller bundles based on the visited URL. &lt;br&gt;
Currently, Remix and Next.JS create per-page bundles automatically at compile time.&lt;/p&gt;

&lt;p&gt;You might think that Server Side Rendering should totally eliminate client bundle problems, but that is not the case with React. The architecture with Virtual DOM and unidirectional rendering flow requires React to recalculate the changes from the top changed component down to all its leaves. To render a component, all the related source code should be presented either as a JavaScript function or with the latest addition of &lt;a href="https://nextjs.org/docs/app/building-your-application/rendering/server-components"&gt;Server Components&lt;/a&gt;, in a special JSON format. &lt;/p&gt;

&lt;p&gt;It is not possible to reuse any HTML code as the source of truth, which leads to data duplication. First, the rendered HTML page is delivered to a browser, and second, the same duplicated content is delivered as part of the JavaScript block (a function or a JSON). The second step, called hydration, will allow the framework to react to user interaction events and render changes in response.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://react-drawbacks.vercel.app/double-data"&gt;second demo&lt;/a&gt;, the Poem component consists purely of static data. There is a client component that wraps and toggles the poem visibility:&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;ClientComponentWrapper&amp;gt;
    &amp;lt;Poem /&amp;gt;
&amp;lt;/ClientComponentWrapper&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please notice that the poem appears twice in the delivered content to a browser: HTML and JavaScript. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8clzzx1jypemp9b3kyns.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8clzzx1jypemp9b3kyns.png" alt="Image description" width="800" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the same time, Next.JS was smart enough not to include static parent HTML in the JSON script. This React limitation led to the official Next.JS recommendation &lt;a href="https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#moving-client-components-down-the-tree"&gt;To move Client Components Down the Tree&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The suggestion does not work once you have the common scenario with the React context client component wrapping all other page elements, for example, with a top-level user sign-in state:&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;UserSignInContext&amp;gt;  &amp;lt;!-- Top level client component --&amp;gt;
   &amp;lt;Navigation /&amp;gt; &amp;lt;!-- depends on the user sign in status --&amp;gt;
   &amp;lt;MainContent /&amp;gt; &amp;lt;!-- depends on the user sign in status --&amp;gt;
&amp;lt;/UserSignInContext&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are better-optimized solutions. &lt;/p&gt;

&lt;p&gt;Miško Hevery, creator of Angular and Qwik, &lt;a href="https://youtu.be/LbMRs7l4czI?t=4021"&gt;re-uses HTML data&lt;/a&gt; in Qwik as much as possible during client components rendering. This is achieved by a light JSON storage with references to the existing HTML elements. No data duplication. The same concept is used in the &lt;a href="https://deno.com/blog/intro-to-islands"&gt;Fresh&lt;/a&gt; framework based on Preact and Deno.&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;!--qv q:id=0 --&amp;gt;
    &amp;lt;p&amp;gt;Hello Qwik&amp;lt;/p&amp;gt;
&amp;lt;!--/qv--&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, Qwik automatically divides components into the &lt;a href="https://qwik.builder.io/docs/concepts/progressive/"&gt;smallest possible chunks&lt;/a&gt;, and no JavaScript client component is executed until a user interacts with some part that requires it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Default unoptimized behaviors
&lt;/h2&gt;

&lt;p&gt;Once React receives a change in a top component, it will re-execute all child components, even those with unchanged properties. All local variables of the components will be recreated, including functions. The &lt;a href="https://react-drawbacks.vercel.app/tree-rerender"&gt;Tree Rerender&lt;/a&gt; demo shows what happens with the table function components once an unrelated input field is changed (&lt;a href="https://github.com/ArturAmpilogov/react-drawbacks/tree/main/nextjs-v14/src/app/tree-rerender"&gt;source code&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67sskkdzje8ef0carv5s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67sskkdzje8ef0carv5s.png" alt="Image description" width="800" height="679"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The reality is that by default React burns users’ CPUs. &lt;/p&gt;

&lt;p&gt;The proposed solution by React is to manually wrap all related components into the &lt;a href="https://react.dev/reference/react/memo"&gt;memo&lt;/a&gt; function, local functions into “useCallback” function-hook, and local state data in “useMemo” function-hook. This procedure is tedious and error-prone.&lt;/p&gt;

&lt;p&gt;The alternative to React hooks is the Signals technology, which precisely executes only the changed dependent components and provides automatic memoization. SolidJS, Preact, Qwik, Svelte, and Angular use &lt;a href="https://vuejs.org/guide/extras/reactivity-in-depth.html"&gt;Signals&lt;/a&gt;. While the React team has &lt;a href="https://dev.to/this-is-learning/react-vs-signals-10-years-later-3k71"&gt;reasons&lt;/a&gt; not to switch to it, the problem of the unnecessary CPU load of user devices is still here. The issue might be resolved this year with the &lt;a href="https://www.youtube.com/watch?v=lGEMwh32soc&amp;amp;embeds_referring_euri=https%3A%2F%2Fdev.to%2F&amp;amp;feature=emb_imp_woyt"&gt;React Forget&lt;/a&gt; compiler, 11 years later after the React release.&lt;/p&gt;

&lt;p&gt;The current situation is that React forces developers to do the next manual optimizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Split code manually by the usage of lazy function and Suspense wrappers.&lt;/li&gt;
&lt;li&gt;Accurately operate with “memo”, “useMemo”, “useCallback” functions.&lt;/li&gt;
&lt;li&gt;Manually specify which component is the client one by adding &lt;a href="https://github.com/reactjs/rfcs/blob/main/text/0188-server-components.md#conventions-for-serverclient-components"&gt;use client&lt;/a&gt; directive.&lt;/li&gt;
&lt;li&gt;Use “startTransitiom” and “useDeferredValue” to help React &lt;a href="https://react.dev/reference/react/startTransition"&gt;faster&lt;/a&gt; update the UI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In comparison, Qwik does the best possible &lt;a href="https://www.youtube.com/watch?v=tJY1zrW35q8"&gt;automatic optimization&lt;/a&gt; for all previously mentioned cases out of the box. &lt;/p&gt;

&lt;p&gt;There are additional optimizations that reduce JavaScript execution. Qwik eliminates the Hydration step with the &lt;a href="https://qwik.builder.io/docs/concepts/resumable/"&gt;Resumability&lt;/a&gt;. Svelte makes direct DOM updates and does not use Virtual DOM structure, drastically reducing CPU and Memory usage. Astro does not load JavaScript until it is specified by a developer. &lt;/p&gt;

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

&lt;p&gt;Today, React is the most popular JavaScript web framework. At the same time, its recommended usage produces many performance drawbacks on user devices. It will be great to see from React the CPU and memory usage reduction of hundreds of millions, or even billions, user devices worldwide as a priority.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>performance</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Programming language, don't make me think</title>
      <dc:creator>Artur Ampilogov</dc:creator>
      <pubDate>Fri, 15 Sep 2023 18:47:45 +0000</pubDate>
      <link>https://forem.com/dev-aces/programming-language-dont-make-me-think-5b3g</link>
      <guid>https://forem.com/dev-aces/programming-language-dont-make-me-think-5b3g</guid>
      <description>&lt;p&gt;Steve Krug published the famous book "Don't Make Me Think" in 2000 and gathered well-known ideas about Web usability. Authors of programming languages often lower the priority of simplicity or have to implement far-from-ideal solutions due to historical restrictions.&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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft0nyvm82jhvnpv588max.jpg" 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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft0nyvm82jhvnpv588max.jpg" alt="Dont' make me think"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to measure complexity?
&lt;/h2&gt;

&lt;p&gt;Maintaining a product requires more reading code than writing. Hence, &lt;strong&gt;the code legibility is more important than its writing speed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One way to measure code complexity is to count &lt;strong&gt;how many terms a developer should hold in memory&lt;/strong&gt; to get a result.&lt;/p&gt;

&lt;p&gt;Another one is &lt;strong&gt;how much time it requires to understand the notion or to revise it&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data structures and operations
&lt;/h2&gt;

&lt;p&gt;In short, programming is all about operations on data. To allocate memory for a 32-bit integer in statically typed languages, we can declare its type and assign a name to the memory block.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// C, C++, Java, C#
int x;

// Ada
X : Integer;

// TypeScript
let x: number;

// Rust
let x: i32;

// Go
var x int32
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a way to infer a type by a compiler or even calculate the memory size and data structure at runtime. This approach is used in JavaScript, Python, and Ruby.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// JavaScript
let x;

// Python
x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The untyped version requires additional time for a developer to figure out the argument structures. Consider the function declared in Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def display(person, age, payment)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Is &lt;code&gt;person&lt;/code&gt; an object, is &lt;code&gt;age&lt;/code&gt; a number, is &lt;code&gt;payment&lt;/code&gt; represented by a boolean, number, or money?&lt;/p&gt;

&lt;p&gt;Compare the same function written in C# that immediately gives answers about the structures:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void Display(string person, int age, decimal payment)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A statically typed language usage also has a vital benefit over a dynamic language - more error checks at compilation time. It is better to find errors at the earliest stage than make them to be discovered by users.&lt;/p&gt;

&lt;h3&gt;
  
  
  Assignment operator
&lt;/h3&gt;

&lt;p&gt;Most modern programming languages implement the assignment operator as the equal &lt;code&gt;=&lt;/code&gt; sign.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int x;
x = 1;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A fresh programming student trying to understand these statements may ask: "Is it possible to write &lt;code&gt;y = a*x^2 + b*x +c&lt;/code&gt; in code similar to the Math notation?" Although students   have been taught for many years that &lt;code&gt;=&lt;/code&gt; sign represents equation in Math, the answer is "no" for most of the programming languages.&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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faadtzzg9xtbaz7if3gcr.jpg" 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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faadtzzg9xtbaz7if3gcr.jpg" alt="Math meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In C, C++, Java, C#, PHP, Python, Ruby, Go, and Rust, the equal sign &lt;code&gt;=&lt;/code&gt; means an assignment. Pascal and Ada languages use the &lt;code&gt;:=&lt;/code&gt; sign, which at least is not a common Math symbol in schools (in Math, it is used as the equal by definition sign, in addition to &lt;code&gt;≡&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;But what does the assignment actually mean? The assignment operator in modern languages has two ideas behind it.&lt;/p&gt;

&lt;h4&gt;
  
  
  Value assignment
&lt;/h4&gt;

&lt;p&gt;The first one is called &lt;code&gt;value assignment&lt;/code&gt; and usually uses &lt;code&gt;deep copy&lt;/code&gt; of memory blocks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// C, C++, Java, C#
int x = 1; 
int y = x; // Deep copy of x to y
x = 2; // Change x
y; // y has the old value 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Reference assignment
&lt;/h4&gt;

&lt;p&gt;The second one is &lt;code&gt;reference assignment&lt;/code&gt;, which always uses the shared block of memory between variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// C#
int[] array1 = { 1, 2, 3 }; // Array of 3 integers

int[] array2 = array1; // Reference assignment

array1[0] = 9; // Change the first element in array1
array1; // { 9, 2, 3 }
array2; // { 9, 2, 3 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Changes in &lt;code&gt;array1&lt;/code&gt; immediately affects &lt;code&gt;array2&lt;/code&gt; as both variables point to the same memory location.&lt;/p&gt;

&lt;p&gt;Java and C# oblige developers to remember what assignment behavior is associated with a structure. Moreover, C++ and C# allow to override the &lt;code&gt;=&lt;/code&gt; operator per object, and Java can achieve the same result by overriding &lt;code&gt;equals&lt;/code&gt; method. It is only possible to be sure about the result of the equality statement in these languages once the type implementation is reviewed.&lt;/p&gt;

&lt;p&gt;As we just saw, C# uses a memory reference approach for array assignment to reduce memory allocation. Go language, instead, uses deep copy for arrays.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Go
var array1 [3]int // Array of length 3
array1 = [3]int{ 1, 2, 3 } // Fill the array with numbers

var array2 [3]int // Array of length 3
array2 = array1 // Deep copy from array1 to array2

array1[0] = 9 // Change the first element in array1
array1; // { 9, 2, 3 }
array2; // { 1, 2, 3 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A tiny declaration change by removing array size in brackets (&lt;code&gt;var array1 []int&lt;/code&gt; and &lt;code&gt;var array2 []int&lt;/code&gt;) leads to &lt;code&gt;array slicing&lt;/code&gt; in Go. The result will be the opposite and the same as with C# reference array assignment.&lt;br&gt;
Go language forces programmers to pay attention to a number in square brackets.&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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffj66yb26lhejaf6swi6z.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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffj66yb26lhejaf6swi6z.png" alt="Grandma"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ruby authors consider all data structures as objects. Even primitive types, like integers, are objects, so everything is linked via a memory reference by default. The result for arrays will be similar to C# and Go slices. Some might expect the same behavior for Ruby integers, but instead, it will be a usual deep copy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Ruby
a = 1
b = a # Deep copy instead of referencing
a = 3
puts a # Holds 3
puts b # Holds the original value 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Passing an argument
&lt;/h2&gt;

&lt;p&gt;Language authors made three options to path an argument to a function.&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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fryxieciy2lh0w5dy1o74.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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fryxieciy2lh0w5dy1o74.png" alt="Big brain"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first one is a &lt;code&gt;pass by reference&lt;/code&gt; so that you can reassign a new value to the outer argument inside the function. &lt;br&gt;
The second is called &lt;code&gt;pass by value&lt;/code&gt;, and there are two options. One is to copy a reference to the memory address, you will not be able to reassign the value for an outer argument but will be able to modify the internals of the shared object. Another one is to make a deep copy of an argument so the changes inside the function will not affect the changes of a passed argument.&lt;/p&gt;

&lt;p&gt;Passing an argument does not fully correlate with the variable assignment &lt;code&gt;=&lt;/code&gt; behavior. Languages presented new symbols to differentiate the operation: &lt;code&gt;ref&lt;/code&gt; keyword. &lt;code&gt;&amp;amp;&lt;/code&gt; and &lt;code&gt;*&lt;/code&gt; signs. Many programmers find the latest two very confusing, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if(*(struct foo**)deque_get(deq, i) != NULL &amp;amp;&amp;amp;
    (*(struct foo**)deque_get(deq, i))-&amp;gt;foo &amp;gt;= 1) {
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even for experienced engineers, it isn't easy to read.&lt;/p&gt;

&lt;p&gt;One may argue that large statements with many terms are relevant only to old languages, like C. Consider the number of terms for a property declaration in modern C#:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ReadOnly(true)]
internal required override string Prop { get; init; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Method calls
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fb25rhzve0j8f64tk5oez.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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb25rhzve0j8f64tk5oez.png" alt="Wrong parameter orders meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Modern frameworks widely use function arguments. Here is a common approach to start a Web server in Go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http.ListenAndServe(":3000", nil)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By reading this code you may guess that the first argument is a port number, but what about the second? Only after inspecting the function you can find out that it is a special controller, and if you pass &lt;code&gt;nil&lt;/code&gt; a default one will be used.&lt;/p&gt;

&lt;p&gt;A common JavaScript example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let obj = {a: { b: { c: 1 }}}
JSON.stringify(obj, null, 2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Can a programmer know what &lt;code&gt;null&lt;/code&gt; represents there and &lt;code&gt;2&lt;/code&gt; without looking at the specification? (Answer: null is passed as an empty replacer, 2 is indentation size)&lt;/p&gt;

&lt;p&gt;You might create a function similar to the next one, which also raises questions about the arguments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func("John", true, null, 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some IDEs, like JetBrains family, immediately show the names of the arguments, but programmers like to use other IDEs as well.&lt;br&gt;
Certain languages allow to rewrite the code with named arguments and even rearrange them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func(id: 1, name:"John", approved: true, email: null)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That approach is optional and many developers do not use it. The better solution for readability would be to oblige structural usage in all function calls, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func({
  id: 1,
  name: "John", 
  approved: true,
  email: null
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  File search and jumps
&lt;/h2&gt;

&lt;p&gt;Modern software development and modern frameworks compel to create complex project structures.&lt;/p&gt;

&lt;p&gt;Try to count how many times you need to jump between files to understand the logic implementation. Are those files far away from each other and in different packages? Do you need to jump to a file to figure out some data structure, or can it be read immediately? Is it possible to declare types in the same file at the top location to simplify the reading? &lt;/p&gt;

&lt;p&gt;If you do not write much code it is possible to view &lt;a href="https://www.twitch.tv/programming" rel="noopener noreferrer"&gt;live programming streams&lt;/a&gt; and check how many context switches happens during file jumps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Complexity
&lt;/h2&gt;

&lt;p&gt;I can provide many more examples, like breaking the reading flow in Go with &lt;code&gt;=&lt;/code&gt; and &lt;code&gt;:=&lt;/code&gt; operators, hidden importance  of &lt;code&gt;=&lt;/code&gt; sign and &lt;code&gt;hashCode&lt;/code&gt; overrides in Java and C#, JavaScript &lt;code&gt;call&lt;/code&gt;, &lt;code&gt;apply&lt;/code&gt; and &lt;code&gt;bind&lt;/code&gt; function calls, etc. The idea stays the same - how many terms a person needs to find, hold in memory to get the result, and how much time it requires to revise a term.&lt;/p&gt;

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

&lt;p&gt;Popular programming languages made or applied revolutionary changes at some time. C language authors drastically simplified code writing and application support in comparison to programming in assembler. The default compilation result in C is still called &lt;code&gt;a.out&lt;/code&gt; or &lt;code&gt;assembly output&lt;/code&gt;. Java simplified working with memory via garbage collection. C# simplified Java statements and introduced Language Integrated Query. Go appeared as a simple alternative to C++ for network and console applications. Rust raised the bar of application stability and security. JavaScript, Python, and Ruby have low learning barriers. &lt;br&gt;
Language authors are restricted by previous versions and styles. Nevertheless, it will be great to see new language versions or new programming languages, reducing reading complexity as a major factor.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The feature missed in C++, Java, C#, PHP, Python, Ruby and JavaScript</title>
      <dc:creator>Artur Ampilogov</dc:creator>
      <pubDate>Sun, 10 Sep 2023 19:32:35 +0000</pubDate>
      <link>https://forem.com/arturampilogov/the-feature-missed-in-c-java-c-and-python-3j0a</link>
      <guid>https://forem.com/arturampilogov/the-feature-missed-in-c-java-c-and-python-3j0a</guid>
      <description>&lt;p&gt;Real objects and notions in our lives have some constraints. The height of a person cannot be a negative number, the same as age. An infant in international airlines is a baby under 2 years old. A TCP/IP port on any device cannot be a number larger than 65535. &lt;/p&gt;

&lt;p&gt;Programming languages, like C, C++, Java, C#, PHP, Python, Ruby, and JavaScript, typically would imply the usage of a wide range of built-in types for such purposes: integer, float, and decimal. In this article, I will review an old language feature that can improve type declaration for the mentioned cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Range constraints
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Temperature
&lt;/h3&gt;

&lt;p&gt;The minimum temperature in Celsius degrees has a constant value equal to -273.15. &lt;/p&gt;

&lt;p&gt;In 1972, in the book "Structured Programming", three well-known computer scientists mentioned an interesting approach to working with such constraints:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;All structured data must in the last analysis be built up from unstructured components, belonging to a primitive or unstructured types. (...)&lt;br&gt;
Although these primitive types are theoretically adequate for all purposes, here are strong practical reasons for encouraging a programmer to define his own unstructured types, both to clarify his intentions about the potential range of values of a variable, and the interpretation of each such value; and to permit subsequent design of an efficient representation.&lt;br&gt;
(...) Such a type is said to be an enumeration, and we suggest a standard notation for the name of the type and associating a name with each of its alternative values.&lt;br&gt;
&lt;code&gt;type suit = (club, diamond, heart, spade);&lt;/code&gt;&lt;br&gt;
(...)&lt;br&gt;
&lt;code&gt;type year = 1900 .. 1960;&lt;/code&gt; &lt;br&gt;
&lt;code&gt;type coordinate = 0 .. 1023;&lt;/code&gt;&lt;br&gt;
(...) We therefore introduce the convention that a .. b stands for the inline range of values between a and b inclusive. This is known as subrange of the type to which a and b belong, (...)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ole-Johan Dahl, Edsger W. Dijkstra, C.A.R. Hoare, Structured Programming, A.P.I.C. Studies in Data Processing, No. 8, 1972, p.97&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pascal, Modula-2, Delphi, and Ada support &lt;code&gt;custom unstructured (primitive) types&lt;/code&gt;. For example, in &lt;a href="https://learn.adacore.com/courses/Ada_For_The_CPP_Java_Developer/chapters/05_Type_System.html#language-defined-types"&gt;Ada&lt;/a&gt; the temperature type can be declared as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;subtype TemperatureCelsius is Float range -273.15 .. Float'Last;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where &lt;code&gt;Float'Last&lt;/code&gt; is the maximum Float number.&lt;/p&gt;

&lt;h3&gt;
  
  
  PassengersNumber
&lt;/h3&gt;

&lt;p&gt;Airline businesses may allow to purchase of tickets for a traveling group having a maximum of 10 persons in one transaction. Instead of using an integer type, it is more suitable to specify a custom type in Ada with compile and runtime checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type PassengersNumber is range 1 .. 10;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Email address
&lt;/h3&gt;

&lt;p&gt;An email address string input may have a constraint to be required and less or equal to 320 characters in length. In Ada, it is possible to define a new type for that purpose as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type EmailAddress is String (1 .. 320);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also makes code more readable when variables do not have full names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String cc;
String body;
// vs
EmailAddress cc;
EmailBody body;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Type predicate
&lt;/h3&gt;

&lt;p&gt;For more complex logic requiring a function check, for example, declaring a type for the standard &lt;a href="https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml"&gt;HTTP client errors codes&lt;/a&gt; (4XX) it is possible to use a &lt;a href="http://www.ada-auth.org/standards/12rat/html/Rat12-2-5.html"&gt;static predicate&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;subtype HTTPClientErrorCode is Integer with
  Static_Predicate =&amp;gt; 
    HTTPClientErrorCode in 400 .. 418 | 421 .. 429 | 431 | 451;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Strong typing
&lt;/h2&gt;

&lt;p&gt;One more important concept is lack of implicit conversion between types, also known as &lt;a href="https://learn.adacore.com/courses/Ada_For_The_CPP_Java_Developer/chapters/05_Type_System.html#strong-typing"&gt;strong typing&lt;/a&gt;. For example, adding a &lt;code&gt;Float&lt;/code&gt; value to a &lt;code&gt;TemperatureCelsius&lt;/code&gt; value in Ada will result in an error.&lt;/p&gt;

&lt;h2&gt;
  
  
  The missed feature
&lt;/h2&gt;

&lt;p&gt;Many modern languages after decades of improvements still do not support such an important feature, it is possible only to &lt;em&gt;mimic&lt;/em&gt; the behavour: &lt;a href="https://www.youtube.com/watch?v=gV7jhTMYkKc&amp;amp;si=e7HpfuPoLsLHqHOP"&gt;C++&lt;/a&gt;, &lt;a href="https://stackoverflow.com/questions/5604713/creating-my-own-integer-object-in-python"&gt;Python&lt;/a&gt;, &lt;a href="https://stackoverflow.com/questions/19443024/is-it-possible-to-create-my-own-primitive-datatype-in-java-like-int-float-doub"&gt;Java&lt;/a&gt;. It will be great for many developers to be able to create custom primitive types in an easy way.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>cpp</category>
      <category>java</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Evolution of C# (videos)</title>
      <dc:creator>Artur Ampilogov</dc:creator>
      <pubDate>Wed, 06 Sep 2023 19:11:46 +0000</pubDate>
      <link>https://forem.com/arturampilogov/evolution-of-c-videos-okl</link>
      <guid>https://forem.com/arturampilogov/evolution-of-c-videos-okl</guid>
      <description>&lt;h3&gt;
  
  
  #1 Intro
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/yuoSDwtdC90"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  #2 Types
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/A6-c0vYkgLM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  #3 Instances
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/kVpFGCY0UNs"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  #4 Strings
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/CIFSDqqQUoU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  #5 Propeties
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/dpRWQ_qm3uk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  #5 Methods
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/G_wsUCZ6UiE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  #6 LINQ and ranges
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/vcRcnnOi1QI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  #8 Pattern matching
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/I4gNM5ZxyfQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  #9 Nullability
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/yBArEZ7Zw6c"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  #10 More
&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/5uenMmnGO0s"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>programming</category>
      <category>dotnet</category>
      <category>evolution</category>
    </item>
    <item>
      <title>The state of modern Web development and perspectives on improvements</title>
      <dc:creator>Artur Ampilogov</dc:creator>
      <pubDate>Thu, 24 Aug 2023 15:19:39 +0000</pubDate>
      <link>https://forem.com/arturampilogov/the-state-of-modern-web-development-and-perspectives-on-improvements-51nl</link>
      <guid>https://forem.com/arturampilogov/the-state-of-modern-web-development-and-perspectives-on-improvements-51nl</guid>
      <description>&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WWW is built on top of REST principles.&lt;/li&gt;
&lt;li&gt;Modern Web development violates REST principles.&lt;/li&gt;
&lt;li&gt;Pure HTML is not suitable for modern web development.&lt;/li&gt;
&lt;li&gt;HTML can be improved with declarative fetch requests, DOM block replacements, and loading code on demand. &lt;/li&gt;
&lt;li&gt;WASM can replace JavaScript in browsers when it provides more functionality to the runtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Website development has seen multiple approaches during the 23 years of the World Wide Web's (WWW) existence. In this article, I review the principles of WWW, the current state, and the problems of modern Web development. Ultimately, I will present multiple proposals to improve Web development considerably.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resource representation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Standardizing World Wide Web
&lt;/h3&gt;

&lt;p&gt;In 1988 a remarkable event happened in the World. Engineers connected European networks with the North American continent via Internet Protocol (IP). The Internet immediately received growth in independent interconnected networks, mostly between scientific institutes. &lt;/p&gt;

&lt;p&gt;Tim Berners-Lee, a British scientist at CERN, saw high demand for communication standardization and, in 1989, invented the World Wide Web (WWW). The work included the standard for HTML as markup language to present the information, HTTP protocol to send and receive data, and the Web client to communicate with servers and process the markup language.&lt;/p&gt;

&lt;p&gt;Roy Thomas Fielding was working on the HTTP protocol improvements and, in 2000, gathered WWW and HTTP ideas in his famous dissertation &lt;a href="https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm" rel="noopener noreferrer"&gt;Architectural Styles and the Design of Network-based Software Architectures&lt;/a&gt;. Chapter 5 contains the essential principles under the “Representational State Transfer” name, or REST for short, which includes the following points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is the &lt;strong&gt;client-server architecture&lt;/strong&gt; where web clients (browsers, robots) communicate with servers.&lt;/li&gt;
&lt;li&gt;The communication must be &lt;strong&gt;stateless&lt;/strong&gt; in nature. Every request from a client should contain all the required information to process the request. This constraint allow to build reliable and scalable systems.&lt;/li&gt;
&lt;li&gt;To improve network efficiency, any request can be &lt;strong&gt;cached&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Components should have a &lt;strong&gt;uniform interface&lt;/strong&gt;. For example, to use HTTP for communication, even though other transfer protocols might work faster for a specific representation in some cases.&lt;/li&gt;
&lt;li&gt;The system should work with the &lt;strong&gt;layered architecture&lt;/strong&gt;. A layer can be a proxy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code-On-Demand&lt;/strong&gt;. REST allows client functionality to be extended by downloading and executing code in the form of applets or scripts…  However, it also reduces visibility, and thus is only an optional constraint within REST.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;resource&lt;/strong&gt; is located in a URI and &lt;strong&gt;is represented&lt;/strong&gt; to a client &lt;strong&gt;via a standard media type&lt;/strong&gt;. A web client only knows how to process the media type. For example, for a browser to display a &lt;code&gt;PNG&lt;/code&gt; media type, there is no need for a JavaScript code. To display a &lt;code&gt;PDF&lt;/code&gt; file a browser does not need to run some special JavaScript code. The same is true for processing and displaying the &lt;code&gt;HTML&lt;/code&gt; media type.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code-on-demand, with JavaScript, Java Applets, Flash ActionScript, or WASM, is optional in REST. This is a crucial fact in web clients. &lt;/p&gt;

&lt;p&gt;The ultimate representation form of a resource should be understandable by a robot. An AI agent should be able to find the information and edit a resource without human interaction and &lt;a href="https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven" rel="noopener noreferrer"&gt;prior knowledge except how to process standard media types&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modern REST violations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Violation of the optional code-on-demand principle
&lt;/h3&gt;

&lt;p&gt;Today, the idea of optional code-on-demand execution in Web sites, in most cases, is violated.&lt;br&gt;
W3C introduced &lt;a href="https://www.webcomponents.org/" rel="noopener noreferrer"&gt;Web Components&lt;/a&gt; to extend HTML tags but made it entirely dependable on JavaScript. All modern Client-Side libraries, like React.JS, Angular, Vue.JS, are built with JavaScript. Sun Microsystems introduced Java Applets based on JVM. Adobe presented Macromedia Flash with a browser extension. Microsft made it possible to run reduced .NET applications in a browser with the &lt;a href="https://www.microsoft.com/silverlight/" rel="noopener noreferrer"&gt;Silverlight&lt;/a&gt; extension and recently introduced &lt;a href="https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blazor" rel="noopener noreferrer"&gt;Blazor&lt;/a&gt;, which compiles C# code to &lt;a href="https://webassembly.org/" rel="noopener noreferrer"&gt;WebAssembly&lt;/a&gt; and executes it on the client side. &lt;/p&gt;

&lt;p&gt;The frameworks mentioned do not allow a page interaction without a code being executed in a browser. The exception is &lt;a href="https://kit.svelte.dev/" rel="noopener noreferrer"&gt;Svelte.Kit&lt;/a&gt;, which tries hard to make a web page interactive &lt;a href="https://youtu.be/0bog8-Ay7CU?t=12759" rel="noopener noreferrer"&gt;even with disabled JavaScript&lt;/a&gt;. &lt;/p&gt;
&lt;h3&gt;
  
  
  Violation of the resource representation principle
&lt;/h3&gt;

&lt;p&gt;Modern websites pursue the mobile application development style. A web client downloads pages as mobile screens and then makes Remote Procedure Calls (RCP) to a server, usually provided as JSON API endpoints. The application knows how to modify a resource by calling a specific method and what structure of JSON should be sent and returned. This implies a tough coupling of a screen to a backend. &lt;/p&gt;

&lt;p&gt;In contrast, with the REST approach, a browser displays a fresh representation of the resource, including dynamically retrieved actions for editing. For example, the HTML version &lt;code&gt;&amp;lt;form action="/post-api"&amp;gt;&amp;lt;input name="lastname"&amp;gt;&amp;lt;button type="submit"&amp;gt;Submit&amp;lt;button&amp;gt;&amp;lt;form&amp;gt;&lt;/code&gt; is a page representation that itself contains the required structure for an action. A web client also does not know what the response will be and in what format. A server will decide about the subsequent representation, possibly redirecting a web client to a new page.&lt;/p&gt;
&lt;h3&gt;
  
  
  Reasons for violation
&lt;/h3&gt;

&lt;p&gt;Developers step aside from the optional code-on-demand principle with a straightforward requirement - users want to see rich interfaces. Pure HTML does not allow building applications such as Google Mail, Google Sheets, or Google Docs, not to mention the code necessity for 3d web applications. Even if some HTML extensions will be added to HTML v.6, developers need to add custom client-side validation behavior, for example, to a phone input format (mask) per country:&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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyukp5gwnpvbztbvattmm.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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyukp5gwnpvbztbvattmm.png" alt="custom dropdown"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Developers violate the resource representations principle because it is easier to think in the Remote Procedure Call paradigm. Also, coupling a webpage to a JSON API does not appear as bad in practice as it might sound. Modern browsers often refresh the pages with inactive tabs.&lt;br&gt;
The problem with JavaScript, or EcmaScrpit, to be precise, is its speed. It is a text code that should be parsed and interpreted by a browser. In the next section, I will show how web development may be accomplished pleasingly for users and developers.&lt;/p&gt;
&lt;h2&gt;
  
  
  Better Future for the World Wide Web
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Best performance with advanced HTML requests
&lt;/h3&gt;

&lt;p&gt;The best speed a web client can achieve is by transferring small data and not executing code-on-demand at all. &lt;/p&gt;

&lt;p&gt;The next proposals from &lt;a href="https://hypermedia.systems/" rel="noopener noreferrer"&gt;Hypermedia Systems&lt;/a&gt; and &lt;a href="https://htmx.org/" rel="noopener noreferrer"&gt;HTMX&lt;/a&gt; can be implemented in the future HTML version:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Allow &lt;code&gt;PUT&lt;/code&gt;, &lt;code&gt;PATCH&lt;/code&gt;, &lt;code&gt;DELETE&lt;/code&gt; to be declared in HTML actions in addition to the current &lt;code&gt;GET&lt;/code&gt; and &lt;code&gt;POST&lt;/code&gt; methods. Example:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;form action="/contacts/1" method="DELETE"&amp;gt;Delete&amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Allow actions to be triggered by any interactive element in addition to &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; tags. Example:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div action="/contacts" type="GET" trigger="mouseenter"&amp;gt;
  Get The Contacts
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Allow to replace partial screens or single elements with the result from a declarative request. This will allow to create the genuine REST API with HTML responses as described by Fielding in REST API must be hypertext driven. Example:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button hx-get="/contacts" action-target="#main"&amp;gt;Get The Contacts&amp;lt;/button&amp;gt;
&amp;lt;div id="main"&amp;gt;
  &amp;lt;p&amp;gt;This content will be replaced with the requested HTML result&amp;lt;p&amp;gt;
&amp;lt;div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Allow declarative polling and web socket communications. Example:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div action="/messages" type="GET" trigger="every 3s"&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Allow to encapsulate code close to the related component by following the Locality of Behavior principle. Example:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;lt;button&amp;gt;
    &amp;lt;script type="text/javascript"&amp;gt;
      &amp;lt;!-- This code is relative only to the nearest button tag --&amp;gt;
    &amp;lt;script&amp;gt;
    &amp;lt;script type="wasm"&amp;gt;
    &amp;lt;!-- Similar with binary WASM --&amp;gt;
    &amp;lt;script&amp;gt;
&amp;lt;button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Better performance with optional HTML requests
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://docs.astro.build/en/core-concepts/astro-components/" rel="noopener noreferrer"&gt;Astro&lt;/a&gt; project makes it possible to download JavaScript code for a component only when it is visible on the screen or near scrolled. This feature can be included in the future version of HTML. Example:&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;input id="my_input" type="text" placeholder="Name"&amp;gt;
  &amp;lt;script type="text/javascript" 
  href="/input-behavior.js" 
  download="when-visible" 
  target="#my_input"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;input&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Declarative HTML element state
&lt;/h3&gt;

&lt;p&gt;Declaring a simple state in div, span, and button elements similar to form inputs will be helpful. State management is often used for block visibility. Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//HTML
&amp;lt;div id="popup" value="visible"&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;button 
  target="#popup" 
  actionType="valueChange" 
  actionValue="hidden"&amp;gt;
  Toggle popup
&amp;lt;/button&amp;gt;

//CSS
div[value="hidden"] {
  display: none;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Though modern browsers will soon support declarative popups and dialogs even without JavaScript with &lt;a href="https://dev.toPopopover"&gt;Popopover&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog" rel="noopener noreferrer"&gt;Dialog&lt;/a&gt;, simple declarative state management will allow for providing more custom behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extendable native controls
&lt;/h3&gt;

&lt;p&gt;Modern websites use custom UI elements for checkboxes, radio buttons, input elements, alerts, and dropdowns. Almost all of them are made with some CSS and JavaScript tricks, for example, in Bootstrap, Chakra UI, Material UI, ANT Design. Loading CSS and JavaScript for such components without special reduction customization often takes several hundreds of KB in size, plus time to parse and execute JavaScript code. &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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fglhysy693d8jaiol370z.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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fglhysy693d8jaiol370z.png" alt="custom select list"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The better approach would be to allow customization of native browser components. Open UI introduced &lt;a href="https://open-ui.org/components/selectlist/" rel="noopener noreferrer"&gt;SelectList&lt;/a&gt;, which is already included in Chrome. The code for select customization without JavaScript can look like:&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;selectlist&amp;gt;
  &amp;lt;button id=custombutton type=selectlist&amp;gt;
    &amp;lt;selectedvalue&amp;gt;&amp;lt;/selectedvalue&amp;gt;
  &amp;lt;/button&amp;gt;
  &amp;lt;option&amp;gt;one&amp;lt;/option&amp;gt;
  &amp;lt;option&amp;gt;two&amp;lt;/option&amp;gt;
&amp;lt;/selectlist&amp;gt;
&amp;lt;style&amp;gt;
selectlist:open #custombutton {
  background-color: green;
}
selectlist:closed #custombutton {
  background-color: red;
}
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  WebAssebmly with rich runtime
&lt;/h3&gt;

&lt;p&gt;The WWW history shows that corporations cannot agree on one proprietary language for the Web. Sun Microsystems issued a &lt;a href="https://www.infoworld.com/article/2077055/what-does-sun-s-lawsuit-against-microsoft-mean-for-java-developers-.html" rel="noopener noreferrer"&gt;lawsuit against Microsoft in 1997&lt;/a&gt;, complaining that JVM was not correctly implemented in Internet Explorer on purpose. Adobe pursued the Flash project with ActionScript until Apple, in 2008, decided &lt;a href="https://www.howtogeek.com/805605/this-is-how-steve-jobs-killed-adobe-flash/" rel="noopener noreferrer"&gt;not to include Flash in the iPhone Safari browser&lt;/a&gt; due to pure performance. Microsoft used its ActiveX extension in browsers that adapt Component Object Model (&lt;a href="https://learn.microsoft.com/en-us/windows/win32/com/the-component-object-model" rel="noopener noreferrer"&gt;COM&lt;/a&gt;) with C++ and Visual Basic programming. Microsft &lt;a href="https://www.microsoft.com/silverlight/" rel="noopener noreferrer"&gt;Silverlight&lt;/a&gt; browser extension allowed to run code with a reduced .NET runtime. Google attempted to &lt;a href="https://www.cnet.com/tech/services-and-software/google-dart-will-rescue-browsers-from-javascript/" rel="noopener noreferrer"&gt;rescue browsers from JavaScript with Dart language&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Browser vendors make successful agreements contributing to the World Wide Web Consortium (W3C).&lt;/p&gt;

&lt;p&gt;The recent contribution is WebAssembly (&lt;a href="https://webassembly.org/" rel="noopener noreferrer"&gt;WASM&lt;/a&gt;), a binary stack machine &lt;a href="https://caniuse.com/wasm" rel="noopener noreferrer"&gt;supported in modern browsers&lt;/a&gt;. It is natively fast, and deliveries take less space than JavaScript code. There are some disadvantages to the current WASM state. &lt;/p&gt;

&lt;p&gt;First is the size. Writing a server-side and client-side program is &lt;a href="https://github.com/flosse/rust-web-framework-comparison" rel="noopener noreferrer"&gt;possible with Rust&lt;/a&gt;, and the resulting WASM package will be small enough. At the same time, Microsoft Blazor converts C# code to WASM, but the client delivery has to include the reduced .NET runtime, taking &lt;a href="https://github.com/dotnet/aspnetcore/issues/41909" rel="noopener noreferrer"&gt;several megabytes&lt;/a&gt; for a script. The same is true for GoLang, even with an attempt to reduce the runtime delivery in &lt;a href="https://tinygo.org/docs/guides/webassembly/" rel="noopener noreferrer"&gt;TinyGo WASM&lt;/a&gt;. Developers want to work with their favorite languages, whether it is Java, Kotlin, Dart, C#, F#, Swift, Ruby, Python, C, C++, GoLang, or Rust. These languages produce groups of runtimes. For example, JVM and .NET have many common parts, Ruby and Python are dynamically interpreted at runtime, and all mentioned depend on automatic garbage collection. For smaller WASM packages, browser vendors can include extended runtime implementations, for example, by delivering a general garbage collector as part of WASM. Garbage collection support by WASM is currently in progress: &lt;a href="https://github.com/WebAssembly/gc/blob/main/proposals/gc/Overview.md" rel="noopener noreferrer"&gt;WASM GC&lt;/a&gt;, &lt;a href="https://github.com/WebAssembly/gc/issues/77" rel="noopener noreferrer"&gt;.NET WASM Notes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Second, WASM still manipulates DOM in a browser via JavaScript interop. Updating the DOM tree natively without a JavaScript proxy will be faster and require fewer CPU resources.&lt;/p&gt;

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

&lt;p&gt;Web development stepped aside from the REST principles to provide interactivity for rich UI interfaces. A new HTML version with a declarative style for fetch requests can lead to ultra-fast websites. New WebAssebly runtimes may allow developers to program Client- and Back-end side code with a favorite language.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>html</category>
      <category>rest</category>
      <category>webassembly</category>
    </item>
  </channel>
</rss>
