<?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: Lex Nwimue P.</title>
    <description>The latest articles on DEV Community by Lex Nwimue P. (@lexnwimue).</description>
    <link>https://dev.to/lexnwimue</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%2F1075397%2F5bc2c061-5d24-4fdb-9840-8cafed4b0e1f.jpeg</url>
      <title>DEV Community: Lex Nwimue P.</title>
      <link>https://dev.to/lexnwimue</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lexnwimue"/>
    <language>en</language>
    <item>
      <title>Happy Monoversary!</title>
      <dc:creator>Lex Nwimue P.</dc:creator>
      <pubDate>Wed, 29 Jul 2026 00:35:20 +0000</pubDate>
      <link>https://dev.to/lexnwimue/happy-monoversary-4ij</link>
      <guid>https://dev.to/lexnwimue/happy-monoversary-4ij</guid>
      <description>&lt;p&gt;Dang! Its been a whole year. Doesn't even feel like it. About a year ago I was employed at Techinnover Analytics Ltd, where I had several firsts - but I refuse to mention them here. I was managing software that issued tickets for Filmhouse Cinemas in millions of Naira, and an audio mgt. software that managed music, announcements, and jingles used in 90+ shopping malls and superstores around the country. It felt complex at the onset, but a few months into the 2+ years I spent there, it became routine. I wanted something else, something more. So, I spent a few nights sending out cold emails, hoping to hear back. On a particular night in June, after sending out about 50+ cold emails manually, I remembered something a friend and former coursemate had told me about using Twitter (now X) for job hunting, so to round off the night, I decided to search for a few backend roles there. After scrolling down a couple times, I saw it. Mono. Hmm. I didn't know too much about them at the time becasue of unfamiliarity with the Fintech space, but I loved their website. It felt modern and foreign. That was my last application for the night. &lt;/p&gt;

&lt;p&gt;I sent out an email (could have been two to two different mails). I think a day or two later, I would hear back from the head of engineering, Ahmed Alfawwaz, who, despite being younger, would turn out to be my manager, and a great one at that. He was impressed by my resume and by something I had done a few months prior - I was featured on the &lt;em&gt;Microsoft On .NET Live&lt;/em&gt; show where I talked about the challenges of managing data in distributed systems. &lt;a href="https://youtu.be/dMsM0mN0hb8" rel="noopener noreferrer"&gt;https://youtu.be/dMsM0mN0hb8&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;So, he scheduled for us to have a call. I was thrilled. Booked a session on his calendar and joined the call on the said date. Oops. He didn't join. I didn't know what to do. Should I send an email and look desperate or should I compose and maintain steeze. I sent an email jare, and he apologized for missing the call, saying he didn't see the booking. I booked another slot, and we had a meeting. &lt;/p&gt;

&lt;p&gt;You know the drill: starting off with some light conversation and getting familiar with ourselves, before the real business of the day. He said usually they give a take-home assessment but since he was already impressed, we can just talk about the assessment right there on the call. I eat system design weekly so I was full and ready to rumble. Scratch that. I was readily humbled :D :D. &lt;/p&gt;

&lt;p&gt;To cut the story short, he wanted me talk about tracking success rate (confidence score) for a list of institutions based on the success rate of the transactions they process. The system had to be flexible such that the tracking window can always be altered without distorting the result, and the system also had to maintain records to allow it track the confidence score across longer duration e.g. past month, quarter, year etc. Yeah, its sliding window problem and my thought process seemed to be sliding away. &lt;/p&gt;

&lt;p&gt;Long story short, I started off well, started blanking out eventually, and then I was done - off! It was terrible. I knew it was offer. Omo. We had such a great start and now we're here. My beloved system design, something I thought I was great at. &lt;/p&gt;

&lt;p&gt;I could feel the disappointment in his voice. He sounded like someone that was really hoping I would be the candidate to finally end his search. I wasn't. Omo, na so interview end o.&lt;/p&gt;

&lt;p&gt;I only felt slightly terrible, surprisingly, but I shrugged it off and continued with my daily routine, but the experience never truly left me. So, about a week later, on the next weekend, I decided to pay a second attention to that problem when I got home from an evening walk I had where I couldn't stop thinking about it. So, I pulled up my laptop, scribbled down some thoughts on a piece of paper, and typed out the algorithm I had in mind for the problem. It missed a few edge cases but it did the job. I fed that to ChatGPT to enhance and identify more edge cases (it was still a crude solution at this point though). You can see it here: &lt;a href="https://github.com/lexNwimue/mono-assessment" rel="noopener noreferrer"&gt;https://github.com/lexNwimue/mono-assessment&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;I sent it over, mentioning clearly how I got the solution, and how I enhanced it with ChatGPT. Also told him I just needed closure and this didn't have anything to do with the interview. Can't deny it though, a small part of me was hoping the solution would help my case. I didn't hear back that day. I kept polling. Incoming webhook - email! He was impressed yet again. We scheduled another call, talked about my solution, then talked about a possible offer. &lt;/p&gt;

