<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mark Andreev</title>
    <description>The latest articles on DEV Community by Mark Andreev (@mrkandreev).</description>
    <link>https://dev.to/mrkandreev</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%2F678144%2Fd2a0acee-cea8-43f6-a4d9-11a6cdd87257.png</url>
      <title>DEV Community: Mark Andreev</title>
      <link>https://dev.to/mrkandreev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mrkandreev"/>
    <language>en</language>
    <item>
      <title>FIX Protocol System-Level Implementation: Session Management Deep Dive</title>
      <dc:creator>Mark Andreev</dc:creator>
      <pubDate>Mon, 13 Oct 2025 19:26:24 +0000</pubDate>
      <link>https://dev.to/mrkandreev/fix-protocol-system-level-implementation-session-management-deep-dive-kjp</link>
      <guid>https://dev.to/mrkandreev/fix-protocol-system-level-implementation-session-management-deep-dive-kjp</guid>
      <description>&lt;p&gt;The Financial Information eXchange (FIX) protocol serves as the standardized messaging framework for electronic trading across global financial institutions. The session-level protocol remains consistent across implementations, providing the foundation for reliable communication that processes billions of messages daily with sub-millisecond latency requirements.&lt;/p&gt;

&lt;p&gt;This article examines the system-level implementation of FIX protocol, focusing on four fundamental session management messages: &lt;strong&gt;Logon&lt;/strong&gt;, &lt;strong&gt;Logout&lt;/strong&gt;, &lt;strong&gt;Heartbeat&lt;/strong&gt;, and &lt;strong&gt;Resend Request&lt;/strong&gt;. These components form the infrastructure layer that every FIX implementation must handle correctly, regardless of the business logic built on top.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: Application-level business messages (orders, executions, market data) are excluded to maintain focus on the foundational session layer.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  FIX Message Structure and Encoding
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Tag-Value Format Specifications
&lt;/h3&gt;

&lt;p&gt;FIX protocol employs tag-value encoding where each field appears as &lt;code&gt;tag=value&lt;/code&gt; pairs separated by the Start of Heading (SOH) character (ASCII 0x01). The SOH delimiter is non-printable, requiring careful handling during debugging and logging.&lt;/p&gt;

&lt;p&gt;Every FIX message adheres to this structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8=FIX.4.4|9=89|35=A|49=SENDER|56=TARGET|34=1|52=20251012-14:30:15|108=30|98=0|141=Y|10=178|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: Pipe characters (&lt;code&gt;|&lt;/code&gt;) represent SOH (0x01) for readability throughout this article.&lt;/em&gt;&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%2Fmcqhhfm2vs5amyj45j5s.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%2Fmcqhhfm2vs5amyj45j5s.png" alt=" " width="800" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(&lt;a href="https://fixparser.mrkandreev.name/#/?state=eNoNzbEKwjAQBuB3yazlLrloEviHglEcdKgdFO0gUkXQOgRB8Hx3u37L9zXX%2B2fTl3K%2B9cUkE7Bc7yupRCNCVOdRq0Ts8naRG%2FUztHWzyq06Aau3sGQ9E9spS3KU2CtTgCONAaQsjMMo4HnQ02Am5vJ6vJ%2FDOB273x%2BWVCLY" rel="noopener noreferrer"&gt;View in FixParser&lt;/a&gt;)&lt;/p&gt;

&lt;h3&gt;
  
  
  Message Anatomy and Mandatory Fields
&lt;/h3&gt;

&lt;p&gt;Three fields maintain strict positional requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tag 8 (BeginString)&lt;/strong&gt;: Protocol version identifier, always first field&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag 9 (BodyLength)&lt;/strong&gt;: Byte count starting immediately after tag 9's delimiter through the byte preceding the checksum field's tag, excluding BeginString and BodyLength themselves but including all SOH delimiters within that range&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag 35 (MsgType)&lt;/strong&gt;: Message type identifier, always third field
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag 10 (CheckSum)&lt;/strong&gt;: Three-digit checksum value, always last field&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The BodyLength calculation excludes tags 8, 9, and 10 along with their delimiters, but counts every byte in between, including field delimiters and the values themselves.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checksum Algorithm Implementation
&lt;/h3&gt;

&lt;p&gt;The CheckSum field (tag 10) ensures message integrity through a modulo 256 algorithm. The calculation process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sum all bytes from BeginString (tag 8) through the delimiter preceding the CheckSum field&lt;/li&gt;
&lt;li&gt;Apply modulo 256 to the sum&lt;/li&gt;
&lt;li&gt;Format the result as a zero-padded three-digit string&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, if the byte sum equals 274, the calculation yields 274 % 256 = 18, transmitted as "018". This lightweight validation catches transmission errors without cryptographic overhead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Message Validation Sequence
&lt;/h3&gt;

&lt;p&gt;Implementations should validate messages in this specific order to prevent expensive processing of malformed data:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;BeginString format verification&lt;/li&gt;
&lt;li&gt;BodyLength calculation and boundary check&lt;/li&gt;
&lt;li&gt;MsgType field presence and validity&lt;/li&gt;
&lt;li&gt;Required field presence based on message type&lt;/li&gt;
&lt;li&gt;CheckSum calculation and comparison&lt;/li&gt;
&lt;li&gt;Sequence number verification against expected value&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This ordering ensures that structurally invalid messages are rejected before performing computationally intensive validation steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Session vs Connection Lifecycle
&lt;/h2&gt;

&lt;p&gt;A critical distinction exists between FIX &lt;strong&gt;sessions&lt;/strong&gt; and &lt;strong&gt;connections&lt;/strong&gt;. A FIX session represents a logical relationship between two parties that spans multiple sequential (not concurrent) physical connections, maintaining continuous sequence numbering across disconnects and reconnects.&lt;/p&gt;

&lt;p&gt;A single connection consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TCP establishment&lt;/li&gt;
&lt;li&gt;Logon message exchange&lt;/li&gt;
&lt;li&gt;Business message flow&lt;/li&gt;
&lt;li&gt;Logout and TCP closure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A session can span an entire trading day with multiple connection attempts, preserving sequence state across each reconnection. The sequence number series begins at 1 and continues monotonically throughout the session's lifetime, potentially across dozens of individual connections.&lt;/p&gt;

&lt;h3&gt;
  
  
  Session vs Application Message Layers
&lt;/h3&gt;

&lt;p&gt;FIX operates at two distinct protocol layers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Session Level Messages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manage connection lifecycle and reliability&lt;/li&gt;
&lt;li&gt;Enforce ordered message delivery&lt;/li&gt;
&lt;li&gt;Handle sequence gaps and recovery&lt;/li&gt;
&lt;li&gt;Types: Logon (A), Logout (5), Heartbeat (0), Test Request (1), Resend Request (2), Sequence Reset (4), Reject (3)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Application Level Messages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transport business-specific trading data
&lt;/li&gt;
&lt;li&gt;Examples: New Order Single (D), Execution Report (8), Market Data Request (V)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Session Management Messages
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Logon Message (MsgType=A)
&lt;/h3&gt;

&lt;p&gt;The Logon message initiates a FIX session and must be the first message transmitted by the connection initiator. Authentication parameters and session configuration are established during this exchange.&lt;/p&gt;

&lt;h4&gt;
  
  
  Required and Optional Fields
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tag 35&lt;/strong&gt;: MsgType = 'A'&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag 98&lt;/strong&gt;: EncryptMethod (0 = none, 1 = PKCS, 2 = DES, 3 = PKCS/DES)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag 108&lt;/strong&gt;: HeartBtInt (heartbeat interval in seconds)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag 141&lt;/strong&gt;: ResetSeqNumFlag (Y/N - controls sequence number initialization)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag 554&lt;/strong&gt;: Password (authentication credential)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag 553&lt;/strong&gt;: Username (authentication credential)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that tag 98 (EncryptMethod) refers to FIX application-layer encryption. Most exchanges require TLS/SSL at the transport layer even when EncryptMethod=0, as transport and FIX-layer encryption operate independently.&lt;/p&gt;

&lt;h4&gt;
  
  
  Logon Message Example
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Initiator to Acceptor:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8=FIX.4.4|9=89|35=A|49=TRADER_SYSTEM|56=EXCHANGE_GATEWAY|34=1|52=20251012-14:30:15.123|98=0|108=30|141=Y|553=trader123|554=secretpass|10=178|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fl3cg25m8jpmp06w5mg7y.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%2Fl3cg25m8jpmp06w5mg7y.png" alt=" " width="800" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(&lt;a href="https://fixparser.mrkandreev.name/#/?state=eNoVjssKwjAQAP8lZy3ZJKtpYQ9BY%2FWgBy1oUSmlRhF80SgIrv9uPc1h5jAfcTy%2F5yHG%2BhSiyISlyWyTmMRwSjZljeTYpFQs3dgvq1W5KvyccUB%2BM5q6Re6r3BV%2B7UrWhoBRkZIKQYLqg8m0zAATUJpTS5JBWtIdDFDJiJqebX0I7d8jGoqhacPzUcfYlQRDy7ub6Inmfnldb93bdv%2F9ARSJMtA%3D" rel="noopener noreferrer"&gt;View in FixParser&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Field Interpretation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;8=FIX.4.4&lt;/code&gt;: Protocol version&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;9=89&lt;/code&gt;: Body length in bytes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;35=A&lt;/code&gt;: Logon message identifier&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;49=TRADER_SYSTEM&lt;/code&gt;: SenderCompID&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;56=EXCHANGE_GATEWAY&lt;/code&gt;: TargetCompID
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;34=1&lt;/code&gt;: Message sequence number&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;52=20251012-14:30:15.123&lt;/code&gt;: UTC timestamp&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;98=0&lt;/code&gt;: No FIX-layer encryption&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;108=30&lt;/code&gt;: 30-second heartbeat interval&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;141=Y&lt;/code&gt;: Reset sequences to 1&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;553=trader123&lt;/code&gt;: Username&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;554=secretpass&lt;/code&gt;: Password&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;10=178&lt;/code&gt;: Checksum&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Acceptor Response (Successful):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8=FIX.4.4|9=78|35=A|49=EXCHANGE_GATEWAY|56=TRADER_SYSTEM|34=1|52=20251012-14:30:15.456|98=0|108=30|141=Y|10=156|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F5utyriadda7j0t2sq3zq.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%2F5utyriadda7j0t2sq3zq.png" alt=" " width="800" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(&lt;a href="https://fixparser.mrkandreev.name/#/?state=eNoNjbEKwjAUAP8ls5a85KUmhTcEjdWhDm3AFpUiUkXQOhRB8PnvZjqOG%2B4rrvdPNUzT%2BTZMohCW1ts2wwzZ0cKyNuQZHYV2ufG7MvSlj2HvOzY5xdqvQt03XRNDxRoJ2ChSUhmQoOaAhZYFmAxNzs6SZJCWdAICdUkIUjiOYiYur8f7Oab94fT7A9G%2BKNE%3D" rel="noopener noreferrer"&gt;View in FixParser&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Acceptor Response (Authentication Failed):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8=FIX.4.4|9=87|35=5|49=EXCHANGE_GATEWAY|56=TRADER_SYSTEM|34=1|52=20251012-14:30:15.789|58=Authentication failed|10=234|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fc8k4xetapxtor8yr1f9q.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%2Fc8k4xetapxtor8yr1f9q.png" alt=" " width="800" height="207"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(&lt;a href="https://fixparser.mrkandreev.name/#/?state=eNqlz70KwjAUBeBXkcxa8mvTwh2Cxuqggxa0qEipqQZqHVpB8Pruxs3d6XA4w8d5kdo%2Fl67ryovrSEo0zBa7SEYSE4g1CgUGZQJ2N5mbVWZPmcnt1hSoxpCvzdSuT5tik9slCgkMFQdOuWKU8RGTqaApU5FUY0w0UGRUgwghGRShAAvDof0VdfwV1b9irBNUGsyjv7q291XZ%2B3s7qEvfuPMX5kIGmAxJdW8etzb83h%2FfH753S7M%3D" rel="noopener noreferrer"&gt;View in FixParser&lt;/a&gt;)&lt;/p&gt;

