<?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: Lori-Shu</title>
    <description>The latest articles on DEV Community by Lori-Shu (@lorishu).</description>
    <link>https://dev.to/lorishu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3968337%2F8e47296c-e45d-440a-a8d1-8667409160db.png</url>
      <title>DEV Community: Lori-Shu</title>
      <link>https://dev.to/lorishu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lorishu"/>
    <language>en</language>
    <item>
      <title>The Basic Animation Mechanism in Egui</title>
      <dc:creator>Lori-Shu</dc:creator>
      <pubDate>Sat, 11 Jul 2026 14:02:27 +0000</pubDate>
      <link>https://dev.to/lorishu/the-basic-animation-mechanism-in-egui-3lbh</link>
      <guid>https://dev.to/lorishu/the-basic-animation-mechanism-in-egui-3lbh</guid>
      <description>&lt;p&gt;As an immediate-mode UI framework, egui handles animations in a fundamentally different way from traditional retained-mode UI frameworks. Instead of maintaining an explicit animation object, egui provides helper functions such as &lt;code&gt;ui.animate_bool_with_time() -&amp;gt; f32&lt;/code&gt; to track animation progress internally.&lt;br&gt;
The method takes three arguments: an Id (a unique identifier for the animation state), a Boolean flag, and a duration specified as a 32-bit floating-point value. Internally, the egui runtime caches a floating-point state associated with the given Id. This value smoothly transitions from 0.0 to 1.0, or reverses from 1.0 back to 0.0, depending on the state change of the Boolean flag.&lt;br&gt;
During each repaint cycle, egui retrieves the cached animation state using the corresponding Id and updates its progress. The Boolean flag determines the animation direction, while the returned floating-point value represents the current animation progress. Developers can then use this value to control rendering parameters, such as opacity, position, or size.&lt;br&gt;
Insight: Although egui's built-in animation functions are convenient, they are not always sufficient for more sophisticated animation requirements. In such cases, developers should manually manage animation progress using &lt;code&gt;ui.time()&lt;/code&gt;. These helper animation functions implicitly maintain internal state, such as a floating-point progress variable, behind the scenes. Understanding this underlying mechanism is essential for designing more advanced animations and for gaining a deeper understanding of egui's immediate-mode paradigm.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>programming</category>
      <category>rust</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The Transition from Code to Standard</title>
      <dc:creator>Lori-Shu</dc:creator>
      <pubDate>Wed, 08 Jul 2026 16:09:37 +0000</pubDate>
      <link>https://dev.to/lorishu/the-transition-from-code-to-standard-2b4f</link>
      <guid>https://dev.to/lorishu/the-transition-from-code-to-standard-2b4f</guid>
      <description>&lt;p&gt;Some software eventually evolves into an official standard. The word standard itself implies that such software has been recognized as authoritative, reliable, and widely accepted. A good example is the Opus audio codec, which was originally developed by the Xiph.Org Foundation and later standardized as an IETF (Internet Engineering Task Force) RFC. Standardization greatly accelerated the adoption of Opus, allowing it to become one of the most widely used audio codecs on the Internet.&lt;br&gt;