&lt;p&gt;I didn't want to get too excited yet. I waited a few days, hoping they hadn't changed their mind. Then I got an email from the people (HR) team, and in a few weeks, after my notice period, I was officially in. &lt;/p&gt;

&lt;p&gt;That was exactly 365+1 days ago. &lt;/p&gt;

&lt;p&gt;My first task? Investigate and fix an issue on the settlement report service. It was always OOM-ing, so my solution was to switch from a memory-hogging approach to a stream-based solution. After my solution went live, I would occasionally look at the Grafana chart, impressed with how flat the lines have gotten over the past few days due to my solution. &lt;/p&gt;

&lt;p&gt;Today, I still lead the payments team, and I do some of the things Alfawwaz used to do when he was still working with us, until he left a few months ago to join Apron, a company in the UK. I'm still grateful to him for wanting this role for me. &lt;/p&gt;

&lt;p&gt;I did get what I want - something to keep me on my toes and not feel routine. Its been a year and sometimes I know less than 0.2% of what I'm doing - sometimes I know too much of it. Its never the same because Mono is not your regular company. &lt;/p&gt;

&lt;p&gt;Later today, I'd be testing some fixes we made to our disbursement service as well as fix other issues on the dispute manager service, write a script for some fee-related stuff I'm not too sure about yet, then possibly making some updates following feedback from the TPS team on our partial sweep product. &lt;/p&gt;

&lt;p&gt;That's it. Later. &lt;/p&gt;

</description>
      <category>career</category>
      <category>software</category>
    </item>
    <item>
      <title>Cron Expressions, LLMs, and Investigating Crimes You Committed</title>
      <dc:creator>Lex Nwimue P.</dc:creator>
      <pubDate>Sun, 07 Jun 2026 15:48:00 +0000</pubDate>
      <link>https://dev.to/lexnwimue/cron-expressions-llms-and-investigating-crimes-you-committed-2aaf</link>
      <guid>https://dev.to/lexnwimue/cron-expressions-llms-and-investigating-crimes-you-committed-2aaf</guid>
      <description>&lt;p&gt;One of the very few things most developers lazily evaluate is Regex (regular expressions). There are several memes about it, but they're undeniably useful when pattern matching is important. The second, in my opinion, is the cron expression. Less scary than regex, a bit more predictable, but still lazily evaluated.&lt;/p&gt;

&lt;p&gt;Coincidentally, they're also useful for pattern matching—just in the context of time. Recurring times, if I might.&lt;/p&gt;

&lt;p&gt;A project I've worked on for a while now relies heavily on background workers/jobs to execute several flows that contribute crucially to the overall system. In fact, there are probably five times as many jobs as there are route groupings (user routes, debit routes, etc.) in the codebase. You can already tell where this is going, because background jobs need cron expressions to work. They need to know &lt;em&gt;when&lt;/em&gt; to run and &lt;em&gt;how often&lt;/em&gt; to run. In other words, they need a pattern.&lt;/p&gt;

&lt;p&gt;One such job is what we loosely call the &lt;em&gt;mandate-debit-readiness&lt;/em&gt; job. Its responsibility is to identify mandates that are ready for debit and update their state accordingly. It was supposed to run every five minutes and had been doing so for almost three months.&lt;/p&gt;

&lt;p&gt;Or so we thought.&lt;/p&gt;

&lt;p&gt;Last week, we noticed that the job didn't seem to run on weekends. Mandates that should have been marked as ready weren't updated until the very first minute of Monday morning. Naturally, we started investigating.&lt;/p&gt;

&lt;p&gt;The first thing we checked was the worker logic itself. Maybe there was some condition buried somewhere that skipped weekends. There wasn't. Nobody thought to check the cron expression initially; it took a few minutes before someone finally did.&lt;/p&gt;

&lt;p&gt;Then we found this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 * * * * 1-5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even as someone who lazily evaluates cron expressions, one thing immediately stood out: the &lt;code&gt;1-5&lt;/code&gt; at the end. It didn't feel like it should be there, and my brain instantly translated it to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Monday through Friday.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There was even a comment beside it — something along the lines of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;every hour on weekdays
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first glance, it looked like we'd found the culprit. The job wasn't running on weekends because we'd explicitly told it not to. We didn't notice there was nothing indicating "every 5 minutes" about this expression, so case closed.&lt;/p&gt;