&lt;h4&gt;
  
  
  Authentication Failure Handling
&lt;/h4&gt;

&lt;p&gt;When authentication fails, the acceptor must send a Logout message rather than simply closing the connection. The Logout should include tag 58 (Text) with the specific failure reason. The acceptor should wait a configurable period (typically 1-2 seconds) before closing the socket to ensure complete transmission of the Logout message.&lt;/p&gt;

&lt;h4&gt;
  
  
  Sequence Number Initialization
&lt;/h4&gt;

&lt;p&gt;The ResetSeqNumFlag (tag 141) determines sequence number behavior. When set to 'Y', both parties reset their outbound and expected inbound sequence numbers to 1. When set to 'N', sequence numbers continue from the previous session's final values, requiring both parties to maintain persistent state across connection failures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logout Message (MsgType=5)
&lt;/h3&gt;

&lt;p&gt;The Logout message provides graceful session termination. Either party may initiate logout, and proper implementations require bidirectional Logout exchange before TCP closure.&lt;/p&gt;

&lt;h4&gt;
  
  
  Message Structure
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tag 35&lt;/strong&gt;: MsgType = '5'&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag 58&lt;/strong&gt;: Text (reason for logout)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Logout Scenarios
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Normal Shutdown:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8=FIX.4.4|9=73|35=5|49=TRADER_SYSTEM|56=EXCHANGE_GATEWAY|34=157|52=20251012-16:00:00.000|58=End of trading day|10=145|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F3of74h6sdf91rwxoo4n4.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%2F3of74h6sdf91rwxoo4n4.png" alt=" " width="800" height="207"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Response Logout:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8=FIX.4.4|9=65|35=5|49=EXCHANGE_GATEWAY|56=TRADER_SYSTEM|34=298|52=20251012-16:00:00.123|58=Goodbye|10=123|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F0zu2689g36i1mupn0ryx.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%2F0zu2689g36i1mupn0ryx.png" alt=" " width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Logout Due to Sequence Error:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8=FIX.4.4|9=89|35=5|49=EXCHANGE_GATEWAY|56=TRADER_SYSTEM|34=299|52=20251012-15:45:30.567|58=Sequence number too low: expected 158, received 150|10=187|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fx2fpx26hni7wa4zble40.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%2Fx2fpx26hni7wa4zble40.png" alt=" " width="800" height="179"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Graceful Termination Requirements
&lt;/h4&gt;

&lt;p&gt;The logout initiator must wait for the counter-party's acknowledgment Logout message before closing the socket. However, implementations must include a timeout mechanism (typically 2-5 seconds) to prevent indefinite waiting if the counter-party fails to respond. After timeout expiration, the socket should be forcibly closed to prevent resource leaks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Heartbeat Message (MsgType=0)
&lt;/h3&gt;

&lt;p&gt;Heartbeat messages maintain connection liveness during idle periods. They are transmitted automatically when no other messages have been sent within the agreed heartbeat interval.&lt;/p&gt;

&lt;h4&gt;
  
  
  Message Components
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tag 35&lt;/strong&gt;: MsgType = '0'&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag 112&lt;/strong&gt;: TestReqID (present only when responding to Test Request)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Heartbeat Examples
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Spontaneous Heartbeat:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8=FIX.4.4|9=58|35=0|49=TRADER_SYSTEM|56=EXCHANGE_GATEWAY|34=89|52=20251012-15:30:45.000|10=123|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F1kxcm1d6tmltklu5yqxo.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%2F1kxcm1d6tmltklu5yqxo.png" alt=" " width="800" height="179"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Response to Test Request:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8=FIX.4.4|9=75|35=0|49=EXCHANGE_GATEWAY|56=TRADER_SYSTEM|34=234|52=20251012-15:30:50.000|112=TEST_ID_001|10=189|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F79pchzuft7tidnek9s5o.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%2F79pchzuft7tidnek9s5o.png" alt=" " width="800" height="179"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Heartbeat Timer Behavior
&lt;/h4&gt;

&lt;p&gt;The heartbeat timer resets after transmitting any message type, not exclusively heartbeats. This prevents unnecessary heartbeat traffic during active trading periods. When responding to a Test Request (MsgType=1), the Heartbeat must echo back the TestReqID value received in tag 112.&lt;/p&gt;

&lt;p&gt;If a party fails to receive any message within the heartbeat interval plus a reasonable transmission buffer, it should issue a Test Request. Continued silence after the Test Request indicates connection failure and typically triggers session termination.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resend Request Message (MsgType=2)
&lt;/h3&gt;

&lt;p&gt;The Resend Request message implements gap recovery by requesting retransmission of missing messages. This mechanism ensures reliable, ordered delivery despite network packet loss or out-of-order TCP segment arrival.&lt;/p&gt;

&lt;h4&gt;
  
  
  Request Structure
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tag 35&lt;/strong&gt;: MsgType = '2'&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag 7&lt;/strong&gt;: BeginSeqNo (first sequence number to resend)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag 16&lt;/strong&gt;: EndSeqNo (last sequence number to resend, 0 = infinity)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Resend Request Examples
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Request Specific Range:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8=FIX.4.4|9=58|35=2|49=TRADER_SYSTEM|56=EXCHANGE_GATEWAY|34=45|52=20251012-14:45:15.000|7=35|16=42|10=167|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fzs716fz2eomu9evnwcje.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%2Fzs716fz2eomu9evnwcje.png" alt=" " width="800" height="189"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request Through Current Message:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8=FIX.4.4|9=57|35=2|49=EXCHANGE_GATEWAY|56=TRADER_SYSTEM|34=123|52=20251012-14:45:20.000|7=98|16=0|10=145|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fgpml29d5w4ftjpon8s44.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%2Fgpml29d5w4ftjpon8s44.png" alt=" " width="800" height="189"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The infinite EndSeqNo scenario (tag 16=0) requests all messages from BeginSeqNo through the most recently sent message. This simplifies gap recovery when the requester is uncertain about the actual gap size.&lt;/p&gt;

&lt;h4&gt;
  
  
  PossDupFlag and OrigSendingTime
&lt;/h4&gt;

&lt;p&gt;Resent messages must include PossDupFlag (tag 43) set to 'Y' and OrigSendingTime (tag 122) containing the timestamp from the original transmission. This allows receivers to detect and handle duplicate processing scenarios:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8=FIX.4.4|9=XXX|35=D|49=BROKER01|56=CLIENT01|34=23|52=20251012-09:16:30.000|43=Y|122=20251012-09:10:15.000|...|10=XXX|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F05du6gfvhtbve8d20i94.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%2F05du6gfvhtbve8d20i94.png" alt=" " width="800" height="189"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The combination of sequence number, PossDupFlag, and OrigSendingTime enables the receiver to determine whether a message represents a genuine retransmission or a critical protocol violation.&lt;/p&gt;

&lt;h4&gt;
  
  
  Sequence Reset with GapFillFlag
&lt;/h4&gt;

&lt;p&gt;When requested messages contain only administrative messages that don't require retransmission, the sender responds with a Sequence Reset (MsgType=4) containing GapFillFlag (tag 123) set to 'Y':&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8=FIX.4.4|9=78|35=4|49=EXCHANGE_GATEWAY|56=TRADER_SYSTEM|34=35|52=20251012-14:45:25.000|123=Y|36=43|10=234|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Frgn75o08p1e4ww88x60d.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%2Frgn75o08p1e4ww88x60d.png" alt=" " width="800" height="189"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The NewSeqNo field (tag 36) is set to one greater than the last administrative message sequence number in the gap. This informs the requester that no application-level messages need recovery for that range.&lt;/p&gt;

&lt;h4&gt;
  
  
  Nested Gap Recovery
&lt;/h4&gt;

