<?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: Dominik</title>
    <description>The latest articles on DEV Community by Dominik (@dominik_alberski).</description>
    <link>https://dev.to/dominik_alberski</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%2F239160%2F3d203814-7fa6-4691-9941-3437b2b0bd63.jpeg</url>
      <title>DEV Community: Dominik</title>
      <link>https://dev.to/dominik_alberski</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dominik_alberski"/>
    <language>en</language>
    <item>
      <title>Reading The Pragmatic Programmer in the age of AI</title>
      <dc:creator>Dominik</dc:creator>
      <pubDate>Tue, 07 Jul 2026 13:51:39 +0000</pubDate>
      <link>https://dev.to/dominik_alberski/reading-the-pragmatic-programmer-in-the-age-of-ai-3jnf</link>
      <guid>https://dev.to/dominik_alberski/reading-the-pragmatic-programmer-in-the-age-of-ai-3jnf</guid>
      <description>&lt;p&gt;I bought &lt;em&gt;The Pragmatic Programmer&lt;/em&gt; a few years ago but never finished it. As part of my current effort to sharpen my fundamentals, I decided to finally read it from cover to cover.&lt;/p&gt;

&lt;p&gt;I expected it to feel slightly dated. The first edition was written in 1999. The second edition came out in 2019, just before generative AI reshaped how many of us work. Instead I found the opposite: most of the principles still hold. What changed isn't their validity — it's the level at which they apply.&lt;/p&gt;

&lt;p&gt;The first thing that stopped me was one sentence in chapter 2. The authors note, almost in passing, that there are still no compilers capable of generating software from a concise description of requirements. Reading that struck a strange tone in my mind. We still don't have the compiler they were imagining, but we do have LLMs and AI agents that occupy a surprisingly similar role — turning a few paragraphs of natural language into working software. A later chapter reinforces the feeling: the authors argue that programming can't be reduced to a mechanical process, or CASE tools would have replaced programmers long ago. History spent twenty years appearing to prove them right. Then it stopped being so obvious.&lt;/p&gt;

&lt;p&gt;That became the question I read the rest of the book with: if implementation is finally being automated, which of these ideas become &lt;em&gt;more&lt;/em&gt; important, and which become less?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Knowledge Portfolio, revisited
&lt;/h2&gt;

&lt;p&gt;Take the &lt;strong&gt;Knowledge Portfolio&lt;/strong&gt;. On the surface, AI seems to reduce the need to learn deeply. Why spend months mastering something an assistant can explain or generate in seconds?&lt;/p&gt;

&lt;p&gt;My strongest evidence to the contrary came from a React migration. I'm primarily a backend developer with little frontend experience. With AI's help I produced a UI that matched the mockups and met every functional requirement. To me, the code looked fine. The senior frontend engineers reviewing it disagreed — it ignored several established patterns in the codebase, and I didn't have enough experience to recognize the problems myself.&lt;/p&gt;

&lt;p&gt;Later, on smaller and more clearly defined tasks, I noticed something. AI followed project conventions much more reliably when I could extract and state those conventions explicitly. The better I understood the rules of the system, the more useful the AI became. The lesson wasn't that AI replaced expertise. It was that expertise determined whether I could recognize good output when I saw it.&lt;/p&gt;

&lt;p&gt;So learning and gaining expertise is still essential. Otherwise how will you notice mistakes in AI thinking? For me, the valuable investment is in mental models — functional programming, distributed systems, architecture, security, AI systems themselves. The goal is no longer accumulating syntax knowledge across many languages but understanding how software behaves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Orthogonality, DRY, and the cost of unclear thinking
&lt;/h2&gt;

&lt;p&gt;The idea that gained the most weight for me was &lt;strong&gt;orthogonality&lt;/strong&gt;. Clear boundaries between modules and responsibilities have always been good practice; in the AI era they're closer to a prerequisite. AI increasingly writes the implementation while the engineer defines interfaces, constraints, and responsibilities — and the quality of those boundaries determines how effectively AI can contribute. Vague definitions produce tangled, duplicated, hard-to-verify output. Clear ones produce something you can actually review and trust.&lt;/p&gt;