Achieving this transition from code to standard is far from easy. Software intended for standardization must be implemented with exceptional quality, accompanied by clear specifications, and undergo extensive technical review and multiple rounds of discussion and voting before it is accepted by organizations such as the IETF.&lt;br&gt;
Insight. Software that has become part of an official standard provides excellent learning material for developers. It demonstrates not only how to write high-quality code, but also how to design software that is robust, interoperable, and maintainable. As developers, striving to produce work that is eventually worthy of standardization is a meaningful long-term goal.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>opensource</category>
      <category>software</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>The Rotation Logic of an AVL Tree</title>
      <dc:creator>Lori-Shu</dc:creator>
      <pubDate>Sun, 05 Jul 2026 08:35:20 +0000</pubDate>
      <link>https://dev.to/lorishu/the-rotation-logic-of-avl-tree-3e57</link>
      <guid>https://dev.to/lorishu/the-rotation-logic-of-avl-tree-3e57</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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpn5wmv64tw2it4iv8tfn.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpn5wmv64tw2it4iv8tfn.png" alt=" " width="765" height="851"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Oh, my drawing is in a mess but I hope it makes sense.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Breaking： FFmpeg News</title>
      <dc:creator>Lori-Shu</dc:creator>
      <pubDate>Thu, 02 Jul 2026 15:28:49 +0000</pubDate>
      <link>https://dev.to/lorishu/breaking-ffmpeg-news-5edk</link>
      <guid>https://dev.to/lorishu/breaking-ffmpeg-news-5edk</guid>
      <description>&lt;p&gt;&lt;strong&gt;FFmpeg&lt;/strong&gt; announced that their native AAC encoder was rewritten and achieved SOTA with respect to quality. &lt;a href="https://x.com/FFmpeg/status/2072320220509741087?s=20" rel="noopener noreferrer"&gt;https://x.com/FFmpeg/status/2072320220509741087?s=20&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The Direct-Access Array</title>
      <dc:creator>Lori-Shu</dc:creator>
      <pubDate>Wed, 01 Jul 2026 15:56:21 +0000</pubDate>
      <link>https://dev.to/lorishu/the-direct-access-array-l8b</link>
      <guid>https://dev.to/lorishu/the-direct-access-array-l8b</guid>
      <description>&lt;p&gt;The &lt;strong&gt;Direct-Access Array&lt;/strong&gt; is one of the simplest data structures. It stores data at the index corresponding to the value of the data itself. Typically, the stored type is a &lt;strong&gt;boolean flag&lt;/strong&gt; indicating the existence of this value. Utilizing a Direct-Access Array yields optimized constant time complexity when storing and reading data (by incrementing the index and accessing the memory that the index points to). It also can be used to detect duplicates. When we try storing a number and the boolean flag is true, we find a duplicate. This characteristic can be used to replace the &lt;strong&gt;HashSets&lt;/strong&gt; in the cases that the largest number is known to be bounded within a reasonable range. Aside from the replacement optimization, the special array is used in the "buckets" structure in the highly efficient Radix Sort algorithm.&lt;br&gt;
Insight: Simple data structures often deliver high performance but often cannot implement sophisticated operations. We should consider these simple data structures when facing limited computational resources and pursuing highly efficient algorithms.&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>computerscience</category>
      <category>performance</category>
    </item>
    <item>
      <title>The Magic of Radix Sort</title>
      <dc:creator>Lori-Shu</dc:creator>
      <pubDate>Mon, 29 Jun 2026 16:15:24 +0000</pubDate>
      <link>https://dev.to/lorishu/the-magic-of-radix-sort-2ceb</link>
      <guid>https://dev.to/lorishu/the-magic-of-radix-sort-2ceb</guid>
      <description>&lt;p&gt;&lt;strong&gt;Radix Sort&lt;/strong&gt; is a sorting algorithm which does not rely on comparison and achieves highly optimized time complexity of O(n). Although it is not suitable for numbers containing too many digits, we developers can leverage its speed to solve specific problems.&lt;/p&gt;

&lt;p&gt;The genius design of Radix Sort is that it exploits the fact that a single digit has only 10 possible values (zero to nine). First, it initializes ten "buckets." Each one is designed for storing the numbers that have the corresponding digit. Second, Radix Sort uses the buckets to sort the input, which is putting the numbers in the bucket with their digits. This process has to consider the digit from the least significant digit (LSD) to the most significant digit (MSD) in order to guarantee the sorting stability and the complexity. Then the algorithm repeats the process until the sorting of the most significant digit is done. While at every cycle Radix Sort writes back the numbers to the original array, at the next time that it scans the array from the beginning, it preserves the results of the previous cycle. With this operation, the numbers which have the same lower digits won't change order unless some of them have bigger high digits and get placed to larger bucket in the remaining cycles. In addition, if we want the "bucket" to work well, we usually make it a &lt;code&gt;queue&lt;/code&gt; so that we can push and pop elements in a FIFO (First-In, First-Out) order to maintain stability. Otherwise, we could use a standard &lt;code&gt;vector&lt;/code&gt; and perform the write-back in reverse order.&lt;/p&gt;