&lt;p&gt;If a Resend Request itself has a sequence gap (the Resend Request's sequence number is higher than expected), the receiver faces nested gap recovery. The receiver must prioritize the new gap by issuing its own Resend Request before processing the original Resend Request, potentially creating multiple overlapping recovery operations that require careful state management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Complete Session Flow
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Session Establishment
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Connection Initiation:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INITIATOR ---&amp;gt; ACCEPTOR: Logon
8=FIX.4.4|9=89|35=A|49=CLIENT01|56=BROKER01|34=1|52=20251012-09:00:00.000|98=0|108=30|141=Y|553=user123|554=pass456|10=178|

ACCEPTOR ---&amp;gt; INITIATOR: Logon Response  
8=FIX.4.4|9=78|35=A|49=BROKER01|56=CLIENT01|34=1|52=20251012-09:00:00.123|98=0|108=30|141=Y|10=156|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fb3r5xsh72xogi322jcy0.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%2Fb3r5xsh72xogi322jcy0.png" alt=" " width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(&lt;a href="https://fixparser.mrkandreev.name/#/?state=eNp1z0sKwkAMANC7zFpL5ldnClmoVCj%2BoLhQrIsiVQSt4lAQjHc3XVgEEQIJIeQlT3E4PeZVCOWxCiIRDifZOjKRIY%2FOk7Y4JONxPMvSxQok2RhH%2BXKa5lxrg9xQqEBZCVL1wScAHBEAkHcIJMGh5mQkbshajU2o7lJprg3eyhCMjXkI5cBRUX%2Fj3PjgHch4d8h%2FvF3%2Fi7cIW0UtemJ%2FPTeXmt%2Fd7l5vKUpFWQ%3D%3D" rel="noopener noreferrer"&gt;View in FixParser&lt;/a&gt;)&lt;/p&gt;

&lt;h3&gt;
  
  
  Active Trading Period
&lt;/h3&gt;

&lt;p&gt;Business messages flow bidirectionally with incrementing sequence numbers. Each party independently maintains outbound sequence counters and expected inbound sequence counters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Idle Period Heartbeat
&lt;/h3&gt;

&lt;p&gt;During periods without business messages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CLIENT01 ---&amp;gt; BROKER01: Heartbeat (sequence 47)
8=FIX.4.4|9=58|35=0|49=CLIENT01|56=BROKER01|34=47|52=20251012-09:15:30.000|10=123|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F4qwgelei5ny09vzs2hg1.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%2F4qwgelei5ny09vzs2hg1.png" alt=" " width="800" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Gap Detection and Recovery
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Gap Detection Scenario:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CLIENT01 ---&amp;gt; BROKER01: Resend Request (detected gap: expected 23, received 25)
8=FIX.4.4|9=57|35=2|49=CLIENT01|56=BROKER01|34=48|52=20251012-09:16:00.000|7=23|16=24|10=145|

BROKER01 ---&amp;gt; CLIENT01: Resend Message 23 (with PossDupFlag and OrigSendingTime)
8=FIX.4.4|9=XXX|35=D|49=BROKER01|56=CLIENT01|34=23|52=20251012-09:16:05.000|43=Y|122=20251012-09:10:15.000|...|10=XXX|

BROKER01 ---&amp;gt; CLIENT01: Resend Message 24
8=FIX.4.4|9=XXX|35=8|49=BROKER01|56=CLIENT01|34=24|52=20251012-09:16:05.100|43=Y|122=20251012-09:10:45.000|...|10=XXX|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fh1erkkl37t6eoxj9kbea.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%2Fh1erkkl37t6eoxj9kbea.png" alt=" " width="800" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(&lt;a href="https://fixparser.mrkandreev.name/#/?state=eNp90MsKwkAMheF3mbUOyTTTG2SjVijeoLioqAuRKoLWRREE47s7VSiipbvAge%2BHPNThdJ8VVbU7FpWKVcjjNNekSSK2gXiWjVDEw2mazJeAYn0eZItJkrnbI6ZQrGEDxiKg6UMUox8DaACQgI0n6LMhQWAkK5vym8%2FzvPZHtd%2BYzm9azndCi2%2FfPnm8EjQ%2FM8T4mbXWdbeutHbDzi61d7GjS39d1VP76%2Fl2Kd1n19vnC94bXhY%3D" rel="noopener noreferrer"&gt;View in FixParser&lt;/a&gt;)&lt;/p&gt;

&lt;h3&gt;
  
  
  Session Termination
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Bidirectional Logout:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CLIENT01 ---&amp;gt; BROKER01: Logout
8=FIX.4.4|9=73|35=5|49=CLIENT01|56=BROKER01|34=49|52=20251012-17:00:00.000|58=End of trading day|10=145|

BROKER01 ---&amp;gt; CLIENT01: Logout Response
8=FIX.4.4|9=65|35=5|49=BROKER01|56=CLIENT01|34=156|52=20251012-17:00:00.123|58=Goodbye|10=123|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fmjxfa8a8n271xfagrn32.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%2Fmjxfa8a8n271xfagrn32.png" alt=" " width="800" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(&lt;a href="https://fixparser.mrkandreev.name/#/?state=eNptz7sKwkAQBdBfCVtrmH1MXjCNEiX4ArEQ1CK6SQhoFoyCwfXfXS2ChTDF5Rb3ME9W1o9F0bZ5VbQsYRFNsq2vfGVjCqWVSGhVTON5li43wC0GNFqvZunaZalIxRYFCRDIgYshDxMAdz4AWIwobbRnSu92zXXdVJ7OO8uBuEK7b36lAHupX3dSrzqJY%2FCf4kJ%2BqKkx%2BtgV333XsAE7mfP90rindofXG%2FOoP8c%3D" rel="noopener noreferrer"&gt;View in FixParser&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Error Handling and Edge Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Sequence Number Violations
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Gap Detected (Too High):&lt;/strong&gt;&lt;br&gt;
The receiver sends a Resend Request for the missing range and queues any newer messages received while waiting for gap fill. Messages are released to the application layer only after gaps are resolved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sequence Too Low (Duplicate or Replay):&lt;/strong&gt;&lt;br&gt;
When a message arrives with a sequence number lower than expected without PossDupFlag=Y, a serious protocol violation has occurred. The recipient must immediately terminate the session via Logout with an explanatory Text field. This scenario indicates potential state desynchronization that could result in duplicate order processing.&lt;/p&gt;
&lt;h3&gt;
  
  
  Test Request Mechanism
&lt;/h3&gt;

&lt;p&gt;When heartbeat violations occur:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;8=FIX.4.4|9=78|35=1|49=CLIENT01|56=BROKER01|34=50|52=20251012-15:45:30.000|112=HEARTBEAT_CHECK_001|10=189|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Ffukaoxq2sjun4ieejb68.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%2Ffukaoxq2sjun4ieejb68.png" alt=" " width="800" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Test Request (MsgType=1) probes for counterparty responsiveness. The counterparty must respond with a Heartbeat containing the echoed TestReqID. Failure to respond within a reasonable timeout (typically equal to the heartbeat interval) indicates connection failure and triggers logout or forced disconnection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Memory-Efficient State Management
&lt;/h3&gt;

&lt;p&gt;High-frequency trading environments require efficient sequence number state management. Implementations should avoid storing entire message histories in memory. Instead, maintain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Current outbound sequence number (32-bit or 64-bit integer)&lt;/li&gt;
&lt;li&gt;Expected inbound sequence number (32-bit or 64-bit integer)
&lt;/li&gt;
&lt;li&gt;Bounded queue of recently sent messages for potential resend (circular buffer with configurable depth)&lt;/li&gt;
&lt;li&gt;Pending gap ranges awaiting resolution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach limits memory consumption while supporting gap recovery without unbounded storage requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Out-of-Order TCP Segment Handling
&lt;/h3&gt;

&lt;p&gt;During periods of high network load, TCP may deliver segments out of order at the application layer despite TCP's ordering guarantees. FIX implementations must buffer messages received with higher-than-expected sequence numbers and trigger Resend Requests only after a timeout period (typically 100-500 milliseconds) to distinguish genuine gaps from transient reordering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Production Implementation Considerations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Transport Layer Security
&lt;/h3&gt;

&lt;p&gt;Most production exchanges mandate TLS/SSL encryption for FIX connections. This requirement exists independently of the EncryptMethod field (tag 98), which controls FIX application-layer encryption. Certificate validation, cipher suite selection, and TLS version negotiation occur at the transport layer before any FIX messages are exchanged.&lt;/p&gt;

&lt;h3&gt;
  
  
  Session State Persistence
&lt;/h3&gt;

&lt;p&gt;Implementations supporting sequence number continuation (ResetSeqNumFlag=N) must persist session state across application restarts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Last sent sequence number&lt;/li&gt;
&lt;li&gt;Last received sequence number&lt;/li&gt;
&lt;li&gt;SenderCompID and TargetCompID bindings&lt;/li&gt;
&lt;li&gt;Session start time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Database or file-based persistence ensures accurate state recovery after crashes or planned maintenance windows.&lt;/p&gt;

&lt;h3&gt;
  
  
  High-Frequency Performance Optimization
&lt;/h3&gt;

&lt;p&gt;Sub-millisecond latency requirements demand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zero-copy message parsing when possible&lt;/li&gt;
&lt;li&gt;Pre-allocated message buffers to avoid allocation overhead&lt;/li&gt;
&lt;li&gt;Lock-free or low-contention data structures for sequence state&lt;/li&gt;
&lt;li&gt;Direct TCP socket access bypassing kernel networking stacks where permitted&lt;/li&gt;
&lt;li&gt;CPU affinity pinning for FIX processing threads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Production systems handling billions of daily messages require these optimizations to meet performance targets while maintaining protocol correctness.&lt;/p&gt;

&lt;h3&gt;
  
  
  Monitoring and Observability
&lt;/h3&gt;

&lt;p&gt;Production FIX engines should emit metrics for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Message throughput (messages per second, inbound and outbound)&lt;/li&gt;
&lt;li&gt;Gap recovery frequency and duration&lt;/li&gt;
&lt;li&gt;Heartbeat latency (time between expected and received heartbeats)&lt;/li&gt;
&lt;li&gt;Sequence number lag (difference between expected and actual sequence numbers)&lt;/li&gt;
&lt;li&gt;Authentication failure rates&lt;/li&gt;
&lt;li&gt;Average message processing latency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These metrics enable operators to detect degradation before it impacts trading operations.&lt;/p&gt;

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

&lt;p&gt;The FIX protocol's session management layer provides battle-tested infrastructure for reliable, ordered message delivery in high-stakes financial environments. The four core messages.Logon, Logout, Heartbeat, and Resend Request establish a framework that processes billions of messages daily with sub-millisecond latency requirements across thousands of global institutions.&lt;/p&gt;

&lt;p&gt;The session layer's separation from application-layer business logic exemplifies sound architectural design. This clean separation allows trading systems to focus on order management, execution, and risk control while delegating transport reliability to the session layer.&lt;/p&gt;

&lt;p&gt;Production FIX implementations demand attention to subtle details: checksum calculation algorithms, sequence number state management, graceful logout procedures with timeout handling, and nested gap recovery scenarios. These technical nuances distinguish robust production systems from naive implementations that fail under adverse network conditions or high message volumes.&lt;/p&gt;

</description>
      <category>software</category>
    </item>
    <item>
      <title>What Most Java Developers Miss About HashMap - And Why It Might Be Slowing You Down</title>
      <dc:creator>Mark Andreev</dc:creator>
      <pubDate>Fri, 10 Oct 2025 07:59:00 +0000</pubDate>
      <link>https://dev.to/mrkandreev/what-most-java-developers-miss-about-hashmap-and-why-it-might-be-slowing-you-down-2fe9</link>
      <guid>https://dev.to/mrkandreev/what-most-java-developers-miss-about-hashmap-and-why-it-might-be-slowing-you-down-2fe9</guid>
      <description>&lt;h2&gt;
  
  
  The Hidden Pitfall of HashMap’s Initial Capacity
&lt;/h2&gt;

&lt;p&gt;If you’ve been working with Java for a while, chances are you’ve used HashMap without giving much thought to its inner workings. After all, it’s a staple collection class-one of those things you just expect to work.&lt;/p&gt;

&lt;p&gt;But here’s the catch: misusing the initial capacity setting can lead to unexpected performance issues, even in welloptimized codebases. And the worst part? Most developers don’t even realize they’re making the mistake.&lt;/p&gt;

&lt;p&gt;So, what’s going on here? And how did Java 19 finally fix the problem?&lt;/p&gt;

&lt;p&gt;Let’s break it down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding HashMap's Parameters
&lt;/h2&gt;

&lt;p&gt;At its core, a HashMap has two parameters that dictate how efficiently it stores data: initial capacity and load factor.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Capacity is simply the number of buckets available to store entries.
Load factor controls when the hash table should grow.&lt;/li&gt;
&lt;li&gt;Whenever the number of entries exceeds the product of the load factor and current capacity, Java rehashes the table, increasing the number of buckets - usually doubling them. This automatic resizing is great in theory but can introduce unnecessary overhead if developers don’t set the initial capacity correctly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Default Initialization is Misleading
&lt;/h2&gt;

&lt;p&gt;Here’s where the problem comes in: most developers assume that setting the initial capacity means they’re defining the number of key-value pairs their HashMap will hold. But that’s not the case.&lt;br&gt;
Instead, the constructor defines the bucket count, which doesn’t directly map to the expected number of entries. Because of this, developers have spent years manually adjusting their calculations using various formulas - each with slightly different results.&lt;/p&gt;

&lt;p&gt;Some common ways Java developers have estimated the right capacity include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;(int) (numMappings / 0.75f) + 1&lt;/li&gt;
&lt;li&gt;(int) ((float) numMappings / 0.75f + 1.0f)&lt;/li&gt;
&lt;li&gt;(numMappings * 4 + 2) / 3&lt;/li&gt;
&lt;li&gt;(int) ((numMappings * 4L + 2L) / 3L)&lt;/li&gt;
&lt;li&gt;(int) Math.ceil(numMappings / 0.75f)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This inconsistency has popped up even in official Java code take java.lang.module.Resolver::makeGraph, which also contains a flawed assumption about capacity (source).&lt;/p&gt;
&lt;h2&gt;
  
  
  How Java 19 Finally Fixed It
&lt;/h2&gt;

&lt;p&gt;After years of developers reinventing the wheel, Java 19 introduced HashMap::newHashMap(int numMappings), which finally offers a standardized way to create a properly sized HashMap.&lt;br&gt;
Here’s how it works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;newHashMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;numMappings&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numMappings&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Negative number of mappings: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;numMappings&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;calculateHashMapCapacity&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numMappings&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="no"&gt;DEFAULT_LOAD_FACTOR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.75f&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;calculateHashMapCapacity&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;numMappings&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;Math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ceil&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numMappings&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="no"&gt;DEFAULT_LOAD_FACTOR&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of manually tweaking capacity values, developers can now call this method and let Java handle the calculation. This ensures that the map is correctly sized and avoids unnecessary resizing operations.&lt;/p&gt;

&lt;p&gt;The update was part of &lt;a href="https://bugs.openjdk.org/browse/JDK-8186958" rel="noopener noreferrer"&gt;JDK-8186958&lt;/a&gt;, and the full implementation can be found in this commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices Before Java 19
&lt;/h2&gt;

&lt;p&gt;If you’re working with a Java version before 19, you have a couple of options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implement your own helper method similar to newHashMap to ensure correctly sized maps.&lt;/li&gt;
&lt;li&gt;Prevent incorrect constructor usage across your team using code quality tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Using ArchUnit for Code Quality
&lt;/h3&gt;

&lt;p&gt;One way to enforce best practices is with &lt;a href="https://www.archunit.org/" rel="noopener noreferrer"&gt;ArchUnit&lt;/a&gt;, which allows you to restrict incorrect constructor calls across your codebase.&lt;br&gt;
The following rule ensures that developers don’t use new HashMap&amp;lt;&amp;gt;(capacity), forcing them to call HashMap.newHashMap(numMappings) instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.tngtech.archunit.base.DescribedPredicate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.tngtech.archunit.core.domain.JavaConstructorCall&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.tngtech.archunit.junit.AnalyzeClasses&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.tngtech.archunit.junit.ArchTest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.tngtech.archunit.lang.ArchRule&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.HashMap&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;tngtech&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;archunit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;syntax&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ArchRuleDefinition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;noClasses&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@AnalyzeClasses&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"org.example"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HashMapCapacityConstructorRulesTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@ArchTest&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ArchRule&lt;/span&gt; &lt;span class="n"&gt;no_class_should_call_hashmap_capacity_constructor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;noClasses&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;should&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;callConstructorWhere&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DescribedPredicate&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"Should not call HashMap&amp;lt;&amp;gt;(capacity). Use HashMap.newHashMap instead"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;@Override&lt;/span&gt;
            &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JavaConstructorCall&lt;/span&gt; &lt;span class="n"&gt;constructorCall&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;constructorCall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTarget&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getOwner&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;isEquivalentTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;constructorCall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTarget&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getRawParameterTypes&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
                    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;constructorCall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTarget&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getRawParameterTypes&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getFirst&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;isEquivalentTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;});&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps teams prevent misleading API usage, ensuring that their projects are future-proof and scalable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Why Clear API Design Matters