&lt;p&gt;This sharpens &lt;strong&gt;DRY&lt;/strong&gt;, too. The principle was always about duplicated &lt;em&gt;knowledge&lt;/em&gt;, not duplicated code — but AI scatters business logic across services and modules so reliably when left unsupervised that the distinction becomes impossible to ignore.&lt;/p&gt;

&lt;p&gt;There's one idea I initially thought was new, then reconsidered. I'd written in my notes that AI makes poor thinking &lt;em&gt;more expensive&lt;/em&gt; — a vague prompt burns tokens, time, and iterations. True, but engineers have always paid for unclear thinking. The currency used to be debugging and rework; now it's tokens and review cycles. The cost isn't new. What's new is how fast and how visibly it arrives. AI acts less like a new source of risk and more like a mirror: it doesn't create bad habits, it reflects them back faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Blackboard pattern, reframed
&lt;/h2&gt;

&lt;p&gt;Master your tools, invest in your environment — still valid. But increasingly the tool is operated by an &lt;em&gt;agent&lt;/em&gt;, not typed directly by a developer. Which makes plain text more central, not less: it's the medium through which intent reaches both humans and machines, in prompts, configuration files, and instructions. The skill that used to be "master your tools" is becoming "design workflows that you and an AI can both operate in effectively."&lt;/p&gt;

&lt;p&gt;That reframing shows up most clearly in the &lt;strong&gt;Blackboard pattern&lt;/strong&gt; — one of the book's more academic-feeling ideas, where independent specialists post partial solutions to a shared space until a solution emerges. It suddenly resembles modern multi-agent systems, where specialized agents collaborate through a shared space rather than a shared conversation.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi5ct4683vgwq4ycnbeqz.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%2Fi5ct4683vgwq4ycnbeqz.png" alt=" " width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The reframe I keep coming back to is that what agents need to share isn't conversational context, which gets expensive fast, but structured knowledge: goals, decisions, findings, tasks.&lt;/p&gt;

&lt;p&gt;Shared knowledge rather than shared context.&lt;/p&gt;

&lt;p&gt;The more I experiment with agentic systems, the more I believe preserving useful knowledge matters more than preserving every step of the conversation that produced it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing: don't let AI do the thinking part
&lt;/h2&gt;

&lt;p&gt;One place that caught my interest was testing. The authors frame tests as valuable less for catching bugs than for forcing you to reason about your code before you write it — and that matches what TDD taught me: deciding how to test something is part of designing it.&lt;/p&gt;

&lt;p&gt;Which is why I'm cautious about handing testing entirely to an AI. Ask an agent to "add test coverage" and it will — but if it does the thinking too, you skip the part that was actually useful. You never ask what the code should guarantee, where it might break, or what "correct" means here. The tests exist, but the design reasoning they usually prompt didn't happen. So in practice I let the AI write the tests while I stay responsible for what to test — writing assertions is mechanical; deciding what to verify is where the thinking is.&lt;/p&gt;

&lt;h2&gt;
  
  
  The lizard brain, and where instinct comes from
&lt;/h2&gt;

&lt;p&gt;That worry generalizes. The authors tell you to trust your "lizard brain" — the instinct you develop from years of writing, debugging, and refactoring code yourself. That instinct is &lt;em&gt;earned&lt;/em&gt;, and it's earned specifically by doing the work. So what happens when AI does more and more of that work? Can you build the same intuition reviewing generated code that you'd build writing it yourself? Or will the next generation of developers grow a different instinct — one tuned to architecture, decomposition, and judging AI output rather than to implementation detail?&lt;/p&gt;

&lt;p&gt;I genuinely enjoy working with AI. It automates the repetitive parts and lets me explore ideas faster than before. But every problem it solves for me is a problem I don't solve myself — and solving problems is how experience accumulates. There's a balance to strike between using AI as a productivity tool and protecting the learning that produces judgment in the first place.&lt;/p&gt;

&lt;p&gt;That, in the end, is what rereading &lt;em&gt;The Pragmatic Programmer&lt;/em&gt; left me with. Software engineering is becoming less about writing code and more about making decisions — architecture, domain modeling, contracts, boundaries. You can't reason well about AI-generated code if you don't understand software engineering yourself. Knowledge hasn't become less important; it's shifted from producing code to evaluating and guiding it.&lt;/p&gt;