&lt;p&gt;Insight: I'm impressed by the optimized O(n) complexity of Radix Sort. It turns out that if we abandon the comparison model, the optimization of sorting algorithm can go further. For memorizing, I think it is better to emphasize the concept of &lt;strong&gt;"bucket"&lt;/strong&gt; and &lt;strong&gt;"non-comparison-based sorting."&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>computerscience</category>
      <category>performance</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Complexity of UI Layout</title>
      <dc:creator>Lori-Shu</dc:creator>
      <pubDate>Sat, 27 Jun 2026 15:48:59 +0000</pubDate>
      <link>https://dev.to/lorishu/the-complexity-of-ui-layout-4a59</link>
      <guid>https://dev.to/lorishu/the-complexity-of-ui-layout-4a59</guid>
      <description>&lt;p&gt;For backend developers like me, handling the widget layout of UI is a burden. In general, there are two mainstream layout strategies: absolute positioning and relative positioning. Frontend engineers leverage these strategies to create magic. In order to simplify and visualize the layout, developers came up with some great tools like the "DOM Tree" in &lt;strong&gt;HTML&lt;/strong&gt; and &lt;strong&gt;anchoring and docking mechanisms&lt;/strong&gt; in UI libraries. These tools and designs make the code logically look like the output UI, which makes it easier for developers to bridge the gap between programming abstractions and visual implementations.&lt;/p&gt;

&lt;p&gt;Insight: In my experience, we can also leverage the &lt;strong&gt;decoupling&lt;/strong&gt; idea in UI sector—treating components as independently as possible. This structural arrangement improves maintainability and accelerates the product development in the long term.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>html</category>
      <category>softwaredevelopment</category>
      <category>ui</category>
    </item>
    <item>
      <title>The Characteristics of Existing Graphics APIs</title>
      <dc:creator>Lori-Shu</dc:creator>
      <pubDate>Fri, 26 Jun 2026 15:51:36 +0000</pubDate>
      <link>https://dev.to/lorishu/the-characteristics-of-existing-graphics-apis-10aa</link>
      <guid>https://dev.to/lorishu/the-characteristics-of-existing-graphics-apis-10aa</guid>
      <description>&lt;p&gt;The &lt;strong&gt;Graphics APIs&lt;/strong&gt; are responsible for connecting high-level code to drivers (one kind of low-level software which controls the external hardware). The quality and efficiency of Graphics APIs are vital to building advanced graphic environments and applications. We could classify these APIs into two kinds: platform-specific APIs and cross-platform APIs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Platform-specific APIs&lt;/strong&gt; are usually the most efficient APIs on the platform. They conventionally are developed along with the system development process so that they can interact with the operating system seamlessly. In addition, hardware manufacturers are willing to support them with the highest priority. Nowadays, &lt;strong&gt;DirectX&lt;/strong&gt; series are the first-class APIs on Windows, which power most existing games. &lt;strong&gt;Metal&lt;/strong&gt; is the current official API on macOS; however, things become far more interesting on Linux.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cross-platform APIs&lt;/strong&gt; are those which are capable of running on multiple platforms. A fact is that the cross-platform APIs are almost all designed for Linux at first and they are in fact the first-class APIs on Linux. However, because of the "open source" root of Linux, the APIs are able to run on other platforms, requiring minimal effort from system developers. &lt;strong&gt;OpenGL&lt;/strong&gt; and &lt;strong&gt;Vulkan&lt;/strong&gt; are the prominent implementations built by the &lt;strong&gt;Khronos Group&lt;/strong&gt;. OpenGL is older, less efficient on large applications while the abstraction is higher and easier to use. Vulkan is more advanced with modern graphic features while the abstraction is more sophisticated and takes a lot of work to integrate in high-level applications.&lt;/p&gt;

&lt;p&gt;Insight: Currently, the axiom is that a Graphics API cannot be both the most efficient and cross-platform. We may expect Vulkan to be the game- changer.&lt;/p&gt;

</description>
      <category>api</category>
      <category>architecture</category>
      <category>computerscience</category>
      <category>performance</category>
    </item>
    <item>
      <title>How Does the Backpressure Mechanism Work in mpsc::channel?</title>
      <dc:creator>Lori-Shu</dc:creator>
      <pubDate>Wed, 24 Jun 2026 16:02:51 +0000</pubDate>
      <link>https://dev.to/lorishu/how-does-the-backpressure-mechanism-work-in-mpscchannel-1cpm</link>
      <guid>https://dev.to/lorishu/how-does-the-backpressure-mechanism-work-in-mpscchannel-1cpm</guid>
      <description>&lt;p&gt;There is a powerful mechanism called "backpressure" derived from &lt;code&gt;mpsc::channel&lt;/code&gt;. Alongside the function of data transfer, we could also utilize the channel with this mechanism to achieve a specific effect.&lt;/p&gt;