&lt;/h2&gt;

&lt;p&gt;Sometimes, even fundamental Java classes contain misleading API designs. While using the wrong HashMap constructor may not always cause obvious performance bottlenecks, it’s still better to adopt modern best practices to avoid hidden inefficiencies.&lt;/p&gt;

&lt;p&gt;With Java 19 introducing newHashMap, developers can finally move away from unclear capacity calculations. And for those still using older versions, enforcing proper usage with tools like ArchUnit is an easy win for code quality.&lt;/p&gt;

&lt;p&gt;At the end of the day, clear API design isn’t just about performance - it’s about making code easier to understand, maintain, and evolve.&lt;/p&gt;

</description>
      <category>java</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Vaadin Flow for AdminUI</title>
      <dc:creator>Mark Andreev</dc:creator>
      <pubDate>Tue, 25 Feb 2025 22:54:19 +0000</pubDate>
      <link>https://dev.to/mrkandreev/vaadin-flow-for-adminui-b8j</link>
      <guid>https://dev.to/mrkandreev/vaadin-flow-for-adminui-b8j</guid>
      <description>&lt;p&gt;Vaadin Flow is a server-driven UI framework that can serve as an alternative to React or Angular, where the frontend exists as a separate codebase written in a different programming language, with a clear boundary for data management (AJAX). For admin UIs, where backend developers manage the interface without deep knowledge of frontend technologies, this approach simplifies the architecture and reduces the overall maintenance effort. I would like to share my experience of adopting this framework.&lt;/p&gt;

&lt;h1&gt;
  
  
  Context
&lt;/h1&gt;

&lt;p&gt;We are specifically dealing with admin UIs, typically have fewer concurrent users but each may have long-running sessions. An example of admin ui is social media moderator room where target users of ui are employees of a company that usually have long sessions. Another major attribute of admin ui is a complex UI with rich business logic, often making it unclear how to split code between frontend and backend.&lt;/p&gt;

&lt;p&gt;All of this allows us to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manage the user's UI state on the backend since we can allocate resources for each user.&lt;/li&gt;
&lt;li&gt;Put functionality ahead of perfect UX, as interface users can be trained. &lt;/li&gt;
&lt;li&gt;Ignore initial loading time, as it is not critical for an admin UI.&lt;/li&gt;
&lt;li&gt;Keep UI-related code alongside the backend, since they are tightly coupled, and no other consumers rely on the same API.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also prefer open-source solutions with free-to-use licenses, as they provide the flexibility to fix critical bugs when needed.&lt;/p&gt;

&lt;h1&gt;
  
  
  Solution
&lt;/h1&gt;

&lt;p&gt;All of this leads us to consider backend-driven UI frameworks like Vaadin Flow, a Java framework for server-rendered UIs. The majority of UI configuration—both layout and behavior—will be written in Java, just like the backend code.&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%2Fjzqn4sh16kpi5fgsaawc.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%2Fjzqn4sh16kpi5fgsaawc.png" alt="Image description" width="418" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For UI pages Vaadin flow provides Routes that can interact directly with spring services without a controllers layer. All state from Vaadin flow route transfers to the user browser using Vaadin internals without extra boilerplates like ajax requests and react subjects. &lt;/p&gt;

&lt;p&gt;For special cases when integration with 3rd party libraries are required there are bridge interfaces with react (&lt;a href="https://vaadin.com/docs/latest/flow/integrations/react" rel="noopener noreferrer"&gt;details&lt;/a&gt;).&lt;br&gt;
UI testing in the free version might be done using Microsoft Playwright or Selenium.&lt;/p&gt;
&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;Enterprise applications often share similar requirements, which are implemented using common building blocks. Since Vaadin is designed for admin UIs and has undergone multiple iterations, you can find well-documented features in its official documentation. While some advanced components are available only in the paid version, with experience and guidance (even from ChatGPT), you can build them yourself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build (maven / gradle)&lt;/li&gt;
&lt;li&gt;Assemble to container (docker)&lt;/li&gt;
&lt;li&gt;Integration with beans management framework (Spring, Quarkus, JBoss CDI)&lt;/li&gt;
&lt;li&gt;Secure using SSO (Authz)&lt;/li&gt;
&lt;li&gt;Shared layout&lt;/li&gt;
&lt;li&gt;Display data grids (tables)&lt;/li&gt;
&lt;li&gt;Display forms with data&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Build
&lt;/h3&gt;

&lt;p&gt;Vaadin supports maven and gradle but documentation is well written only for maven. In some cases you may find bugs caused by gradle groovy to kotlin migration.&lt;/p&gt;
&lt;h3&gt;
  
  
  Containerisation
&lt;/h3&gt;

&lt;p&gt;Vaadin offers a development mode with reduced build times and a production mode that compacts the JavaScript bundle and integrates user-defined components. It’s essential to test your production build to catch any potential build-related bugs early.&lt;/p&gt;