&lt;p&gt;Or so we thought.&lt;/p&gt;

&lt;p&gt;After a quick sanity check with Gemini, we removed the &lt;code&gt;1-5&lt;/code&gt; restriction, updated the comment, deployed the change.&lt;/p&gt;

&lt;p&gt;Problem solved.&lt;/p&gt;

&lt;p&gt;Except it wasn't.&lt;/p&gt;

&lt;p&gt;A day or two later, it was reported that ready mandates were taking far too long to get updated. Excuse me? We literally just fixed this. The weekend issue was gone. Weekdays were never supposed to have been a problem.&lt;/p&gt;

&lt;p&gt;Naturally, the PM started a Slack huddle, and we found ourselves knee-deep in logs again.&lt;/p&gt;

&lt;p&gt;Debugging jobs is a fascinating experience. It's like being the detective assigned to investigate a crime that you committed.&lt;/p&gt;

&lt;p&gt;Eventually, a pattern emerged from the logs. The job wasn't running every few minutes as expected — it was running every hour. Wonderful.&lt;/p&gt;

&lt;p&gt;Back to the code.&lt;/p&gt;

&lt;p&gt;And there it was. That same comment we'd previously ignored because we were too busy celebrating our fix.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;every hour...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Interesting.&lt;/p&gt;

&lt;p&gt;I pasted the updated cron expression into Gemini again, and Gemini insisted it meant every hour. Weird. I pasted the exact same expression into ChatGPT, and ChatGPT told me it ran every minute. Now things were getting interesting.&lt;/p&gt;

&lt;p&gt;Same expression.&lt;/p&gt;

&lt;p&gt;Different interpretations.&lt;/p&gt;

&lt;p&gt;I tried Claude. Claude sided with Gemini. I tried Crontab Guru. Crontab Guru also sided with Gemini.&lt;/p&gt;

&lt;p&gt;At this point, I was less concerned about the bug and more fascinated by the fact that several systems appeared to disagree on something that felt as standardised as a cron expression. And if the expression really meant "every hour", another question remained:&lt;/p&gt;

&lt;p&gt;How had this job been behaving correctly for months?&lt;/p&gt;

&lt;p&gt;That mystery was becoming more interesting than the actual bug.&lt;/p&gt;

&lt;p&gt;Then it clicked.&lt;/p&gt;

&lt;p&gt;The issue wasn't necessarily the LLMs. It was my assumption that cron expressions are universally interpreted the same way.&lt;/p&gt;

&lt;p&gt;Our codebase contains a mix of cron formats. Some jobs use five fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*/5 * * * *
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Others use six:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 0 2 * * *
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 0 3,22 * * *
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And once you introduce multiple cron formats into the conversation, things get surprisingly messy.&lt;/p&gt;

&lt;p&gt;Some cron implementations use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minute hour day-of-month month day-of-week
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Others include seconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;second minute hour day-of-month month day-of-week
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suddenly, an expression that looks obvious isn't quite so obvious anymore. The real source of truth isn't Gemini. It isn't ChatGPT. It isn't Claude. And it isn't Crontab Guru.&lt;/p&gt;

&lt;p&gt;It's the actual scheduler that's parsing and executing the expression in production.&lt;/p&gt;

&lt;p&gt;Eventually, we updated the expression to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*/5 * * * *
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which explicitly means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Run every five minutes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The behaviour aligned with our expectations, and that was the end of the incident.&lt;/p&gt;

&lt;p&gt;Mostly.&lt;/p&gt;

&lt;p&gt;What stuck with me wasn't the cron bug itself. It was how quickly we became confident in a theory that happened to fit the evidence we had at the time. The expression looked suspicious. The comment appeared to confirm our suspicion. Gemini agreed with us. We deployed the change and moved on, only to discover that we'd introduced a completely different problem.&lt;/p&gt;

&lt;p&gt;In hindsight, the most interesting part of the story isn't that different LLMs produced different interpretations. It's that they had valid reasons to. Once I realised our ecosystem contained a mix of five-field and six-field cron formats, the disagreement became a lot less mysterious.&lt;/p&gt;

&lt;p&gt;The real lesson wasn't about cron expressions at all. It was about assumptions.&lt;/p&gt;

&lt;p&gt;Regex and cron expressions occupy a similar place in many developers' minds. We don't use them often enough to remember all the details, but we use them just often enough to feel confident that we do. Most of the time that's fine. Then one day, they become the problem.&lt;/p&gt;