&lt;p&gt;"Backpressure" relies on the &lt;code&gt;async runtime&lt;/code&gt;. When a bounded channel is full, the sender will suspend the current task and yield control back to the async executor until it becomes ready again. This only works in an async context. Otherwise, the sender will just block. How can we use the phenomenon? In my experience, this can be used to automatically suspend background tasks. In most cases, the data flows in one direction. Once we control the consumer at the endpoint, the tasks along the entire pipeline are gracefully suspended. This can save a lot of work if we want to temporarily stop the consuming process and the upstream tasks. Symmetrically, it works in the scenario that we make the producer side stop sending.&lt;/p&gt;

&lt;p&gt;Insight: There are many elegant optimizations leveraging the side effects from the original action. In addition to "backpressure", I have encountered mechanisms like storing information in the unused bits of a chunk of memory, storing static assets in the static space of an &lt;code&gt;executable file&lt;/code&gt; etc.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>programming</category>
      <category>rust</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What Do I Know about Gradle?</title>
      <dc:creator>Lori-Shu</dc:creator>
      <pubDate>Tue, 23 Jun 2026 16:28:37 +0000</pubDate>
      <link>https://dev.to/lorishu/what-do-i-know-about-gradle-2mkn</link>
      <guid>https://dev.to/lorishu/what-do-i-know-about-gradle-2mkn</guid>
      <description>&lt;p&gt;Developers starting their careers with Java must have encountered the package manager—Maven. The software has become the standard for developing Java projects. However, have you ever heard of another build tool for Java? Gradle is capable of managing Java projects as well.&lt;/p&gt;

&lt;p&gt;Gradle maintainers describe it as "a highly scalable build automation tool designed to handle everything from large, multi-project enterprise builds to quick development tasks across various languages." I am going to talk about how it interacts with Java.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build Acceleration&lt;/strong&gt;&lt;br&gt;
The architecture of Gradle enables it to build with cache. If some parts of the code didn't change since the last build, Gradle will reuse the build files that correspond to the unchanged code. This significantly reduces the build time compared to building from scratch. The design is similar to another build tool "cargo" which is contained in the Rust toolchain.&lt;br&gt;
&lt;strong&gt;Dependencies Management&lt;/strong&gt;&lt;br&gt;
Gradle supports downloading dependencies from a central repository just like Maven. Although it is convenient, it takes a lot of work for Maven to make it great. The burden of handling dependency conflicts is a nightmare for developers. Gradle tried to absorb the experience of Maven. It employs DSL (Domain-Specific Language) script to declare project metadata, dependencies etc. Originally, it corresponded to Groovy DSL (&lt;code&gt;build.gradle&lt;/code&gt;). Iterating to modern version, it is taking a transition to Kotlin DSL (&lt;code&gt;build.gradle.kts&lt;/code&gt;). Compared with powerful but old XML solution of Maven, Gradle achieves more clear declaration and less boilerplate code.&lt;br&gt;
&lt;strong&gt;Remaining Limitations&lt;/strong&gt;&lt;br&gt;
Despite the fact that Gradle gained so many optimizations, there are remaining defects. First of all, the core of Gradle is written in Java so that it needs a JVM to run. Java developers all know that not only is JVM one of the most powerful features of Java but also a drawback when it comes to distribution. The user side often doesn't have a JRE or JDK installed and the JVM can make a distribution pack huge. Another problem I have encountered is the default wrapper configuration. In order to unify the Gradle version especially for Android projects, Gradle makes the wrapper configuration default but it is a pain in the cases that I just don't want to automatically download another version of Gradle.&lt;/p&gt;

&lt;p&gt;Insight: Gradle currently supports many languages including some outside the JVM ecosystem. I recommend Java developers to try switching the long term supported projects from Maven to Gradle.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>beginners</category>
      <category>java</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Design Patterns of Software Architecture</title>
      <dc:creator>Lori-Shu</dc:creator>
      <pubDate>Mon, 22 Jun 2026 15:23:29 +0000</pubDate>
      <link>https://dev.to/lorishu/design-patterns-of-software-architecture-4bhi</link>
      <guid>https://dev.to/lorishu/design-patterns-of-software-architecture-4bhi</guid>
      <description>&lt;p&gt;Let's talk about Design Patterns. Design Patterns are special structures applied to code base. These unique structures are efficient and elegant as long as developers use them in the fields that they are good at. Common Design Patterns and their use cases are arranged as follows:&lt;br&gt;