&lt;p&gt;This topic covered by this guide (&lt;a href="https://vaadin.com/docs/latest/flow/production/production-build" rel="noopener noreferrer"&gt;https://vaadin.com/docs/latest/flow/production/production-build&lt;/a&gt; )&lt;/p&gt;
&lt;h3&gt;
  
  
  Integration with beans management framework
&lt;/h3&gt;

&lt;p&gt;Vaadin can be easily integrated with leading Java frameworks like Spring, Quarkus, and CDI. In the case of Spring, Vaadin routes can be treated as Spring components with a web session-like scope, meaning a bean is created per user session and retains state throughout user interactions. This scope is particularly intuitive for form management (covered in next sections).&lt;/p&gt;
&lt;h3&gt;
  
  
  Authz
&lt;/h3&gt;

&lt;p&gt;While “SSO Kit” is a part of paid version you can rely on Spring authz that provides similar functionality. For example, you can delegate this task to Spring security with Keycloak.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring.security.oauth2.client.registration.keycloak.client-id=${keycloak.client-id}
spring.security.oauth2.client.registration.keycloak.scope=openid,profile,email
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.keycloak.redirect-uri=${app.protocol}://${app.host} /login/oauth2/code/{registrationId}
spring.security.oauth2.client.provider.keycloak.issuer-uri=${keycloak.issuer-url}
spring.security.oauth2.client.provider.keycloak.jwk-set-uri=${keycloak.base-url}/protocol/openid-connect/certs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Layouts
&lt;/h3&gt;

&lt;p&gt;As a starting point for hands-on experience, you can use &lt;a href="https://start.vaadin.com/app/p" rel="noopener noreferrer"&gt;Vaadin Start&lt;/a&gt;, which provides an online UI designer and generates related code. Take a closer look at the generated code to better understand AppLayout, which serves as a top-level placeholder for other views, and an example of a user-defined route (view) that extends VerticalLayout or HorizontalLayout.&lt;/p&gt;

&lt;p&gt;Your UI is primarily built using two key layout components: HorizontalLayout and VerticalLayout, both of which can contain other UI components or nested layouts.&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%2Fq6umy4dfcz153buaoupb.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%2Fq6umy4dfcz153buaoupb.png" alt="Image description" width="619" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Data grids
&lt;/h3&gt;

&lt;p&gt;Vaadin calls it com.vaadin.flow.component.grid.Grid (&lt;a href="https://vaadin.com/docs/latest/components/grid" rel="noopener noreferrer"&gt;https://vaadin.com/docs/latest/components/grid&lt;/a&gt; ). It contains sorting, filtering and lazy loading.&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%2Fpfjq7vjwelaht7w3fsok.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%2Fpfjq7vjwelaht7w3fsok.png" alt="Image description" width="357" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Forms
&lt;/h3&gt;

&lt;p&gt;The primary integration layer is com.vaadin.flow.data.binder.Binder, which synchronizes Java Beans with the UI state. It also provides an API for validation using withValidator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// example
var binder = new Binder&amp;lt;&amp;gt;(BusinessPerson.class);

TextField nameField = new TextField();
binder.bind(nameField, BusinessPerson::getName, BusinessPerson::setName);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Felxjr34sjs9s4xt1tsm9.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%2Felxjr34sjs9s4xt1tsm9.png" alt="Image description" width="295" height="123"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This topic covered by &lt;a href="https://vaadin.com/docs/latest/flow/binding-data" rel="noopener noreferrer"&gt;https://vaadin.com/docs/latest/flow/binding-data&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus: long running tasks
&lt;/h3&gt;

&lt;p&gt;You might encounter a situation where each user interaction with a Java service, such as one involving long blocking database interactions, also blocks the user interface. While this may not be a problem for short interactions, long-running tasks, like bulk imports or exports, should be offloaded to threads that are not dedicated to rendering the UI. This approach is like what is done in other rendering frameworks, such as Swing or AWT.&lt;/p&gt;

&lt;p&gt;More details &lt;a href="https://vaadin.com/docs/latest/building-apps/application-layer/background-jobs" rel="noopener noreferrer"&gt;https://vaadin.com/docs/latest/building-apps/application-layer/background-jobs&lt;/a&gt; , &lt;a href="https://vaadin.com/docs/latest/flow/advanced/long-running-tasks" rel="noopener noreferrer"&gt;https://vaadin.com/docs/latest/flow/advanced/long-running-tasks&lt;/a&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Alternatives
&lt;/h1&gt;

&lt;p&gt;Since Vaadin is Java-focused, its major benefits are best realized within that ecosystem. If you're using .NET, &lt;a href="https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blazor" rel="noopener noreferrer"&gt;Blazor&lt;/a&gt; might be a better fit, while in the Python world, a lightweight alternative could be &lt;a href="https://streamlit.io/" rel="noopener noreferrer"&gt;Streamlit&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Author is Mark Andreev, SWE&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>java</category>
      <category>frontend</category>
      <category>programming</category>
    </item>
    <item>
      <title>What is RocksDB (and its role in streaming)?</title>
      <dc:creator>Mark Andreev</dc:creator>
      <pubDate>Mon, 13 May 2024 08:25:51 +0000</pubDate>
      <link>https://dev.to/mrkandreev/what-is-rocksdb-and-its-role-in-streaming-3bla</link>
      <guid>https://dev.to/mrkandreev/what-is-rocksdb-and-its-role-in-streaming-3bla</guid>
      <description>&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%2Fzg6cj6xasn5brdtt0yhb.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%2Fzg6cj6xasn5brdtt0yhb.png" alt="Image description" width="800" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;RocksDB, a high-performance database, is a hidden gem in the tech industry, often overlooked by developers. I’m excited to delve into the intricacies and applications of this powerful tool. Who knows? It might just become the cornerstone of your next project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Originating from Facebook, RocksDB emerged as a potent storage engine designed for server workloads across diverse storage media, with an initial emphasis on high-speed storage, particularly Flash storage. It’s a C++ library that stores keys and values as byte streams of arbitrary sizes. It’s capable of both point lookups and range scans, and offers various ACID guarantees.&lt;/p&gt;

&lt;p&gt;RocksDB strikes a harmonious balance between customizability and self-adaptability. It boasts highly adjustable configuration settings that can be fine-tuned to operate in a wide range of production environments, including SSDs, hard disks, ramfs, or remote storage. It supports a variety of compression algorithms and provides robust tools for production support and debugging. Simultaneously, efforts are made to limit the number of adjustable parameters, ensuring satisfactory out-of-box performance and implementing adaptive algorithms where suitable.&lt;/p&gt;

&lt;p&gt;RocksDB incorporates substantial code from the open-source leveldb project and ideas from Apache HBase. The initial codebase was a fork from open-source leveldb. Furthermore, it builds upon code and concepts that were developed at Facebook prior to the inception of RocksDB.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;The fundamental design principle of RocksDB is its performance optimization for fast storage and server workloads. It is engineered to facilitate efficient point lookups and range scans. Its configurability allows it to support high random-read workloads, high update workloads, or a blend of both. The architecture of RocksDB is designed to easily adjust trade-offs to cater to different workloads and hardware configurations.&lt;/p&gt;

&lt;p&gt;RocksDB serves as a storage engine library, providing a key-value store interface where keys and values are represented as arbitrary byte streams. It arranges all data in a sorted sequence, and the typical operations include &lt;code&gt;Get(key)&lt;/code&gt;, &lt;code&gt;NewIterator()&lt;/code&gt;, &lt;code&gt;Put(key, val)&lt;/code&gt;, &lt;code&gt;Delete(key)&lt;/code&gt;, and &lt;code&gt;SingleDelete(key)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;RocksDB does not natively support SQL. While it does not have a relational data model and does not support SQL queries, it can be used in conjunction with other systems or frameworks that provide SQL-like querying capabilities. For example, MyRocks combines RocksDB with MySQL. However, it’s important to note that RocksDB itself does not natively support SQL. It also does not have direct support for secondary indexes, but a user may build their own internally using Column Families or externally. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The main features are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Designed for application servers wanting to store up to a few terabytes of data on local or remote storage systems.&lt;/li&gt;
&lt;li&gt;Optimized for storing small to medium size key-values on fast storage -- flash devices or in-memory&lt;/li&gt;
&lt;li&gt;It works well on processors with many cores&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;For read &amp;amp; write workload, rocksdb should be opened by a single process. RocksDB has the capability to support a multi-process read-only operation without any write operations to the database. This can be achieved by invoking the DB::OpenForReadOnly() method to open the database. &lt;/p&gt;

&lt;p&gt;RocksDB was initially released as an open-source project under the BSD 3-clause license. However, in July 2017, the licensing of RocksDB was changed to a dual license model, incorporating both Apache 2.0 and GPLv2. This change was significant as it enabled RocksDB’s integration into projects under the Apache Software Foundation, which had previously blacklisted the BSD+Patents license clause. The dual-license information is available in the root directory of the RocksDB repository on GitHub. For the most recent updates, you may want to check the official RocksDB GitHub repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Applications
&lt;/h2&gt;

&lt;p&gt;RocksDB is widely used in stream processing frameworks like Apache Flink, serving as a fast and efficient state store for maintaining the state of streaming applications. It’s also utilized in web applications for caching and session storage due to its efficient memory utilization and fast read/write operations. Additionally, RocksDB serves as a storage engine in database systems like TiKV that require high performance and durability, and is used in embedded systems such as IoT devices or edge computing applications due to its small memory footprint and light design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Streaming&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Streaming and batching are two different methods of processing data, each with its own use cases and advantages.&lt;/p&gt;

&lt;p&gt;Streaming is a data processing method where each data item is processed individually and in real time as soon as it arrives. It’s like a water stream, where data flows continuously. This method is particularly useful when you need to process live data, such as real-time analytics, live monitoring systems, or real-time recommendations. The advantage of streaming is that it provides real-time or near-real-time insights. However, it can be more complex to implement and requires a robust infrastructure to handle continuous data flow.&lt;/p&gt;

&lt;p&gt;On the other hand, batching is a method where data is collected over a period of time and processed all at once. It’s like filling a bucket with water and then processing all the water at once. This method is often used when the data doesn’t need to be processed in real time, such as daily reports, historical data analysis, or large ETL (Extract, Transform, Load) jobs. The advantage of batching is that it’s simpler to implement and can be more cost-effective, as it allows for resource optimization. However, it doesn’t provide real-time insights and can be slower, as you need to wait for the batch to be completed before you can process the data.&lt;/p&gt;

&lt;p&gt;In summary, the choice between streaming and batching depends on your specific use case and requirements. If you need real-time insights, streaming is the way to go. If you’re dealing with large volumes of data and don’t need real-time processing, batching could be a more efficient choice. As a data engineer, it’s crucial to understand these differences to make the best decision for your data processing needs.&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%2F59dawfzx2ea94gz1phq2.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%2F59dawfzx2ea94gz1phq2.png" alt="Image description" width="800" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Streaming. Apache Flink
&lt;/h3&gt;

&lt;p&gt;Applications that process streams often have a stateful nature, meaning they retain information from events they’ve processed to influence the processing of future events. In the context of Flink, this retained information, or state, is locally stored in a state backend that’s been configured. To safeguard against data loss during failures, the state backend periodically takes a snapshot of its contents and stores it in a durable storage that’s been pre-configured.&lt;br&gt;
Among the three built-in state backends in Flink, the RocksDB state backend (also known as RocksDBStateBackend) is one. &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%2Fucyyb135l3i1dnojil7x.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%2Fucyyb135l3i1dnojil7x.png" alt="Image description" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find example of usage in &lt;code&gt;org/apache/flink/contrib/streaming/state&lt;/code&gt; package  (&lt;a href="https://github.com/apache/flink/tree/9fe8d7bf870987bf43bad63078e2590a38e4faf6/flink-state-backends/flink-statebackend-rocksdb/src/main/java/org/apache/flink/contrib/streaming/state" rel="noopener noreferrer"&gt;https://github.com/apache/flink/tree/9fe8d7bf870987bf43bad63078e2590a38e4faf6/flink-state-backends/flink-statebackend-rocksdb/src/main/java/org/apache/flink/contrib/streaming/state&lt;/a&gt;).&lt;/p&gt;
&lt;h3&gt;
  
  
  Streaming. Kafka Streams &amp;amp; KSQL
&lt;/h3&gt;

&lt;p&gt;Kafka Streams and KSQL use RocksDB as their default storage engine for stateful operations.In KSQL, RocksDB is used to store the materialized view locally on its disk. RocksDB is an embedded key/value store that runs in process in each KSQL server. You do not need to start, manage, or interact with it. This allows KSQL to execute stateful operations efficiently and reliably.&lt;/p&gt;

&lt;p&gt;You can find example of usage in RocksDBStore class (&lt;a href="https://github.com/a0x8o/kafka/blob/master/streams/src/main/java/org/apache/kafka/streams/state/internals/RocksDBStore.java" rel="noopener noreferrer"&gt;https://github.com/a0x8o/kafka/blob/master/streams/src/main/java/org/apache/kafka/streams/state/internals/RocksDBStore.java&lt;/a&gt;).&lt;/p&gt;
&lt;h3&gt;
  
  
  CockroachDB
&lt;/h3&gt;

&lt;p&gt;CockroachDB is a distributed SQL database system developed by Cockroach Labs. It is designed to be resilient and consistent, much like its namesake, the cockroach. The system is known for its scalability, high availability, and versatility. It can handle increasing loads by adding more nodes, ensures data is always accessible, and can be run in various environments.&lt;/p&gt;

&lt;p&gt;One of the key features of CockroachDB is its compatibility with PostgreSQL. It supports the PostgreSQL wire protocol and the majority of PostgreSQL syntax. This means that existing applications built on PostgreSQL can often be migrated to CockroachDB without changing application code. However, it’s important to note that CockroachDB does not support some of the PostgreSQL features or behaves differently from PostgreSQL because not all features can be easily implemented in a distributed system.&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%2Fl78objwdu58k5y2icd5v.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%2Fl78objwdu58k5y2icd5v.png" alt="Image description" width="800" height="554"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CockroachDB uses RocksDB as its underlying storage engine. The architecture of CockroachDB is divided into two layers: the SQL layer and the storage layer. The SQL layer sits on top of a transactional and strongly-consistent distributed key-value store.&lt;/p&gt;

&lt;p&gt;In this key-value store, the key ranges are divided and stored in RocksDB. This allows CockroachDB to leverage the efficient storage mechanism of RocksDB while providing the benefits of a SQL interface. The data stored in RocksDB is replicated across the cluster, enhancing the resilience of the system. This design choice enables CockroachDB to handle large-scale, distributed storage while maintaining high performance and strong consistency.&lt;/p&gt;

&lt;p&gt;You can find details about RocksDB usage in CockroachDB at their blog &lt;a href="https://www.cockroachlabs.com/blog/cockroachdb-on-rocksd/" rel="noopener noreferrer"&gt;https://www.cockroachlabs.com/blog/cockroachdb-on-rocksd/&lt;/a&gt; &lt;/p&gt;
&lt;h3&gt;
  
  
  TiKV
&lt;/h3&gt;

&lt;p&gt;TiKV, short for “Ti Key-Value”, is an open-source, distributed, and transactional key-value database. It’s designed to handle vast amounts of data while ensuring strong consistency and reliability. Unlike traditional NoSQL systems, TiKV provides both classical key-value APIs and transactional APIs with ACID compliance.&lt;/p&gt;

&lt;p&gt;Built in Rust and powered by the Raft consensus algorithm, TiKV was originally created by PingCAP to complement TiDB, a distributed HTAP (Hybrid Transactional and Analytical Processing) database compatible with the MySQL protocol. The design of TiKV is inspired by some great distributed systems from Google, such as BigTable, Spanner, and Percolator, and some of the latest achievements in academia in recent years, such as the Raft consensus algorithm.&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%2Fug8cnzwwcknzsm4zxq8x.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%2Fug8cnzwwcknzsm4zxq8x.png" alt="Image description" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TiKV uses RocksDB as its primary storage layer. This design choice allows TiKV to handle large-scale, distributed storage while maintaining high performance and strong consistency.&lt;/p&gt;

&lt;p&gt;In TiKV’s architecture, data is stored as key-value pairs. The keys are divided into ranges, and each range of keys is stored in RocksDB. This allows TiKV to leverage the efficient storage mechanism of RocksDB.&lt;/p&gt;

&lt;p&gt;TiKV also uses the Raft consensus algorithm for data replication. For every write request, TiKV first writes the request to the Raft log. After the log is committed, TiKV applies the Raft log and writes the data to RocksDB. This ensures data consistency across multiple replicas in the cluster.&lt;/p&gt;

&lt;p&gt;Moreover, TiKV uses a feature of RocksDB called Prefix Bloom Filter (PBF). PBF can filter out data which is impossible to contain keys with the same prefix as the row key provided. This is particularly useful in TiKV’s multi-version concurrency control (MVCC) model, where multiple versions of the same row share the same prefix. This feature enhances the efficiency of read operations.&lt;/p&gt;

&lt;p&gt;In summary, RocksDB plays a crucial role in TiKV’s ability to provide a reliable, high-performance distributed storage solution.&lt;/p&gt;
&lt;h3&gt;
  
  
  Apache Kvrocks
&lt;/h3&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%2Fi2uu459akl8rh9xoj53n.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%2Fi2uu459akl8rh9xoj53n.png" alt="Image description" width="465" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Apache Kvrocks, a distributed key-value NoSQL database, utilizes RocksDB as its storage engine and is designed to be compatible with the Redis protocol.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Kvrocks has the following key features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redis Compatible: Users can access Apache Kvrocks via any Redis client.&lt;/li&gt;
&lt;li&gt;Namespace: Similar to Redis SELECT but equipped with token per namespace.&lt;/li&gt;
&lt;li&gt;Replication: Async replication using binlog like MySQL.&lt;/li&gt;
&lt;li&gt;High Availability: Support Redis sentinel to failover when master or slave was failed.&lt;/li&gt;
&lt;li&gt;Cluster: Centralized management but accessible via any Redis cluster client.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can find details in their official documentation &lt;a href="https://kvrocks.apache.org/community/data-structure-on-rocksdb/" rel="noopener noreferrer"&gt;https://kvrocks.apache.org/community/data-structure-on-rocksdb/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Use in application
&lt;/h2&gt;

&lt;p&gt;RocksDB is an embedded database, which means it is designed to be integrated directly into your application. Unlike standalone database systems, an embedded database like RocksDB operates as an integral part of your application, allowing for efficient data management and storage within the application itself. This can lead to improved performance and easier data handling, as the database operations are closely tied to the application’s functionality. However, it also means that the application is responsible for the direct management of the database.&lt;/p&gt;
&lt;h3&gt;
  
  
  C++
&lt;/h3&gt;

&lt;p&gt;In C++ you can operate with database using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.&lt;/span&gt;
&lt;span class="c1"&gt;//  This source code is licensed under both the GPLv2 (found in the&lt;/span&gt;
&lt;span class="c1"&gt;//  COPYING file in the root directory) and Apache 2.0 License&lt;/span&gt;
&lt;span class="c1"&gt;//  (found in the LICENSE.Apache file in the root directory).&lt;/span&gt;

&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;cstdio&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"rocksdb/db.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"rocksdb/options.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"rocksdb/slice.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;ROCKSDB_NAMESPACE&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;ROCKSDB_NAMESPACE&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;ROCKSDB_NAMESPACE&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;PinnableSlice&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;ROCKSDB_NAMESPACE&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ReadOptions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;ROCKSDB_NAMESPACE&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;ROCKSDB_NAMESPACE&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;WriteBatch&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;ROCKSDB_NAMESPACE&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;WriteOptions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cp"&gt;#if defined(OS_WIN)
&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;kDBPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"C:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;Windows&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;TEMP&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;rocksdb_simple_example"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="cp"&gt;#else
&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;kDBPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/tmp/rocksdb_simple_example"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="cp"&gt;#endif
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Options&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Optimize RocksDB. This is the easiest way to get RocksDB to perform well&lt;/span&gt;
  &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IncreaseParallelism&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OptimizeLevelStyleCompaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// create the DB if it's not already present&lt;/span&gt;
  &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_if_missing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// open DB&lt;/span&gt;
  &lt;span class="n"&gt;Status&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kDBPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

  &lt;span class="c1"&gt;// Put key-value&lt;/span&gt;
  &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WriteOptions&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"key1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// get value&lt;/span&gt;
  &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ReadOptions&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"key1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// atomically apply a set of updates&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;WriteBatch&lt;/span&gt; &lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"key1"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"key2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WriteOptions&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ReadOptions&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"key1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsNotFound&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

  &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ReadOptions&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"key2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;PinnableSlice&lt;/span&gt; &lt;span class="n"&gt;pinnable_val&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ReadOptions&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;DefaultColumnFamily&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"key2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pinnable_val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pinnable_val&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;string_val&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// If it cannot pin the value, it copies the value to its internal buffer.&lt;/span&gt;
    &lt;span class="c1"&gt;// The intenral buffer could be set during construction.&lt;/span&gt;
    &lt;span class="n"&gt;PinnableSlice&lt;/span&gt; &lt;span class="n"&gt;pinnable_val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;string_val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ReadOptions&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;DefaultColumnFamily&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"key2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pinnable_val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pinnable_val&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// If the value is not pinned, the internal buffer must have the value.&lt;/span&gt;
    &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pinnable_val&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsPinned&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;string_val&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;PinnableSlice&lt;/span&gt; &lt;span class="n"&gt;pinnable_val&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ReadOptions&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;DefaultColumnFamily&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"key1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pinnable_val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsNotFound&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="c1"&gt;// Reset PinnableSlice after each use and before each reuse&lt;/span&gt;
  &lt;span class="n"&gt;pinnable_val&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ReadOptions&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;DefaultColumnFamily&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"key2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pinnable_val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pinnable_val&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;pinnable_val&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// The Slice pointed by pinnable_val is not valid after this point&lt;/span&gt;

  &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find details in official wiki in github &lt;a href="https://github.com/facebook/rocksdb/wiki/Basic-Operations" rel="noopener noreferrer"&gt;https://github.com/facebook/rocksdb/wiki/Basic-Operations&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Java
&lt;/h3&gt;

&lt;p&gt;RocksJava is an initiative aimed at developing a Java driver for RocksDB that is both high-performing and user-friendly.&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;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;org.rocksdb&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;rocksdbjni&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;6.6.4&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can open a database using&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.rocksdb.RocksDB&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.rocksdb.RocksDBException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.rocksdb.Options&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="c1"&gt;// a static method that loads the RocksDB C++ library.&lt;/span&gt;
  &lt;span class="nc"&gt;RocksDB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;loadLibrary&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// the Options class contains a set of configurable DB options&lt;/span&gt;
  &lt;span class="c1"&gt;// that determines the behaviour of the database.&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Options&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Options&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;setCreateIfMissing&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// a factory method that returns a RocksDB instance&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;RocksDB&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RocksDB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;open&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"path/to/db"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// do something&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RocksDBException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// do some error handling&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And do some read and write operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;key2&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// some initialization for key1 and key2&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  &lt;span class="c1"&gt;// value == null if key1 does not exist in db.&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RocksDBException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// error handling&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find details in official documentation &lt;a href="https://github.com/facebook/rocksdb/wiki/RocksJava-Basics" rel="noopener noreferrer"&gt;https://github.com/facebook/rocksdb/wiki/RocksJava-Basics&lt;/a&gt; &lt;/p&gt;

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

&lt;p&gt;In conclusion, RocksDB is an excellent solution for managing persistent state on disk due to its high performance and efficient key-value storage. It’s particularly well-suited for applications that require fast, low-latency access to disk-based data. However, if your needs extend to larger-scale distributed state management or constraint management, more abstract databases such as MySQL might be a better fit. MySQL, being a relational database, offers features like transactional support, advanced querying capabilities, and robustness in handling complex data relationships, making it more suitable for these more complex scenarios. Therefore, the choice between RocksDB and MySQL (or any other database) should be guided by the specific requirements of your application.&lt;/p&gt;




&lt;p&gt;Author is Mark Andreev, SWE @ Conundrum.AI&lt;/p&gt;

</description>
      <category>database</category>
      <category>java</category>
      <category>cpp</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to create Unit tests for code design?</title>
      <dc:creator>Mark Andreev</dc:creator>
      <pubDate>Mon, 15 Apr 2024 08:56:20 +0000</pubDate>
      <link>https://dev.to/mrkandreev/how-to-create-unit-tests-for-code-design-5g9i</link>
      <guid>https://dev.to/mrkandreev/how-to-create-unit-tests-for-code-design-5g9i</guid>
      <description>&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%2Fl1f9xbhgpix0oh7fytjh.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%2Fl1f9xbhgpix0oh7fytjh.png" alt="Preview picture" width="593" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a seasoned software engineer, I understand the importance of well-designed code and the role of unit tests in maintaining its integrity. Code design is the foundation of any software system. It's the blueprint that guides the construction of the system, ensuring that the final product is robust, scalable, and maintainable. A well-designed codebase is easy to understand, modify, and extend, making it resilient to the ever-changing demands of the business environment.&lt;/p&gt;

&lt;p&gt;Consistent code design is crucial for a team's productivity and the long-term maintainability of a project. However, achieving it is not a trivial task. It requires clear communication, shared understanding, and discipline from all team members. The difficulty lies in the fact that each developer has their unique coding style and problem-solving approach. Over time, without a concerted effort to maintain consistency, the codebase can become a patchwork of different styles and patterns, making it hard to understand and maintain.&lt;/p&gt;

&lt;p&gt;I would like to share an approach based on ArchUnit - unit tests for your code.&lt;/p&gt;

&lt;p&gt;ArchUnit is a powerful library developed by TNG that brings architectural control right into your codebase. The core idea of the project is to validate architectural rules in your Java codebase, ensuring that the design principles and standards you’ve set are being adhered to.&lt;/p&gt;

&lt;p&gt;The library provides a domain-specific language (DSL) that allows you to express architectural rules in a clear, concise manner. This makes it easier for developers to understand and enforce these rules, leading to a more consistent and maintainable codebase.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@AnalyzeClasses&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"com.tngtech.archunit.example.layers"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MethodsTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@ArchTest&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;ArchRule&lt;/span&gt; &lt;span class="n"&gt;codeUnitsInDAOLayerShouldNotBeSecured&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="n"&gt;noCodeUnits&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;that&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;areDeclaredInClassesThat&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;resideInAPackage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"..persistence.."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;should&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;beAnnotatedWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Secured&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;One of the main benefits of using ArchUnit is its ability to catch architectural violations early. Instead of waiting for code reviews or architectural audits, ArchUnit can identify issues as soon as the code is written. This leads to quicker feedback and less technical debt.&lt;/p&gt;

&lt;p&gt;Furthermore, ArchUnit is flexible and extensible, allowing you to define custom rules that fit your project’s unique needs. It integrates seamlessly with popular testing frameworks like JUnit, making it a natural fit for any Java project.&lt;/p&gt;

&lt;p&gt;For example you can disable JUnit Assertions when you prefer AssertJ library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Test&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;isTestClassesDontUseJunitAssertions&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;ArchRuleDefinition&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;noClasses&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;should&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dependOnClassesThat&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;haveNameMatching&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"org.junit.jupiter.api.Assertions"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;check&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;importedTestClasses&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or for Spring you can add restrictions for Controller names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Test&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;controllerNameRule&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;classes&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;that&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;areAnnotatedWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RestController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;should&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;haveSimpleNameContaining&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Controller"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;check&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;importedClasses&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or even check Validation usage in RequestBody:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Test&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;restControllerValidationRule&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;classes&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;that&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;areAnnotatedWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RestController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;should&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;beAnnotatedWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Validated&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;check&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;importedClasses&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Test&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;restControllerValidationRequestBodyRule&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;classes&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;that&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;areAnnotatedWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RestController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;should&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArchCondition&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"Any @RequestBody must be @Valid"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
              &lt;span class="nd"&gt;@Override&lt;/span&gt;
              &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;check&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JavaClass&lt;/span&gt; &lt;span class="n"&gt;javaClass&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ConditionEvents&lt;/span&gt; &lt;span class="n"&gt;conditionEvents&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JavaMethod&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;javaClass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMethods&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isConstructor&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
                  &lt;span class="o"&gt;}&lt;/span&gt;

                  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Parameter&lt;/span&gt; &lt;span class="n"&gt;parameter&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reflect&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getParameters&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parameter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isAnnotationPresent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RequestBody&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                        &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;parameter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isAnnotationPresent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Valid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                      &lt;span class="n"&gt;conditionEvents&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                          &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SimpleConditionEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                              &lt;span class="n"&gt;javaClass&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                              &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                              &lt;span class="n"&gt;javaClass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                                  &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" contains method "&lt;/span&gt;
                                  &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;
                                  &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" with @RequestBody and without Valid"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
                    &lt;span class="o"&gt;}&lt;/span&gt;
                  &lt;span class="o"&gt;}&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
              &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;})&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;check&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;importedClasses&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Absolutely, one of the powerful features of ArchUnit is its predefined rules. These rules provide a solid foundation for enforcing architectural standards in your Java codebase. They cover a wide range of common architectural scenarios, making it easier for you to get started with architectural control.&lt;/p&gt;

