<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Michal Pasierbski</title>
    <description>The latest articles on Forem by Michal Pasierbski (@pasmichal).</description>
    <link>https://forem.com/pasmichal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F198899%2F1c317475-7d3a-4050-b4f0-f3fa54824dae.png</url>
      <title>Forem: Michal Pasierbski</title>
      <link>https://forem.com/pasmichal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/pasmichal"/>
    <language>en</language>
    <item>
      <title>Agents are the New Websites: The Evolution of the Software Engineer</title>
      <dc:creator>Michal Pasierbski</dc:creator>
      <pubDate>Sat, 14 Feb 2026 09:38:02 +0000</pubDate>
      <link>https://forem.com/pasmichal/agents-are-the-new-websites-the-evolution-of-the-software-engineer-4jpb</link>
      <guid>https://forem.com/pasmichal/agents-are-the-new-websites-the-evolution-of-the-software-engineer-4jpb</guid>
      <description>&lt;p&gt;For the last twenty years, the "Web Developer" was the protagonist of the tech industry. We mastered the DOM, wrestled with CSS frameworks, and perfected the art of the CRUD app.&lt;/p&gt;

&lt;p&gt;But the wind has shifted.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Era of "Too Easy"
&lt;/h2&gt;

&lt;p&gt;Building a standard website has become a "solved" problem. Between low-code platforms and AI coding assistants, the barrier to entry has collapsed. If a prompt can generate a functional React component in three seconds, the value of the "builder" is no longer in the construction—it's in the architecture.&lt;/p&gt;