&lt;p&gt;The book didn't change my mind about AI. It sharpened it. The implementation was never the hardest part of the job. If AI keeps automating the mechanics, the ability to think clearly about software may become the most valuable skill a developer can have — and I'm genuinely unsure how we'll keep teaching it once the machine is doing the reps.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ai</category>
      <category>tdd</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Rails Integration Testing with Fixtures: A Practical Approach for Complex Data Sets</title>
      <dc:creator>Dominik</dc:creator>
      <pubDate>Tue, 07 May 2024 07:47:48 +0000</pubDate>
      <link>https://dev.to/dominik_alberski/rails-integration-testing-with-fixtures-a-practical-approach-for-complex-data-sets-mce</link>
      <guid>https://dev.to/dominik_alberski/rails-integration-testing-with-fixtures-a-practical-approach-for-complex-data-sets-mce</guid>
      <description>&lt;h4&gt;
  
  
  The Challenge of Realistic Test Data
&lt;/h4&gt;

&lt;p&gt;I recently faced a unique challenge in writing integration specs for a Rails application. The goal was to simulate real-world complexity within our test environment, involving interactions across 13 models like orders, line items, and products. The catch? I needed to generate around 10,000 interrelated records, reflecting the kind of volume and complexity we see in production. Typically, I'd reach for the &lt;code&gt;factory_bot&lt;/code&gt; gem for test data generation, but due to the sheer volume and the need for persistent data, this method proved too slow. My ideal solution needed to enable the insertion of a large volume of data into the database efficiently, mirroring production data characteristics as closely as possible.&lt;/p&gt;

&lt;h4&gt;
  
  
  Solution: Tapping into Production DB and Fixtures
&lt;/h4&gt;

&lt;p&gt;After exploring several avenues, I discovered that leveraging Rails' default fixtures, combined with our staging database (which mirrors the last three months of production records), provided an unexpectedly effective solution. Here’s how I transformed real production data into a manageable, anonymized test suite:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fixture_creator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;anonymized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;root&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/spec/fixtures/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;table_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.yml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"w+"&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;fixture_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;in_batches&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;of: &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="n"&gt;fixture_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;fixture_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
          &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;anonymized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt; &lt;span class="n"&gt;fixture_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_yaml&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Exploring the Code
&lt;/h4&gt;

&lt;p&gt;In this snippet, &lt;code&gt;fixture_creator&lt;/code&gt; function does the heavy lifting:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Batch Processing&lt;/strong&gt;: By processing the data in batches (&lt;code&gt;model.in_batches(of: 100)&lt;/code&gt;), we efficiently handle large volumes of data without overwhelming memory usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unique Keys for Fixtures&lt;/strong&gt;: We create unique keys for each record (&lt;code&gt;"#{record.id}_#{fixture_data.size + 1}"&lt;/code&gt;), ensuring each entry in our fixtures file is distinct and easily identifiable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anonymization&lt;/strong&gt;: The &lt;code&gt;anonymized&lt;/code&gt; parameter is a hash that overrides sensitive attributes with dummy values, crucial for maintaining data privacy.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach significantly speeds up the process compared to individually creating records via &lt;code&gt;factory_bot&lt;/code&gt;. By directly exporting data from a staging environment (a subset of our production data), we ensure our tests are running against data that closely reflects real user interactions, both in volume and complexity.&lt;/p&gt;

&lt;h4&gt;
  
  
  Anonymization and Security
&lt;/h4&gt;