&lt;p&gt;These predefined rules can be used as-is, or they can serve as a starting point for creating your own custom rules. This flexibility allows you to tailor ArchUnit to the specific needs of your project, ensuring that your architectural standards are upheld in a way that makes sense for your team and your codebase.&lt;/p&gt;

&lt;p&gt;In essence, ArchUnit’s predefined rules are a valuable tool for maintaining architectural integrity, reducing technical debt, and enhancing the overall quality of your code. They are a testament to the library’s power and versatility, making it an essential tool for any Java developer serious about architecture.&lt;/p&gt;

&lt;p&gt;You can found general predefined rules in com.tngtech.archunit.library.GeneralCodingRules like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NO_CLASSES_SHOULD_ACCESS_STANDARD_STREAMS&lt;/li&gt;
&lt;li&gt;NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS&lt;/li&gt;
&lt;li&gt;NO_CLASSES_SHOULD_USE_JODATIME&lt;/li&gt;
&lt;li&gt;NO_CLASSES_SHOULD_USE_JAVA_UTIL_LOGGING&lt;/li&gt;
&lt;li&gt;NO_CLASSES_SHOULD_USE_FIELD_INJECTION&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And dependency rules available in com.tngtech.archunit.library.DependencyRules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NO_CLASSES_SHOULD_DEPEND_UPPER_PACKAGES&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More examples you can find at official user guide &lt;a href="https://www.archunit.org/userguide/html/000_Index.html" rel="noopener noreferrer"&gt;https://www.archunit.org/userguide/html/000_Index.html&lt;/a&gt; or at github repository &lt;a href="https://github.com/TNG/ArchUnit" rel="noopener noreferrer"&gt;https://github.com/TNG/ArchUnit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In summary, ArchUnit is a valuable tool for maintaining the integrity of your codebase’s architecture, promoting consistency, reducing technical debt, and enhancing overall code quality. It’s a must-have for any team serious about architecture.&lt;/p&gt;