&lt;strong&gt;Observer Pattern&lt;/strong&gt;: The Observer Pattern allows objects (observers) to subscribe to a subject, so they are automatically notified of any state changes. Observer Pattern is used in products like message queues which has to broadcast messages to all the message subscribers.&lt;br&gt;
&lt;strong&gt;Strategy Pattern&lt;/strong&gt;: Strategy Pattern separates strategy code from certain client code, leading to convenient switch of strategy. Strategy Pattern makes strategy code run outside client (e.g., compiling to different executable files), which achieves low coupling. Programs like browsers which support plugin systems are using this model.&lt;br&gt;
&lt;strong&gt;Template Pattern&lt;/strong&gt;: This model encourages developers to extract abstract classes or interfaces so that we improve the reusability of code (often written in child classes or interface implementations). Java programmers are familiar with this model because Java uses abstract classes and interfaces everywhere.&lt;br&gt;
&lt;strong&gt;Adapter Pattern&lt;/strong&gt;: Sometimes we want classes with different interfaces to work together. Adapter Pattern defines adapter interface extracting the common "traits" of these classes. The abstraction is capable of calling methods of different classes by identical interface. The famous JDBC (Java Database Connectivity) is a demonstration of Adapter Pattern. Adapter Pattern is good at maintaining compatibility. No matter whether the implementation is new or old, as long as it implements the interface, the code will always work.&lt;br&gt;
&lt;strong&gt;Decoration Pattern&lt;/strong&gt;: This pattern prefers composition rather than inheritance. Each time the type needs a new function, we add new member fields rather than create child class to extend its responsibility. Rust enforces composition over inheritance at the language level, which significantly reduces the dependence complexity and is proved to be ideal for writing clear-minded code in practice.&lt;/p&gt;

&lt;p&gt;Insight: Even though the benefits of these Design Patterns are tempting, experienced developers only apply them in suitable cases. The trade-off mindset must always be kept in mind.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>computerscience</category>
      <category>programming</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Position Calculations in Two-Dimensional Arrays</title>
      <dc:creator>Lori-Shu</dc:creator>
      <pubDate>Sat, 20 Jun 2026 15:56:11 +0000</pubDate>
      <link>https://dev.to/lorishu/position-calculations-in-two-dimensional-arrays-jp3</link>
      <guid>https://dev.to/lorishu/position-calculations-in-two-dimensional-arrays-jp3</guid>
      <description>&lt;p&gt;I keep falling into the same trap: coordinate calculations. I'm here to record some of the lessons with possible solutions which could solve or relieve some of the traps.&lt;/p&gt;

&lt;p&gt;Firstly, how do we choose the coordinate axes? When we take math classes, professors often draw the x- and y-axes with the origin located at the bottom-left corner; x goes right and y goes up. This is intuitive but we need to switch our mindset when we are in programming. We still consider a two-dimensional array in such axes only if we can fit the dimensions. For example, an array a[3][4] has three elements in the first dimension and four elements in the second dimension. If we view it as a 3×4 array, the first dimension is mapped to x while the second dimension is mapped to y. If we view it as a 4×3 array, the first dimension is mapped to y while the second dimension is mapped to x. Either layout is valid only if it remains consistent with that mapping. After fixing the axes, we should consistently follow the same mapping whenever we access the array. In order to make the variables more readable, sometimes we use names like "row" or "col". Never mix "x/y" and "row/column" terminology. Just pick one. The code tends to become a disaster when I mix them together.&lt;/p&gt;

&lt;p&gt;Secondly, how do we calculate a point from other points? In many cases, we determine the position of a point through linear combination of other points. For example, the midpoint between two points is given by 〖(pos〗_2+〖pos〗_1)/2. However, when pos1 is the origin, I often neglect it in subsequent calculations, leading to incorrect results. To avoid that, we should understand the position formula and the idea of relative position. Every coordinate is ultimately defined relative to the chosen origin. However, when we calculate the middle point between two points, the midpoint is defined relative to the two endpoints rather than the origin.&lt;/p&gt;

&lt;p&gt;Insight: Handling dimension mappings and relative positions is a common source of bugs in programming. I hope that "Be consistent with the coordinate system you have chosen." and "Understand what a formula actually represents geometrically." will not bother me again in the future.&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>beginners</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