&lt;p&gt;One key aspect of using production data for testing is ensuring all sensitive information is thoroughly anonymized. In my case, the &lt;code&gt;anonymized&lt;/code&gt; hash includes mappings of original attribute names to anonymized values, applied to each record. This step is crucial not just for security and privacy, but also for complying with legal obligations like GDPR.&lt;/p&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;This method of generating fixtures from production data presents a robust way to create realistic, high-volume test environments for Rails applications. It's particularly useful when the test scenarios are complex, and the realism of data interrelations is crucial. While this approach worked well in my case, it's important to tailor the solution to the specific needs and constraints of your project and always prioritize data security in any testing strategy.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>testing</category>
      <category>fixtures</category>
    </item>
    <item>
      <title>Memoization in Modern Ruby: How a Shape-Based Approach to Instance Variables Lookup Impacts Performance.</title>
      <dc:creator>Dominik</dc:creator>
      <pubDate>Thu, 02 Nov 2023 11:32:39 +0000</pubDate>
      <link>https://dev.to/dominik_alberski/memoization-in-modern-ruby-using-a-shape-based-approach-to-instance-variables-lookup-2lok</link>
      <guid>https://dev.to/dominik_alberski/memoization-in-modern-ruby-using-a-shape-based-approach-to-instance-variables-lookup-2lok</guid>
      <description>&lt;p&gt;Memoization is a classic technique in Ruby programming, greatly assisting in boosting performance. With Ruby's ongoing evolution, particularly towards a shape-based method in instance variable lookups, thoughtfully implementing memoization can be beneficial. Inspired by Jean Boussier's insights on RailsAtScale.com, this post highlights some suggested best practices.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Consider Memoization?
&lt;/h4&gt;

&lt;p&gt;Memoization helps cache results of resource-heavy function calls, aiming to speed up subsequent executions. Ruby’s newer shape-based mechanism for instance variable lookups suggests organizing objects based on their instance variables. This approach influences performance and memory usage, but it's important to note that using memoization indiscriminately could lead to a range of object shapes, which might inadvertently affect performance. Understanding these subtleties can be helpful for developers looking to craft efficient and thoughtful Ruby code.&lt;/p&gt;

&lt;h4&gt;
  
  
  Suggested Best Practices
&lt;/h4&gt;

&lt;p&gt;Aligning with Ruby's shape-based approach and optimizing memoization strategies, developers might consider the following approaches:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Mindful Use of Memoized Variables&lt;/strong&gt;: It’s generally a good idea to keep memoized variables to a minimum. Ideally, aiming for one or two per class helps. If you find yourself needing more, initializing these variables to &lt;code&gt;nil&lt;/code&gt; in the constructor could be a proposed better approach:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt; 
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;     
        &lt;span class="vi"&gt;@expensive_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;   
    &lt;span class="k"&gt;end&lt;/span&gt;    

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;expensive_value&lt;/span&gt;     
        &lt;span class="vi"&gt;@expensive_value&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="n"&gt;compute_expensive_value&lt;/span&gt;   
    &lt;span class="k"&gt;end&lt;/span&gt; 
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Handling Falsy Values with Tokens&lt;/strong&gt;: When dealing with memoized values that might return falsy results, using a token could be a neat way to differentiate between an uninitialized state and a value that's legitimately falsy:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt;   
    &lt;span class="no"&gt;NOT_SET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;   
    &lt;span class="n"&gt;private_constant&lt;/span&gt; &lt;span class="ss"&gt;:NOT_SET&lt;/span&gt;    
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;     
        &lt;span class="vi"&gt;@expensive_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;NOT_SET&lt;/span&gt;   
    &lt;span class="k"&gt;end&lt;/span&gt;    

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;expensive_value&lt;/span&gt;     
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="vi"&gt;@expensive_value&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="vi"&gt;@expensive_value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;NOT_SET&lt;/span&gt;     &lt;span class="vi"&gt;@expensive_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute_expensive_value&lt;/span&gt;   
        &lt;span class="k"&gt;end&lt;/span&gt; 
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Wrapping Up
&lt;/h4&gt;

&lt;p&gt;Adjusting to Ruby's shape-based approach for variable lookups, we might consider refining our memoization tactics to help maintain efficient performance and thoughtful memory usage. For those interested in exploring this topic further, Jean Boussier provides a deeper dive in his article at &lt;a href="https://railsatscale.com/2023-10-24-memoization-pattern-and-object-shapes/"&gt;RailsAtScale&lt;/a&gt;. It's a thought-provoking read for anyone interested in evolving their Ruby coding practices in harmony with the latest language developments.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This summary reflects ideas from Jean Boussier's article published on October 24, 2023, on RailsAtScale.com. To broaden your understanding, the original article is well worth a read.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>performance</category>
    </item>
  </channel>
</rss>