&lt;p&gt;Author is Mark Andreev, SWE @ Conundrum.ai&lt;/p&gt;

</description>
      <category>java</category>
      <category>webdev</category>
      <category>testing</category>
      <category>programming</category>
    </item>
    <item>
      <title>Enhance Your Project Quality with These Top Python Libraries</title>
      <dc:creator>Mark Andreev</dc:creator>
      <pubDate>Mon, 18 Mar 2024 14:15:00 +0000</pubDate>
      <link>https://dev.to/mrkandreev/enhance-your-project-quality-with-these-top-python-libraries-2ln5</link>
      <guid>https://dev.to/mrkandreev/enhance-your-project-quality-with-these-top-python-libraries-2ln5</guid>
      <description>&lt;p&gt;In the ever-evolving landscape of software development, Python has emerged as a language of choice for programmers worldwide. Its simplicity, versatility, and robust library support have made it a favourite among both beginners and seasoned developers. This article, titled “Enhance Your Project Quality with These Top Python Libraries”, aims to guide you through some of the most powerful and efficient Python libraries that can significantly enhance the quality of your projects.&lt;/p&gt;

&lt;p&gt;Python’s extensive collection of libraries is one of its most attractive features. These libraries, each with its unique capabilities, can simplify complex tasks, reduce coding time, and increase the efficiency and performance of your projects. Whether you’re working on data analysis, machine learning, web development, or any other domain, Python has a library that can make your job easier. Please note that while this article aims to be as comprehensive and accurate as possible, the world of Python libraries is vast and constantly evolving. Therefore, I encourage readers to continue exploring and experimenting beyond what is covered here.&lt;/p&gt;