&lt;p&gt;And when they do, you find yourself investigating a crime that, more often than not, you committed yourself.&lt;/p&gt;

</description>
      <category>cron</category>
      <category>timers</category>
      <category>discrepancy</category>
    </item>
    <item>
      <title>Leetcode 2</title>
      <dc:creator>Lex Nwimue P.</dc:creator>
      <pubDate>Fri, 15 May 2026 01:38:56 +0000</pubDate>
      <link>https://dev.to/lexnwimue/leetcode-2-2f0h</link>
      <guid>https://dev.to/lexnwimue/leetcode-2-2f0h</guid>
      <description>&lt;p&gt;I did LeetCode 2. Yup. That’s the headline. The classic &lt;em&gt;Add Two Numbers.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Submitted my solution thanks to the tremendous help of ChatGPT, but I still feel a bit guilty about it. Afterward, I went down a rabbit hole of trying to convince myself it’s fine not to understand every single detail of every problem on the first pass. Some Reddit comments helped reinforce that idea — learn patterns, don’t memorize solutions.&lt;/p&gt;

&lt;p&gt;I agree with that in theory. Which is why I immediately went to watch the NeetCode breakdown on YouTube to actually understand what was going on. I stopped just as the video started playing to write this blabbering. My solution was in Rust, of course, which probably made the whole thing feel more intimidating than it needed to be. But honestly, I don’t think I would’ve fared much better in TypeScript either, so I’m not blaming Rust for this one.&lt;/p&gt;

&lt;p&gt;All of this happened in the last two hours.&lt;/p&gt;

&lt;p&gt;Earlier in the day, I had been working on something completely different: integrating the HashiCorp Vault Transit Engine for encryption and decryption in an MFA feature I was shipping. The feature was actually complete locally, but we ran into policy configuration issues in dev. That got resolved today, and the frontend team was finally able to integrate it successfully.&lt;/p&gt;

&lt;p&gt;Before this, our 2FA system was...let’s just call it creative, in a bad way.&lt;/p&gt;

&lt;p&gt;We had two endpoints: &lt;code&gt;/initiate&lt;/code&gt; and &lt;code&gt;/validate&lt;/code&gt; (Ehn..., tell me about naming conventions 😂☺️). The frontend would call them before allowing users to perform critical actions like withdrawals, transfers etc.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/initiate&lt;/code&gt; simply generated a random 6-digit code and stored it in Redis as plain text, keyed by the user’s email. That OTP was then emailed to the user. &lt;code&gt;/validate&lt;/code&gt; just compared the input against whatever was in Redis.&lt;/p&gt;

&lt;p&gt;If you already think that sounds like an insecure API design, it gets better.&lt;/p&gt;

&lt;p&gt;Nothing stopped a malicious user from completely bypassing the whole “2FA flow” and calling the withdrawal endpoint directly. There was no server-side enforcement tying the withdrawal action to a completed 2FA challenge. So effectively, the “2FA” was just client-side theatre. You still needed your PIN and login session, sure — but as far as security layers go, this one was more decorative than functional.&lt;/p&gt;

&lt;p&gt;Two years ago, I would’ve been livid that anyone would design it this way. These days, I understand how fast-paced systems can lead to oversights like this. I still don’t see myself making this exact mistake, even when I was a junior, but reality is messy and things slip through.&lt;/p&gt;

&lt;p&gt;Since my MFA implementation and some intentional security hardening work across the company, we’ve been closing gaps like this. This particular one is now fixed: every critical action (withdrawals, transfers, etc.) is tied to a scoped MFA session. Meaning an MFA challenge is bound to a specific action and cannot be reused or replayed across different flows.&lt;/p&gt;

&lt;p&gt;The frontend and PMs may see it as a “small update,” but any security-conscious backend engineer knows that this is actually a meaningful shift in how trust boundaries are enforced.&lt;/p&gt;

&lt;p&gt;On another note, I also had to debug a bug caused by a slightly incorrect use of the dayjs library in a different project.&lt;/p&gt;

&lt;p&gt;We had a job that ran roughly like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasExceededDefaultWindow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dayjs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isBefore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;dayjs&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;subtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;day&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hasExceededDefaultWindow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// do something1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;IS_CHECK_FEATURE_ENABLED&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// carry out check&lt;/span&gt;
  &lt;span class="c1"&gt;// if check is true, do something1 else do nothing&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The intention was simple:&lt;br&gt;