&lt;p&gt;We've reached a point where the world doesn't need more pixel-pushers; it needs orchestrators.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Market is Speaking (and it's loud)
&lt;/h2&gt;

&lt;p&gt;This isn't just a hunch; it's reflected in the data. If you look at the recent analysis of engineering roles, the demand for traditional Frontend Engineers is shrinking.&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%2Fznjv1jqb9row845hs7r7.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%2Fznjv1jqb9row845hs7r7.png" alt=" " width="740" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As companies automate their interface layers, the "Front-end" is becoming a commodity. The premium salaries and the high-growth roles are moving "upstream." They are moving toward the systems that drive the interfaces. If your value is tied strictly to translating a Figma design into HTML/CSS, you are competing against a machine that doesn't sleep and costs pennies.&lt;/p&gt;

&lt;h2&gt;
  
  
  From UI to Agency
&lt;/h2&gt;

&lt;p&gt;The website was a destination—a place where a human went to perform a task. The AI Agent is the evolution of that destination. Instead of a user navigating a menu to book a flight, an agent understands the intent and executes the workflow across multiple APIs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Websites are passive containers.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agents are active problem-solvers.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As engineers, our job is shifting from building the pages to building the brains. We are moving away from defining exactly how a button looks and toward defining how a system reasons, uses tools, and recovers from errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Engineering Identity Crisis
&lt;/h2&gt;

&lt;p&gt;I've felt it too. There's a comfort in the "Edit-Refresh" cycle of web dev. But as the "easy" parts of our jobs are swallowed by automation, we face a choice: stay in the shrinking space of interface implementation or evolve into Agentic Engineers.&lt;/p&gt;

&lt;p&gt;This transition isn't just about swapping JavaScript for Python. It's a fundamental shift in how we think about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Non-deterministic logic:&lt;/strong&gt; Handling outputs that aren't always the same.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool-use:&lt;/strong&gt; Teaching models to interact with the real world safely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliability:&lt;/strong&gt; Moving beyond "it compiles" to "it actually works."&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introducing: Practically Agents
&lt;/h2&gt;

&lt;p&gt;I realized that while there are a million tutorials on how to "chat with a PDF," there is a massive gap in how to build production-grade agents. Most "Hello World" agent tutorials fail the second they hit real-world data or edge cases.&lt;/p&gt;

&lt;p&gt;That's why I created Practically Agents. It's a resource designed for the engineer who is ready to move past the hype. We aren't just playing with prompts; we are building robust, scalable, and reliable agentic systems. It's the curriculum I needed for my own evolution to stay relevant in a changing market, and now it's here for yours.&lt;/p&gt;

&lt;p&gt;The era of the website isn't over, but its reign as the "center of the universe" is. It's time to start building the agents that will run the world.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://practicallyagents.com/articles/agents-are-the-new-websites/" rel="noopener noreferrer"&gt;https://practicallyagents.com/articles/agents-are-the-new-websites/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>career</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>How to Pass Data from a Function Tool to State in ADK (Agent Development Kit)</title>
      <dc:creator>Michal Pasierbski</dc:creator>
      <pubDate>Mon, 21 Apr 2025 16:16:25 +0000</pubDate>
      <link>https://forem.com/pasmichal/how-to-pass-data-from-a-function-tool-to-state-in-adk-agent-development-kit-2p2n</link>
      <guid>https://forem.com/pasmichal/how-to-pass-data-from-a-function-tool-to-state-in-adk-agent-development-kit-2p2n</guid>
      <description>&lt;h2&gt;
  
  
  What is ADK?
&lt;/h2&gt;

&lt;p&gt;Google’s new ADK (Agent Development Kit) is an exciting step forward in building AI agents. Think of it as a framework for composing tools, states, and logic in a way that feels modular and powerful—kind of like LangChain or LangGraph, but backed by Google.&lt;/p&gt;

&lt;p&gt;IMO it has lower learning curve than LangGraph while offering the same functionality, better local development tooling and straight forward deployment options to Agent Engine or Cloud Run (for details see &lt;a href="https://google.github.io/adk-docs/deploy/" rel="noopener noreferrer"&gt;docs&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  What is state?
&lt;/h2&gt;

&lt;p&gt;In ADK state is a mutable object shared between agents and tools. It holds all the data that flows through your agent’s workflow—like user inputs, intermediate results, or tool outputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to set state from function tool?
&lt;/h2&gt;

&lt;p&gt;It’s not clearly documented in the official docs, but thankfully the source code is well-structured and readable.&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%2Fh7onhx6ddv0i8uad9xqd.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%2Fh7onhx6ddv0i8uad9xqd.png" alt="Code fragment that injects ToolContext to tool function" width="800" height="306"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Source: &lt;a href="https://github.com/google/adk-python/blob/1664b455627c01194a804b880d31bd2602e1a447/src/google/adk/tools/function_tool.py#L59" rel="noopener noreferrer"&gt;https://github.com/google/adk-python/blob/1664b455627c01194a804b880d31bd2602e1a447/src/google/adk/tools/function_tool.py#L59&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can get hold of &lt;a href="https://google.github.io/adk-docs/context/#the-different-types-of-context" rel="noopener noreferrer"&gt;&lt;code&gt;ToolContext&lt;/code&gt;&lt;/a&gt; object (which holds reference to the state object) by adding an argument named &lt;code&gt;tool_context&lt;/code&gt; to your tool function signature - ADK will inject the value. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.adk.agents&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LlmAgent&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.prompt&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;system_prompt&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.adk.tools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ToolContext&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_prd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool_context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ToolContext&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;tool_context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;prd&lt;/span&gt;&lt;span class="sh"&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;prd&lt;/span&gt;

&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LlmAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;product_owner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A product owner agent that is responsible for the product vision and strategy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-2.0-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;instruction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;save_prd&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ai</category>
      <category>adk</category>
      <category>python</category>
    </item>
    <item>
      <title>Dead simple Role-based access control in supabase</title>
      <dc:creator>Michal Pasierbski</dc:creator>
      <pubDate>Tue, 22 Aug 2023 09:26:02 +0000</pubDate>
      <link>https://forem.com/pasmichal/dead-simple-role-based-access-control-in-supabase-3ffp</link>
      <guid>https://forem.com/pasmichal/dead-simple-role-based-access-control-in-supabase-3ffp</guid>
      <description>&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; &lt;em&gt;I got featured on Community Highlights!&lt;/em&gt;&lt;/p&gt;

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

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



&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I shared this post 👇 and it gained more attention than I expected (considering my usual standards 😅). Here’s a breakdown of how everything comes together.&lt;/em&gt;&lt;/p&gt;

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

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



&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Defining Roles
&lt;/h1&gt;

&lt;p&gt;For a more human-friendly approach to referencing roles, you can create a custom enum type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TYPE&lt;/span&gt; &lt;span class="n"&gt;user_role&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nb"&gt;ENUM&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'spots_moderator'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'admin'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  2. Setting Up the “user_roles” Table
&lt;/h1&gt;

&lt;p&gt;The &lt;code&gt;user_roles&lt;/code&gt; table allows us to link roles with users. To ensure the security of user_roles, enable Row-Level Security (RLS) and implement the policy:&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%2F0o8iyvbovj2o9j3mbixy.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%2F0o8iyvbovj2o9j3mbixy.png" alt=" " width="525" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To secure user_roles enable RLS (Row-level security) and add following policy &lt;code&gt;auth.uid() = user_id&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fezco4ufnqullq2ukfq1b.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%2Fezco4ufnqullq2ukfq1b.png" alt=" " width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This policy grants authenticated users access to read the roles they possess.&lt;/p&gt;

&lt;p&gt;Key points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;user_id&lt;/code&gt; references &lt;code&gt;auth.users.id&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The role is based on the &lt;code&gt;user_role&lt;/code&gt; type (the enum type from step 1.)&lt;/li&gt;
&lt;li&gt;RLS enables reading of roles owned by the user&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  3. Implementing Row-Level Security for Role-Specific Access
&lt;/h1&gt;

&lt;p&gt;You can now control access to specific rows within a table, such as &lt;code&gt;spot_proposals&lt;/code&gt; in this case, by users with particular roles. This is done by specifying the following RLS condition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;user_roles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;
   &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;user_roles&lt;/span&gt;
  &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_roles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'spots_moderator'&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;user_role&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fohy815bh1d589o2w7dcc.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%2Fohy815bh1d589o2w7dcc.png" alt=" " width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Key points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;user_roles&lt;/code&gt; has an RLS policy, allowing authenticated users to read their roles&lt;/li&gt;
&lt;li&gt;The RLS policy on &lt;code&gt;spot_proposals&lt;/code&gt; restricts access to specific roles, such as &lt;code&gt;spots_moderator&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This setup ensures a straightforward yet effective role-based access control mechanism in Supabase.&lt;/p&gt;

&lt;p&gt;Looking for more Supabase content? Join me on &lt;a href="https://twitter.com/mpasierbski" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; for the latest updates, tutorials, and insights! Follow along to stay in the loop.&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>webdev</category>
      <category>database</category>
    </item>
    <item>
      <title>Dart: late + final = easy and safe caching</title>
      <dc:creator>Michal Pasierbski</dc:creator>
      <pubDate>Sun, 08 Jan 2023 10:19:57 +0000</pubDate>
      <link>https://forem.com/pasmichal/dart-late-final-easy-and-safe-caching-11ib</link>
      <guid>https://forem.com/pasmichal/dart-late-final-easy-and-safe-caching-11ib</guid>
      <description>&lt;p&gt;Let's say You have a &lt;code&gt;Person&lt;/code&gt; class and You want to expose &lt;code&gt;netWorth&lt;/code&gt; field.&lt;br&gt;
There is a backend API to fetch it but it's pretty expensive.&lt;br&gt;
Backend needs to call all associated bank APIs, convert currencies, calculate real estate values, etc.&lt;br&gt;
Here's how to use new &lt;code&gt;late&lt;/code&gt; variables feature to implement easy and safe caching.&lt;/p&gt;

 
&lt;h2&gt;
  
  
  Naive approach
&lt;/h2&gt;

&lt;p&gt;We could start with super simple approach, i.e. fetch the value every time we use it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;num&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;netWorth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_fetchNetWorth&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// await person.netWorth()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Cache result
&lt;/h2&gt;

&lt;p&gt;Instead of calling &lt;code&gt;_fetchNetWorth&lt;/code&gt; every time we could call it only once and cache the results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;num&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;_fetchNetWorthFuture&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;num&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;netWorth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_fetchNetWorthFuture&lt;/span&gt; &lt;span class="o"&gt;??=&lt;/span&gt; &lt;span class="n"&gt;_fetchNetWorth&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_fetchNetWorthFuture&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// await person.netWorth()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is an open question hanging in the air: why &lt;code&gt;netWorth&lt;/code&gt; is &lt;code&gt;Future&amp;lt;num&amp;gt;&lt;/code&gt; and not simply &lt;code&gt;num&lt;/code&gt;?&lt;br&gt;
We could have some initialization function that could resolve the future, right?&lt;/p&gt;

&lt;p&gt;I'm not a fan of such initialization functions because it creates unnecesarry dependency that can quickly become unmanagable.&lt;/p&gt;

&lt;p&gt;What if we have another field in the class that has to be fetched? We throw it in init function!&lt;/p&gt;

&lt;p&gt;What if we need only one not the other? Should we have two init functions? Or maybe have some logic what to initialize?&lt;/p&gt;

&lt;p&gt;Futures are cheap and I like the explicit contract that we expose. Consumer of our class knows from the get-go that this value has some cost.&lt;/p&gt;

&lt;p&gt;Ok, now we cached the result (or rather Future of the result) so we don't make the expensive call again.&lt;br&gt;
There is not much more we can do in terms of resource optimisation, but we can optimise the code a bit - we can get rid of the intermidiate &lt;code&gt;_fetchNetWorthFuture&lt;/code&gt; variable.&lt;/p&gt;
&lt;h2&gt;
  
  
  late + final
&lt;/h2&gt;

&lt;p&gt;With introduction of sound null-safty we got access to &lt;a href="https://dart.dev/null-safety/understanding-null-safety#late-variables" rel="noopener noreferrer"&gt;&lt;code&gt;late&lt;/code&gt;&lt;/a&gt; keyword. &lt;code&gt;late&lt;/code&gt; allows us to take responsibility of nullness of the value. It's like telling compiler "trust me, the value will be there when I use it".&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The late modifier has some other special powers too. It may seem paradoxical, but you can use late on a field that has an initializer:&lt;br&gt;
&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Possibility to have initializer on &lt;code&gt;late&lt;/code&gt; variables allows us to get rid of intermidiate &lt;code&gt;_fetchNetWorthFuture&lt;/code&gt; variable.&lt;br&gt;
Slapping &lt;code&gt;final&lt;/code&gt; gives us compilte time guarantee that the variable will be assigned only once.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Potentially expensive calculation.&lt;/span&gt;
  &lt;span class="kd"&gt;late&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;netWorth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_fetchNetWorth&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// await person.netWorth&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;This post was originally posted on my blog at &lt;a href="https://www.stuffs.dev/posts/dart-late-final-for-simple-and-safe-caching/" rel="noopener noreferrer"&gt;stuffs.dev&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://dart.dev/null-safety/understanding-null-safety#lazy-initialization" rel="noopener noreferrer"&gt;https://dart.dev/null-safety/understanding-null-safety#lazy-initialization&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>dart</category>
    </item>
    <item>
      <title>Free blog setup with GitHub and Hugo</title>
      <dc:creator>Michal Pasierbski</dc:creator>
      <pubDate>Sat, 07 Jan 2023 21:34:26 +0000</pubDate>
      <link>https://forem.com/pasmichal/free-blog-setup-with-github-and-hugo-p0n</link>
      <guid>https://forem.com/pasmichal/free-blog-setup-with-github-and-hugo-p0n</guid>
      <description>&lt;p&gt;I recently moved my blog from Wordpress hosted on DigitalOcean to &lt;a href="https://gohugo.io/" rel="noopener noreferrer"&gt;Hugo&lt;/a&gt; hosted on &lt;a href="https://pages.github.com/" rel="noopener noreferrer"&gt;GitHub pages&lt;/a&gt;. Here's how and why I did it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;Because I'm cheap and spending ~10$/month for a blog that gets close to 0 traffic and close to 0 attention from the owner hurts my onion hearth.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Hugo?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://gohugo.io/" rel="noopener noreferrer"&gt;Hugo&lt;/a&gt; is a static site generator (SSG) written in Go. It's main strength is speed of generation, but I like it for other reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Convention over configuration&lt;/li&gt;
&lt;li&gt;"All you need" features out of the box&lt;/li&gt;
&lt;li&gt;Maybe not the biggest but definitely high quality community&lt;/li&gt;
&lt;li&gt;Easy to understand, no magic source code&lt;/li&gt;
&lt;li&gt;Markdown 💖&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Migrating content
&lt;/h2&gt;

&lt;p&gt;Hugo content is written in Markdown so I had to transform it. And since my blog had at the time enormous amount of content, i.e. 2 posts, I did that manually using .&lt;/p&gt;

&lt;p&gt;The easiest way is to simply open each blog post, inspect the source in Chrome, find the first wrapping dom node in the inspector, right click and select "Copy outerHTML". Paste result in to &lt;a href="https://codebeautify.org/html-to-markdown" rel="noopener noreferrer"&gt;https://codebeautify.org/html-to-markdown&lt;/a&gt; and enjoy freshly baked Markdown.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If You need your old posts to appear under the same URL You can use &lt;a href="https://gohugo.io/content-management/front-matter/#predefined" rel="noopener noreferrer"&gt;&lt;code&gt;aliases&lt;/code&gt;&lt;/a&gt; field in post frontmatter.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hosting
&lt;/h2&gt;

&lt;p&gt;GitHub distingushes 3 types of pages: personal, organization and project. Since it's a personal blog I followed the guidelines for that type. In this case GitHub requires that the repo must be named after the username, in my case &lt;code&gt;https://github.com/pasierb/pasierb&lt;/code&gt;.&lt;br&gt;
Side benefit of this naming scheme is that the repo's README becomes your &lt;a href="https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/managing-your-profile-readme" rel="noopener noreferrer"&gt;profile README&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I was worried that I will need to learn GitHub Actions to run hugo build, but suprisingly once GitHub notices that the repo is a Hugo project I got predefined build configuration suggested and it works flowlessly (awesome job GH!).&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom domain
&lt;/h2&gt;

&lt;p&gt;To set up custom domain for GitHub Pages I had to verify that I own the domain, which boils down to setting some TXT record in DNS.&lt;/p&gt;

&lt;p&gt;On thing that I noticed once the project was available at &lt;code&gt;www.stuffs.dev&lt;/code&gt; is that assets are not loading and paths are wrong. Turns out that Hugo be default uses relative paths which is problematic since GH Pages uses username path prefix, e.g. &lt;code&gt;pasierb.github.io/PASIERB&lt;/code&gt;.&lt;br&gt;
In order for things to work correctly with path prefix I had to force Hugo to use absolute paths when generating HTMLs. Fortunately it's as easy as setting &lt;code&gt;canonifyURLs = true&lt;/code&gt; in &lt;code&gt;config.toml&lt;/code&gt;. That's it!&lt;/p&gt;

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

&lt;p&gt;Moving everything took me probably less than 2h which I find a great result. Developer experience both on GitHub side as well as Hugo is top notch. &lt;br&gt;
10$/month more in my pocket is also top notch 🤑.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originially posted on my blog at &lt;a href="https://www.stuffs.dev/posts/free-blog-setup-with-github-and-hugo/" rel="noopener noreferrer"&gt;www.stuffs.dev&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ai</category>
      <category>openai</category>
    </item>
    <item>
      <title>How I got to Google as a self-taught software engineer.</title>
      <dc:creator>Michal Pasierbski</dc:creator>
      <pubDate>Fri, 09 Sep 2022 20:27:24 +0000</pubDate>
      <link>https://forem.com/pasmichal/how-i-got-to-google-as-a-self-taught-software-engineer-3e27</link>
      <guid>https://forem.com/pasmichal/how-i-got-to-google-as-a-self-taught-software-engineer-3e27</guid>
      <description>&lt;p&gt;Landing a SWE job at Google is no easy feat. Being self-taught seemingly hinders one's chances, but how about adding to it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;being thirty-something years old (closer to 40 than 30 😅)&lt;/li&gt;
&lt;li&gt;having wife, small kid and a dog&lt;/li&gt;
&lt;li&gt;being only source of income for family&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;FAANG interviews are notoriously difficult. Good news is that if I could do it, so can you! Here are some battle-tested tips how to prepare.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to study
&lt;/h2&gt;

&lt;p&gt;In my circumstances time I could spent on learning was pretty limited. Full time job, small kid, wife - there is not much time and energy left in a day.&lt;/p&gt;

&lt;p&gt;I tried to do 8 hours on weekends and fail miserably because kid wants to play (and I want it to!), wife wants to go to IKEA (and I want it to!), dog wants to go for a walk (and... you guessed it).&lt;/p&gt;

&lt;p&gt;I tried late nights after family goes to sleep and failed again. I would do some productive work for first hour and then sit for next 3 staring at the screen not even noticing that I'm just passing time and depleting myself from sleep.&lt;/p&gt;

&lt;p&gt;What changed my approach was to stop thinking about prepping to "the interview" but rather to be better software engineer. From being goal oriented - passing the interview - to being process oriented - being better software engineer.&lt;/p&gt;

&lt;p&gt;I would do 30-60 mins daily sessions and that was a game changer. Not only I had more energy for my family, but it also learned at higher pace. Having shorter sessions allowed me digest the material better, think about it throughout the day and make it stick to brain's long-term memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Know your basics
&lt;/h2&gt;

&lt;p&gt;Think about it as your tools. You need to have them handy and know how to use them. In 30-40 mins that you have to solve a problem(s) there is no time to figure out how BFS, DFS,  works - you HAVE TO have this knowledge available to you at will.&lt;/p&gt;

&lt;p&gt;Must know topics IMO in no particular order:&lt;/p&gt;

&lt;h3&gt;
  
  
  Data structures:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Linked lists&lt;/li&gt;
&lt;li&gt;Arrays&lt;/li&gt;
&lt;li&gt;Maps&lt;/li&gt;
&lt;li&gt;Sets&lt;/li&gt;
&lt;li&gt;Trees / Graphs / Tries (this tend to very useful)&lt;/li&gt;
&lt;li&gt;Heaps&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Algorithms:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;basic sorting algorithms&lt;/li&gt;
&lt;li&gt;Dijkstra's algorithm - a lot of interview problems are some sort of variations&lt;/li&gt;
&lt;li&gt;backtracking&lt;/li&gt;
&lt;li&gt;dynamic programming&lt;/li&gt;
&lt;li&gt;tree traversal (DFS, BFS)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Practice
&lt;/h2&gt;

&lt;p&gt;I distinguish two phases of practice:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Basics&lt;/li&gt;
&lt;li&gt;Problem solving&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Basics
&lt;/h3&gt;

&lt;p&gt;For basics there is not other way that just writing code. Once you understand basic concepts you need to be fluent in transcribing those ideas to code. Don't memorise implementation, understand well enough that you can implement it without effort.&lt;/p&gt;

&lt;p&gt;The goal is to build ready to use mental blocks. If part of the problem is to traverse a tree you could say "I'm going to use breath-first-search, it's going to be O(n) time complexity" and focus on next part of the challenge.&lt;/p&gt;

&lt;p&gt;You need to be ready to talk about details of implementation, but chances are that you won't need to write it down.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem solving
&lt;/h3&gt;

&lt;p&gt;This might be a bit controversial, but I believe that you either know the solution or not. There is to little time to figure it out on the spot. This is where purposeful learning comes to play.&lt;/p&gt;

&lt;p&gt;Start with easy problems, get comfortable. When it's getting to comfortable start moving to medium difficulty. Up the ante enough to keep you engaged but not discouraged. If you're stuck for more than 15 minutes, then just read the solution - that's how you learn!&lt;/p&gt;

&lt;p&gt;Once you're fairly comfortable with coding up the solutions... stop coding. Solve it in your head and check answers in forums to verify. My rule of thumb was no more than 10 minutes per question. Again, if you can't solve it  just lookup the solution, try to understand it and move on - chances are you will encounter this question again.&lt;/p&gt;

&lt;p&gt;This approach should develop in You some intuition what data structures to use, what kind of algorithm problem lends itself to. You will rather not encounter the same question in the interview, but it might be similar.&lt;/p&gt;

&lt;h2&gt;
  
  
  During interview
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Think out loud
&lt;/h3&gt;

&lt;p&gt;Your thinking process matters. Your interviewer can't read your mind, read it to her. If you considering array, say it. If it's something You discard, explain why. This also allows your interviewer to push you in the right direction.&lt;/p&gt;

&lt;p&gt;One thing to pay attention to is rambling. If you notice that your thoughts are chaotic and you interviewer is confused, stop for a second. Say that you need a minute to think and relax.&lt;/p&gt;

&lt;h3&gt;
  
  
  Explain your approach
&lt;/h3&gt;

&lt;p&gt;Before You start writing code you have to have clear picture how to arrive at solution. Write down your algorithms in plain words and discuss it with your interviewer. I always ask directly "shall we proceed to coding?". Most interviewers will signal to you if she has some concerns and you should correct your approach first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use helper functions
&lt;/h3&gt;

&lt;p&gt;Focus on high level solution first using helper functions and fill them out later. For example: if you have algorithms that need topological sort, just write it as you would have it - &lt;code&gt;topologicalSort(items)&lt;/code&gt; - and tell your interviewer that you will implement it later. Here it's important that you know your basics and can identify time/space complexity  for those helpers so interviewer feels confident that you know how to implement it.&lt;/p&gt;

&lt;p&gt;It is possible that interviewer will get enough signals and you won't have to fill in those helper functions. The key point here is to have complete algorithm in time. Chances are that there is a follow up question and your helpers become irrelevant anyways.&lt;/p&gt;

&lt;h2&gt;
  
  
  Just try!
&lt;/h2&gt;

&lt;p&gt;Let's face it, chances that you will nail it in first try are slim. Why not get some practice then? Apply early and see where you stand. Don't get me wrong - try your best, prepare like your life depends on it, but keep in mind that it may not be your last time applying ;) I applied to all FAANG companies and others known to have similar interview process, just to get some reps in. Even if you apply to company that is not you first choice you might ended up getting hard to reject offer (BTW that's how I ended up at Amazon in Berlin).&lt;/p&gt;

&lt;p&gt;There is a lot of stress involved and you will forget about details so take notes about the process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what questions were you asked&lt;/li&gt;
&lt;li&gt;what worked and what not&lt;/li&gt;
&lt;li&gt;what areas to focus next time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It will come handy next time, trust me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;It's not easy, but it's doable. Treat it as a marathon, not a sprint. If you think about the whole thing as a means to become better software engineer, with a possible side effect of landing your dream job it will become easier and pay dividends in your career regardless of the outcome.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://www.educative.io/courses/grokking-the-coding-interview" rel="noopener noreferrer"&gt;Grokking the Coding Interview: Patterns for Coding Questions&lt;/a&gt; - great place to start&lt;br&gt;
&lt;a href="https://leetcode.com/problemset/algorithms/" rel="noopener noreferrer"&gt;LeetCode&lt;/a&gt; - hands down best practice platform&lt;br&gt;
&lt;a href="https://www.youtube.com/channel/UCZCFT11CWBi3MHNlGf019nw" rel="noopener noreferrer"&gt;Abdul Bari's youtube channel&lt;/a&gt; - some more advanced topics for curious ones&lt;br&gt;
&lt;a href="https://www.algoexpert.io/product" rel="noopener noreferrer"&gt;AlgoExpert&lt;/a&gt; - easy to follow, worth the money&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was originally published on my blog &lt;a href="https://www.stuffs.dev/posts/how-i-got-to-google/" rel="noopener noreferrer"&gt;stuffs.dev&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>career</category>
    </item>
  </channel>
</rss>