&lt;p&gt;In the realm of software development, the quality of code is paramount. It is the bedrock upon which reliable, efficient, and maintainable software is built. The main components that contribute to code quality include code style, linters, code formatters, type checking, unit tests, and documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code style
&lt;/h2&gt;

&lt;p&gt;Code style is the set of conventions and guidelines that developers adhere to when writing code. It ensures consistency, readability, and understandability across the codebase, making it easier for others to read and maintain. Code formatters automatically format code according to a specified style guide. They save developers time and effort, and ensure that the codebase has a consistent look and feel.&lt;/p&gt;

&lt;p&gt;There are several Python libraries that can help improve code style:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/PyCQA/pycodestyle" rel="noopener noreferrer"&gt;PEP8 (pycodestyle)&lt;/a&gt;: Named after Python’s PEP 8 style guide, this tool checks your Python code against some of the style conventions in PEP 8.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/psf/black" rel="noopener noreferrer"&gt;Black&lt;/a&gt;: Known as “The Uncompromising Code Formatter”, Black automatically formats your Python code to conform to the PEP 8 style guide. It takes away the hassle of having to manually adjust your code style.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pycqa.github.io/isort/" rel="noopener noreferrer"&gt;isort&lt;/a&gt;: This library sorts your imports alphabetically, and automatically separates them into sections and by type. It provides a cleaner and more organised way to manage project imports.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/google/yapf" rel="noopener noreferrer"&gt;YAPF&lt;/a&gt; (Yet Another Python Formatter): YAPF takes a different approach in that it’s based off of ‘clang-format’, a popular formatter for C++ code. YAPF reformats Python code so that it conforms to the style guide and looks good.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pypi.org/project/autopep8/" rel="noopener noreferrer"&gt;AutoPEP8&lt;/a&gt;: This tool automatically formats Python code to conform to the PEP 8 style guide. It uses pycodestyle, a library that encapsulates the functionality of the original pep8 tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These libraries can be integrated into your development environment or used as part of your continuous integration pipeline to ensure that all code adheres to your project’s style guidelines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Linters
&lt;/h2&gt;

&lt;p&gt;Linters are tools that analyse code to detect potential errors, bugs, stylistic errors, and suspicious constructs. They enforce a level of quality and consistency, and help developers avoid common pitfalls and mistakes.&lt;/p&gt;

&lt;p&gt;Linting is an essential part of writing clean, error-free Python code. Here are some Python linter libraries that are widely used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://pypi.org/project/pylint/" rel="noopener noreferrer"&gt;Pylint&lt;/a&gt;. This is one of the most popular and comprehensive linter tools for Python. Pylint checks for errors, tries to enforce coding standards, and looks for bad smells in your code. It also provides useful features such as checking line-code’s length, checking if variable names are well-formed according to your coding standard, and more.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/PyCQA/flake8" rel="noopener noreferrer"&gt;Flake8&lt;/a&gt;. This library is a wrapper around pycodestyle (PEP8), pyflakes, and Ned Batchelder’s McCabe script. It is a great toolkit for checking your code base against coding style (PEP8), programming errors (like SyntaxError, NameError, etc) and to check cyclomatic complexity.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pypi.org/project/pyflakes/" rel="noopener noreferrer"&gt;Pyflakes&lt;/a&gt; is a simple program that checks Python source files for errors. It is similar to PyLint but focuses only on errors, not style. This makes it faster and less intrusive than some other tools.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/PyCQA/bandit" rel="noopener noreferrer"&gt;Bandit&lt;/a&gt; is a tool designed to find common security issues in Python code. It was developed by the OpenStack Security Project and is a great addition to any serious Python project.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/astral-sh/ruff" rel="noopener noreferrer"&gt;Ruff&lt;/a&gt; is a Python linter that helps to identify and remove code smells. Over 700 built-in rules: Ruff includes native re-implementations of popular Flake8 plugins, like flake8-bugbear. And also built-in caching to avoid re-analyzing unchanged files. &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/klen/pylama" rel="noopener noreferrer"&gt;Pylama&lt;/a&gt; is a code audit tool for Python that wraps tools like Pylint, pycodestyle, PyFlakes, McCabe, and others to provide a unified interface.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://prospector.landscape.io/en/master/" rel="noopener noreferrer"&gt;Prospector&lt;/a&gt;  is a Python static analysis tool that combines multiple Python linters for a more comprehensive error check.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These linter libraries can be integrated into your development environment or used as part of your continuous integration pipeline to ensure that all code adheres to your project’s style guidelines and is free from common errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Type checking
&lt;/h2&gt;

&lt;p&gt;Type checking is the process of verifying and enforcing the constraints of types. It can catch and prevent many types of bugs, making the code safer and more predictable.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://mypy.readthedocs.io/en/stable/getting_started.html" rel="noopener noreferrer"&gt;Mypy&lt;/a&gt; is a static type checker for Python that combines the benefits of dynamic typing and static typing. Mypy checks that the types of variable values match their declared types, and it can catch a whole class of bugs before the code is even run.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/microsoft/pyright" rel="noopener noreferrer"&gt;Pyright&lt;/a&gt; is a fast type checker meant for large Python source bases. It can run in a “watch” mode and performs fast incremental updates when files are modified.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://google.github.io/pytype/" rel="noopener noreferrer"&gt;Pytype&lt;/a&gt; checks and infers types for your Python code - without requiring type annotations. Pytype can catch type errors in your Python code before you even run it.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pyre-check.org/" rel="noopener noreferrer"&gt;Pyre&lt;/a&gt; is a performant type-checker developed by Facebook. Pyre can analyse codebases with millions of lines of code incrementally – providing instantaneous feedback to developers as they write code.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Instagram/MonkeyType" rel="noopener noreferrer"&gt;MonkeyType&lt;/a&gt; collects runtime types of function arguments and return values, and can automatically generate stub files or add type annotations directly to your Python code based on the types collected at runtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these libraries has its own strengths and weaknesses, and the choice between them often depends on the specific needs of the project. It’s also worth noting that these tools are most effective when used in conjunction with good testing practices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Unit tests
&lt;/h2&gt;

&lt;p&gt;Unit tests are small, isolated tests that verify the functionality of a specific section of code. They provide a safety net, allowing developers to refactor and add features with confidence.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.pytest.org/en/8.0.x/" rel="noopener noreferrer"&gt;PyTest&lt;/a&gt; is a mature full-featured Python testing tool that helps you write better programs. It provides a simple and easy way to write tests and has a powerful set of features. PyTest allows for compact test suites and introduces the concept that Python tests should be plain Python functions instead of forcing developers to include their tests inside large test classes.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.python.org/3/library/unittest.html" rel="noopener noreferrer"&gt;Unittest&lt;/a&gt; is a built-in module of Python. It’s inspired by the xUnit framework architecture. This is a great tool to create and organise test cases in a systematic way. You can use unittest.mock with pytest when you need to create mock objects in your tests. The unittest.mock module is a powerful feature in Python’s standard library for creating mock objects in your tests. It allows you to replace parts of your system under test and make assertions about how they have been used. So, even though pytest is a different testing framework, it can work seamlessly with unittest.mock for creating and using mock objects.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.python.org/3/library/doctest.html" rel="noopener noreferrer"&gt;DocTest&lt;/a&gt; is another module that’s part of the Python standard library. It searches for pieces of text that look like interactive Python sessions in docstrings, and then executes those sessions to verify that they work exactly as shown.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tox.wiki/" rel="noopener noreferrer"&gt;Tox&lt;/a&gt; is a powerful tool in Python development, primarily used for automating and standardised testing across multiple environments. It’s part of a larger vision of easing the packaging, testing, and release process of Python software. You should consider using tox in the following scenarios if your application needs to run across different Python versions, tox can help ensure your code works consistently across all these versions; If your project has complex dependencies, tox can manage and isolate these dependencies in different environments.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hypothesis.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;Hypothesis&lt;/a&gt; is a Python library for creating unit tests that are simpler to write and more powerful when run, finding edge cases in your code you wouldn’t have thought to look for. It is stable, powerful, and easy to add to any existing test suite. It allows you to write tests that assert that something should be true for every case, not just the ones you happen to think of. This approach is often called property-based testing, and was popularised by the Haskell library Quickcheck. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Documentation
&lt;/h2&gt;

&lt;p&gt;Documentation is the written text that accompanies the code, explaining how it works and how to use it. Good documentation makes the codebase accessible and understandable to others, and serves as a valuable reference.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.sphinx-doc.org/en/master/" rel="noopener noreferrer"&gt;Sphinx&lt;/a&gt; is a tool that makes it easy to create intelligent and beautiful documentation. It was originally created for the Python documentation, and it has excellent facilities for the documentation of Python projects, but C/C++ is already supported as well, and it is planned to add special support for other languages as well.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.mkdocs.org/" rel="noopener noreferrer"&gt;MkDocs&lt;/a&gt; is a fast, simple and downright gorgeous static site generator that’s geared towards building project documentation. Documentation source files are written in Markdown, and configured with a single YAML configuration file.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.python.org/3/library/pydoc.html" rel="noopener noreferrer"&gt;Pydoc&lt;/a&gt; is a module in Python that generates documentation for modules, scripts, and classes. Pydoc provides a way to access Python’s built-in documentation strings and provides an interface for viewing the documentation in a user-friendly format.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.readthedocs.io/en/stable/tutorial/index.html" rel="noopener noreferrer"&gt;Read the Docs&lt;/a&gt; simplifies software documentation by automating building, versioning, and hosting of your docs for you.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.doxygen.nl/" rel="noopener noreferrer"&gt;Doxygen&lt;/a&gt; is a documentation generator, a tool for writing software reference documentation. The documentation is written within code, and is thus relatively easy to keep up to date. Doxygen can cross reference documentation and code, so that the reader of a document can easily refer to the actual code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember that code quality is a continuous process. Regularly review and refactor your code to maintain high standards. Happy coding! &lt;/p&gt;

&lt;p&gt;Author is Mark Andreev, SWE @ Conundrum.ai &lt;/p&gt;

</description>
      <category>python</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