If &lt;code&gt;item.createdAt&lt;/code&gt; is more than 24 hours old, process it immediately. Otherwise, if the feature flag is enabled, run an extra check before deciding what to do.&lt;/p&gt;

&lt;p&gt;We had feature-flagged this because even though it had been tested in staging and already deployed, there were still internal reasons to keep the behavior partially disabled in production.&lt;/p&gt;

&lt;p&gt;Later, we noticed inconsistent behavior. Some items that were clearly older than 24 hours weren’t being processed. &lt;code&gt;hasExceededDefaultWindow&lt;/code&gt; was still evaluating to false, and because the feature flag was also disabled, the fallback logic never ran either. So the job effectively did... nothing.&lt;/p&gt;

&lt;p&gt;I’m skipping some surrounding context, but the root cause ended up being subtle behavior around date difference calculations in dayjs.&lt;/p&gt;

&lt;p&gt;At one point, the logic was effectively relying on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;dayjs&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;dayjs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;day&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which actually means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Only true after more than 1 full day boundary has passed&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So in practice:&lt;/p&gt;

&lt;p&gt;23 hours → 0&lt;br&gt;
25 hours → 1&lt;br&gt;
48+ hours → 2&lt;/p&gt;

&lt;p&gt;Meaning it only becomes true after roughly 48 hours, not 24.&lt;/p&gt;

&lt;p&gt;The corrected version is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasExceededDefaultWindow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nf"&gt;dayjs&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;dayjs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hour&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or more readable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasExceededDefaultWindow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nf"&gt;dayjs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;isBefore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;dayjs&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;subtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;day&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This didn’t take long to trace — we had Grafana logs showing job execution patterns, so it was fairly quick to isolate. Still, it was one of those “small but annoying” parts of the day.&lt;/p&gt;

&lt;p&gt;Now I’ll probably format this properly with ChatGPT, then sleep off while watching NeetCode explain LeetCode 2 again — this time with a little less guilt attached.&lt;/p&gt;

</description>
      <category>leetcode</category>
      <category>rust</category>
      <category>dsa</category>
      <category>bug</category>
    </item>
    <item>
      <title>Rust got 'pub' wrong</title>
      <dc:creator>Lex Nwimue P.</dc:creator>
      <pubDate>Wed, 24 Dec 2025 17:44:09 +0000</pubDate>
      <link>https://dev.to/lexnwimue/rust-got-pub-wrong-7jf</link>
      <guid>https://dev.to/lexnwimue/rust-got-pub-wrong-7jf</guid>
      <description>&lt;p&gt;The &lt;code&gt;pub&lt;/code&gt; keyword in Rust is used as an access modifier to make items—such as functions, structs, enums, traits, and modules—accessible outside of their defining module. In that sense, it behaves similarly to &lt;code&gt;public&lt;/code&gt; in many other languages.&lt;/p&gt;

&lt;p&gt;However, one major difference—especially noticeable if you’re coming from JavaScript—is the default behaviour.&lt;/p&gt;

&lt;p&gt;In JS/TS, methods on a class are public by default (assuming you don’t explicitly mark them otherwise using # or the &lt;code&gt;private&lt;/code&gt; keyword). The underlying assumption is that most class methods should be accessible, so there’s no need to constantly annotate method signatures with a visibility keyword. You could call this &lt;em&gt;convention over configuration.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Rust could have borrowed this idea and arguably become even closer to perfection than it already is. But it didn’t. Instead, Rust went in the opposite direction: private by default, public by explicit declaration.&lt;/p&gt;

&lt;p&gt;The result is that you often end up with code that looks like this:&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%2Fmhm5jv2elrrhh65byp8s.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%2Fmhm5jv2elrrhh65byp8s.png" alt="Rust pub keyword litter" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See it? A literal littering of &lt;code&gt;pub&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;If the default behaviour were reversed, we might end up with cleaner-looking code—similar to how Rust handles the &lt;code&gt;mut&lt;/code&gt; keyword. Variables are immutable by default, and when you explicitly add mut, it immediately signals to the reader that this value is going to change somewhere later. That signal is psychological as much as it is technical.&lt;/p&gt;

&lt;p&gt;Right now, &lt;code&gt;pub&lt;/code&gt; doesn’t quite have that same signalling power because it appears everywhere. It becomes visual noise. If, instead, Rust had opted for public-by-default, then explicitly marking things as private could have had the same effect that mut has today. Seeing a private keyword would immediately tell the reader: “This is intentionally hidden; don’t depend on it.”&lt;/p&gt;

&lt;p&gt;In other words, the code would read more like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Everything here is meant to be accessible—except these specific things.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Rather than:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“We want this, and this, and this, and this… to be public.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Important Clarification (Where Rust Actually Differs from JS)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One thing worth correcting is why this comparison feels slightly off. Rust’s visibility is module-based, not class-based. In JavaScript (and many OOP languages), visibility is scoped primarily to classes. In Rust, visibility is scoped to modules, which act as explicit API boundaries. This means Rust isn’t just protecting fields and methods—it’s protecting entire namespaces and architectural layers.&lt;/p&gt;

&lt;p&gt;So the choice of “private by default” isn’t just stylistic. It strongly encourages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;deliberate API design&lt;/li&gt;
&lt;li&gt;minimal public surface area&lt;/li&gt;
&lt;li&gt;fewer accidental breaking changes&lt;/li&gt;
&lt;li&gt;clearer ownership of invariants&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is especially important in a language designed for large, long-lived systems and libraries.&lt;/p&gt;

&lt;p&gt;So… is Rust wrong here?&lt;/p&gt;

&lt;p&gt;Probably not.&lt;/p&gt;

&lt;p&gt;But is the ergonomics debate valid?&lt;/p&gt;

&lt;p&gt;Absolutely.&lt;/p&gt;

&lt;p&gt;Rust trades verbosity for correctness and stability, and while that choice makes sense from a language-design perspective, it does come at a readability cost—especially for people coming from JS/TS, where public APIs are often implied rather than declared.&lt;/p&gt;

&lt;p&gt;Whether that trade-off is worth it depends on what you value more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;visual cleanliness&lt;/li&gt;
&lt;li&gt;or uncompromising explicitness&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rust very clearly chose the latter.&lt;/p&gt;

&lt;p&gt;What do you think?&lt;/p&gt;

</description>
      <category>keyword</category>
      <category>rust</category>
      <category>programming</category>
    </item>
    <item>
      <title>Rust Slices</title>
      <dc:creator>Lex Nwimue P.</dc:creator>
      <pubDate>Tue, 23 Dec 2025 02:25:08 +0000</pubDate>
      <link>https://dev.to/lexnwimue/rust-slices-1p7f</link>
      <guid>https://dev.to/lexnwimue/rust-slices-1p7f</guid>
      <description>&lt;p&gt;Most of my writings about Rust come from a JS/TS developer’s point of view. Intuitively, when you learn a new language through another, you tend to map concepts between the two. For example, a struct in Rust might map to an interface or type in TypeScript. Doing this makes it easier to consume knowledge in the new language because the concept suddenly feels familiar. But this pattern of learning introduces a subtle problem.&lt;/p&gt;

&lt;p&gt;Once you get used to constantly mapping ideas, it becomes harder to truly grasp concepts in the new language that don’t have a direct equivalent in the one you already know. This was the hurdle I ran into with slices in Rust.&lt;/p&gt;

&lt;p&gt;This short article assumes a basic understanding of Rust concepts such as references, borrowing, and ownership.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A common Rust pattern&lt;/strong&gt;&lt;br&gt;
In Rust, it is generally best practice to use an immutable (read-only) reference when writing a function that does not need to mutate its argument. To illustrate this, let’s write a function that accepts a full name and returns just the first name.&lt;/p&gt;

&lt;p&gt;We might end up with something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fn get_first_name(full_name: &amp;amp;str) -&amp;gt; &amp;amp;str {
    full_name
        .split_whitespace()
        .next()
        .unwrap_or("")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;What’s going on here?&lt;/em&gt;&lt;br&gt;
The &lt;code&gt;get_first_name&lt;/code&gt; function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Borrows a string slice (&amp;amp;str); it does not take ownership.&lt;/li&gt;
&lt;li&gt;Splits the string by whitespace into words.&lt;/li&gt;
&lt;li&gt;Takes the first word (if any).&lt;/li&gt;
&lt;li&gt;If there are no words (i.e. the string is empty or contains only spaces), it returns "".&lt;/li&gt;
&lt;li&gt;It returns a slice of the original string, not a new String.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything makes sense… except that last bullet point. What do you mean &lt;em&gt;“it returns a slice of the original string, not a new string”&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let’s &lt;del&gt;unwrap&lt;/del&gt; unpack 😌😉&lt;/strong&gt;&lt;br&gt;
What does “returning a slice” actually mean?&lt;/p&gt;

&lt;p&gt;Let me say the same thing using different words: &lt;em&gt;The function is not creating a new string. Instead, it is simply pointing to a portion of the existing one&lt;/em&gt;. So if our original string is "Lex Luthor", a slice could refer to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Lex"&lt;/li&gt;
&lt;li&gt;"Luthor"&lt;/li&gt;
&lt;li&gt;"thor"&lt;/li&gt;
&lt;li&gt;"ex Lu"&lt;/li&gt;
&lt;li&gt;or even "Lex Luthor" (the entire string)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these are just views into the same underlying string data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The JavaScript mental model (this helps)&lt;/strong&gt;&lt;br&gt;
If you’re coming from JavaScript, your brain probably jumps straight to substrings. Yep—that’s a very good instinct.&lt;/p&gt;

&lt;p&gt;A substring is a part of another string. Its start and end indices fall within the bounds of the original string. If the start is 0 and the end is string.length, then the substring represents the entire original string. That’s conceptually how slices work in Rust too—but with one important difference:&lt;em&gt;Slices are references, not new values.&lt;/em&gt; This distinction is crucial.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why slices exist at all&lt;/strong&gt;&lt;br&gt;
If you already have a reference to a string, and you want to refer to part of that string, you could allocate a new string and copy the data into it. But that would mean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;allocating new memory&lt;/li&gt;
&lt;li&gt;copying bytes&lt;/li&gt;
&lt;li&gt;doing extra work you don’t actually need&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rust looks at this and says: &lt;em&gt;Why not just reference a portion of the original data instead?&lt;/em&gt; That way there is no copying, no new memory allocation, and everything stays fast and explicit. That is exactly why slices exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Slices aren’t just for strings&lt;/strong&gt;&lt;br&gt;
Slices work with arrays too, and the syntax looks very similar.&lt;/p&gt;

&lt;p&gt;With strings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let original_value = String::from("Hello world");
let slice = &amp;amp;original_value[1..7];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;slice&lt;/code&gt; is a &lt;code&gt;&amp;amp;str&lt;/code&gt; pointing to "ello w" inside &lt;code&gt;original_value&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With arrays:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let ages = [13, 21, 37, 4, 55];
let slice = &amp;amp;ages[2..4];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, &lt;code&gt;slice&lt;/code&gt; is a reference to part of the array: &lt;code&gt;[37, 4]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Slices use the form &lt;code&gt;&amp;amp;original_value[start_index..end_index]&lt;/code&gt; where &lt;code&gt;start_index&lt;/code&gt; is inclusive and &lt;code&gt;end_index&lt;/code&gt; is exclusive. So you slice from start_index up to (end_index - 1). You can also omit one or both indices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;amp;value[..]&lt;/code&gt; → the entire value&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;amp;value[..3]&lt;/code&gt; → from the start to index 2&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;amp;value[3..]&lt;/code&gt; → from index 3 to the end&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Final thoughts&lt;/strong&gt;&lt;br&gt;
Slices felt strange to me at first because I kept trying to force them into familiar JS concepts. Once I stopped thinking in terms of “new values” and started thinking in terms of references to existing data, everything clicked.&lt;/p&gt;

&lt;p&gt;If you want to go deeper, the official Rust book explains slices beautifully and in more detail here, including one powerful example why you should use slices:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://doc.rust-lang.org/book/ch04-03-slices.html" rel="noopener noreferrer"&gt;https://doc.rust-lang.org/book/ch04-03-slices.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>programming</category>
      <category>memory</category>
    </item>
    <item>
      <title>The void</title>
      <dc:creator>Lex Nwimue P.</dc:creator>
      <pubDate>Sun, 21 Dec 2025 00:52:26 +0000</pubDate>
      <link>https://dev.to/lexnwimue/the-void-40i2</link>
      <guid>https://dev.to/lexnwimue/the-void-40i2</guid>
      <description>&lt;p&gt;Hello.&lt;/p&gt;

&lt;p&gt;This would be my first article in what is, hopefully, a series on my entanglement with the Rust programming language. Seeing as I like to speak to myself sometimes, you will find leakages of my mental monologues in here—and they might have absolutely nothing to do with the subject matter. No vex.&lt;/p&gt;

&lt;p&gt;That said, I should probably start by stating that I’ve had my fair share of experience with programming. My journey began a long time ago, back in primary school around 2004/2005 (the date could be off by a year or two), when I first saw a computer at my school, Meved Model International School, Oginigba, Port Harcourt.&lt;/p&gt;

&lt;p&gt;I remember there was a short queue of my classmates waiting to “touch” the computer. Like any young child, I was intrigued. When it was my turn, I pressed the letter G. I remember this insignificant detail weirdly well. I had no idea that I was supposed to press and release the key, so I held it down, and a long sequence GGGGGGGGGGGGG appeared on the screen before I was quickly asked to stop. LOL. I moved on and made way for the next kid.&lt;/p&gt;

&lt;p&gt;It wouldn’t be until 2010 before I had access to a computer again. This time, I accompanied my friend (and neighbour), Kemah Barida, to a computer centre in Bori. He was already familiar with using one—I can’t recall where he learned, maybe at school—and he paid for time while I watched. There were several computers in the room, and two kids—likely the owner’s children—were playing what looked like very colourful games in the background. (It was really more of a room than a facility, but I digress.) In my 12-year-old head, it felt like pure luxury.&lt;/p&gt;

&lt;p&gt;I don’t remember exactly what Kemah went there to do, though now that I think about it, it might have been research for a school assignment. What I do remember is basking in the euphoria of seeing—and possibly touching—a computer again. I replayed the scene excitedly in my head for the rest of the evening.&lt;/p&gt;

&lt;p&gt;Fast forward about two years later. I had graduated from secondary school, and my mum paid ₦9,000 out of an agreed ₦12,000 for me to take computer lessons at David’s Investment, 51 Mayor Street, Bori. I trained under Barisiletam (Asile, as we fondly call him), who would later become my mentor, my first boss, and—years later—the person who gifted me my first laptop. I was beyond excited to get started. Also, my mom never really paid the ₦3,000 balance. Either she did, and Asile wouldn't take it or something else, I couldn’t say. &lt;/p&gt;

&lt;p&gt;Over the next few weeks, I was introduced to the typewriter. Disappointingly. :(&lt;/p&gt;

&lt;p&gt;I typed the same text repeatedly on blank A4 sheets. There were folders full of these papers—typed by my predecessors—some of them so neat and error-free they made me jealous. I, on the other hand, always found a way to mess up somewhere on the page. I never completed a full page without errors before I was finally moved on to the next stage of my training: actually using a computer.&lt;/p&gt;

&lt;p&gt;Unfortunately, I’m not very good with hardware, so I can’t tell you exactly what machines we used. What I do know is that they were desktop computers with massive CRT monitors. We had a couple of LCD screens too, but those came a bit later, I think. The keyboards were clunky and loud, but the noise made us feel like badass typers—it amplified our perceived dexterity.&lt;/p&gt;

&lt;p&gt;Almost immediately, I was introduced to Mavis Beacon, where I spent the next couple of weeks. I vividly remember the first time I completed a full session in Penguin Crossing. I was amazed—I’d been trying for weeks. At that point, my typing speed hovered around 30 words per minute. My last measured peak was about 80 WPM a year or two later.&lt;/p&gt;

&lt;p&gt;At this time, I knew almost nothing about programming. Still, this experience alone was enough to make me abandon my plan to study medicine in favour of computer science. Three years later, I’d head to university to do just that—and finally learn, in a classroom setting, what programming really, really was.&lt;/p&gt;

&lt;p&gt;I wrote my first “Hello, World” program in 2016 at Rivers State University, Port Harcourt. Guess what language it was in. Of course—Python. It was the first programming language we learned, and I studied the documentation a lot, despite understanding less than 10% of what I was reading.&lt;/p&gt;

&lt;p&gt;Eventually, we moved on to C++, then Java—the language I first explored extensively. By 2019, I was rounding off school and building an automated attendance system using face detection and recognition. I never fully completed the software, and I didn’t know enough about GitHub at the time to store the code properly, so it eventually got lost on some computer in the school library.&lt;/p&gt;

&lt;p&gt;What I failed to mention is that by 2018, I had done my internship at elitePath Software. That was where I first properly learned HTML, CSS, and some JavaScript. For the first time, I found a language I could naturally resonate with: JavaScript. I fondly referred to it as the language of the gods because of its many quirks. That introduction—eventually leading to Node.js—guided me into backend development, which is what I would go on to build a career in.&lt;/p&gt;

&lt;p&gt;I later dabbled in C#—not for very long, but long enough to land a spot on Microsoft’s .NET Show, where I was invited to speak about the challenges of distributed system design. That video is still on YouTube. After my time with C#, I started thinking about exploring a different space from the traditional API development I’d been doing for a couple of years. That curiosity eventually led me to Rust.&lt;/p&gt;

&lt;p&gt;Between work and personal commitments, it’s been difficult to fully immerse myself in the Rust ecosystem. But in recent weeks, I’ve decided to be more intentional, and I’ve taken things up a notch. That’s why tonight I decided to write about Rust’s unit type (). However, since I’ve made this article unnecessarily long and delightfully distracting, it might be best to save that for another article—probably with a very similar title.&lt;/p&gt;

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