<?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: Rosebella Wandere</title>
    <description>The latest articles on DEV Community by Rosebella Wandere (@bwandere).</description>
    <link>https://dev.to/bwandere</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%2F4032039%2F9831f7ba-10db-4e22-9260-009062aa9933.png</url>
      <title>DEV Community: Rosebella Wandere</title>
      <link>https://dev.to/bwandere</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bwandere"/>
    <language>en</language>
    <item>
      <title>Building a Data Analyst Agent with Google ADK.</title>
      <dc:creator>Rosebella Wandere</dc:creator>
      <pubDate>Mon, 21 Sep 2026 08:50:39 +0000</pubDate>
      <link>https://dev.to/bwandere/building-a-data-analyst-agent-with-google-adk-5349</link>
      <guid>https://dev.to/bwandere/building-a-data-analyst-agent-with-google-adk-5349</guid>
      <description>&lt;h2&gt;
  
  
  Lessons in Agentic Workflows
&lt;/h2&gt;

&lt;p&gt;At the recent Build with Google AI event in Kisumu, the core focus centered around a fundamental shift: moving from single-prompt chat completion to &lt;strong&gt;Agentic Workflows&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of asking one LLM to solve a complex problem in a single turn, agentic patterns split tasks across specialized, autonomous units coordinated by an orchestrator.&lt;/p&gt;

&lt;p&gt;To explore this hands-on, I built a Data Analyst Agent using the &lt;strong&gt;Google Agent Development Kit (ADK)&lt;/strong&gt;. Here's a quick look at the build, the bugs I bumped into, and the concepts behind them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Google ADK?
&lt;/h2&gt;

&lt;p&gt;Google's Agent Development Kit (ADK) is an open-source, code-first Python framework for building and testing AI agents. It gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agents&lt;/strong&gt;: Individual units with specific roles and instructions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools&lt;/strong&gt;: Custom functions (SQL execution, Python scripts, APIs) that agents invoke autonomously.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orchestration&lt;/strong&gt;: Dynamic routing loops to chain multiple agents together.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Development UI &amp;amp; Tracing&lt;/strong&gt;: A local server (&lt;code&gt;adk web&lt;/code&gt;) to monitor API calls, inspect payloads, and debug agent reasoning in real time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Crucial Concept: Model Context Protocol (MCP)
&lt;/h2&gt;

&lt;p&gt;A key concept when building agentic systems is the &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt;. MCP serves as a standardized bridge between AI models and external data sources or execution environments.&lt;/p&gt;

&lt;p&gt;Rather than hardcoding custom integrations for every database or API, MCP gives agents a uniform interface to securely read context, access files, and call tools across different systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Build &amp;amp; How I Fixed the Roadblocks
&lt;/h2&gt;

&lt;p&gt;I instantiated the agent in &lt;code&gt;agent.py&lt;/code&gt; using standard ADK imports:&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&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt;

&lt;span class="n"&gt;data_agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&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;data_analyst&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.5-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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are an expert Data Analyst AI...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During local testing in the ADK web UI, I hit two quick configuration bumps:&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%2F4sjt6q39njim0xp90r4w.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%2F4sjt6q39njim0xp90r4w.png" alt="Google ADK UI showing a 404 NOT_FOUND error" width="800" height="697"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Requesting a Non-Existent Model (&lt;code&gt;404 NOT_FOUND&lt;/code&gt;)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Issue&lt;/strong&gt;: The agent attempted to contact a model string that didn't map to a valid Vertex AI endpoint (&lt;code&gt;gemini-1.5-flash&lt;/code&gt;), causing the platform to reject the request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Fix&lt;/strong&gt;: I updated the model configuration to a valid target identifier: &lt;code&gt;gemini-2.5-flash&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. A Malformed Resource String (&lt;code&gt;400 INVALID_ARGUMENT&lt;/code&gt;)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Issue&lt;/strong&gt;: A formatting slip left a space in the string (&lt;code&gt;"gemini-2.5 flash"&lt;/code&gt; instead of a hyphen), breaking the API URL parser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Fix&lt;/strong&gt;: I removed the stray space across &lt;code&gt;.env&lt;/code&gt; and &lt;code&gt;agent.py&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Finalizing the Credentials
&lt;/h2&gt;

&lt;p&gt;After fixing the config files, I refreshed my local session using &lt;code&gt;gcloud auth application-default login&lt;/code&gt;. Re-running &lt;code&gt;adk web&lt;/code&gt; gave a clean &lt;code&gt;200 OK&lt;/code&gt; status, allowing the agent to successfully process data requests and generate summaries.&lt;br&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%2F70vxn0dtqzhy1qw2ea7r.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%2F70vxn0dtqzhy1qw2ea7r.png" alt="Successful 200 OK HTTP response with gemini-2.5-flash active" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Watch Configuration Syntax&lt;/strong&gt;: Model names must exactly match active provider endpoints; minor typos break API routing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standardize Tools with MCP&lt;/strong&gt;: Leveraging protocols like MCP makes connecting agents to external databases and environments seamless.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Local Tracing&lt;/strong&gt;: Running local inspection interfaces (&lt;code&gt;adk web&lt;/code&gt;) drastically speeds up finding API-level bugs.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>data</category>
      <category>python</category>
    </item>
    <item>
      <title>Why Algorithms Matter</title>
      <dc:creator>Rosebella Wandere</dc:creator>
      <pubDate>Mon, 07 Sep 2026 14:01:17 +0000</pubDate>
      <link>https://dev.to/bwandere/why-algorithms-matter-1oco</link>
      <guid>https://dev.to/bwandere/why-algorithms-matter-1oco</guid>
      <description>&lt;h2&gt;
  
  
  Why Algorithms Matter: What a Sorting Project Taught Me About Programming
&lt;/h2&gt;

&lt;p&gt;When I started learning programming, I thought most problems could be solved by just writing enough code. Eventually I realized something important: the hardest part isn't always writing the code , it's deciding what the code should do. That's where algorithms come in.&lt;/p&gt;

&lt;p&gt;While working on a sorting project recently (a Push-Swap implementation, where you sort numbers using two stacks and a limited set of operations), I had to think hard about different ways to sort data, how those approaches scale, and how to work within strict constraints. What caught my attention was the algorithmic thinking behind it, and that's what I want to share.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Exactly Is an Algorithm?
&lt;/h2&gt;

&lt;p&gt;An algorithm is a step-by-step procedure for solving a problem. Say you have &lt;code&gt;5 2 8 1 3&lt;/code&gt; and you need &lt;code&gt;1 2 3 5 8&lt;/code&gt;. Getting there is straightforward in principle, but there are many ways to do it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repeatedly find the smallest value and place it.&lt;/li&gt;
&lt;li&gt;Compare neighboring values and swap them.&lt;/li&gt;
&lt;li&gt;Divide the problem into smaller pieces and merge the results.&lt;/li&gt;
&lt;li&gt;Process the digits or bits of each number instead of comparing whole values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these produce the same result. What makes algorithms interesting is &lt;em&gt;how&lt;/em&gt; they get there  and that difference has real consequences for performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Same Problem, Very Different Solutions
&lt;/h2&gt;

&lt;p&gt;A simple sorting approach is &lt;strong&gt;Bubble Sort&lt;/strong&gt;: repeatedly compare neighboring elements and swap them if they're in the wrong order.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;5 2 8 1&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;5 2 8 1  → compare 5,2 → 2 5 8 1
2 5 8 1  → compare 5,8 → 2 5 8 1
2 5 8 1  → compare 8,1 → 2 5 1 8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep repeating until nothing needs swapping. It works, but its worst-case time complexity is &lt;code&gt;O(n²)&lt;/code&gt;, which gets expensive fast as &lt;code&gt;n&lt;/code&gt; grows. This raises a real developer question: if two algorithms solve the same problem, which one should you choose?&lt;/p&gt;

&lt;h2&gt;
  
  
  Complexity Changes Everything
&lt;/h2&gt;

&lt;p&gt;Say Algorithm A runs in &lt;code&gt;O(n²)&lt;/code&gt; and Algorithm B runs in &lt;code&gt;O(n log n)&lt;/code&gt;. For small inputs, the difference barely matters. At &lt;code&gt;n = 1,000&lt;/code&gt;, though:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;n²        = 1,000,000
n log₂n  ≈    10,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a huge gap in work done. This is why understanding time complexity matters. Correct code can still be a poor solution if it doesn't scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Big O Isn't About Exact Seconds
&lt;/h2&gt;

&lt;p&gt;One common misunderstanding is that Big O tells you exactly how many seconds an algorithm takes. It doesn't, instead it describes how the &lt;em&gt;amount of work&lt;/em&gt; grows relative to input size.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O(1) — constant time.&lt;/strong&gt; Work doesn't grow with input size.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;O(n) — linear time.&lt;/strong&gt; Double the input, roughly double the work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// process number&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;O(n²) — quadratic time.&lt;/strong&gt; Double the input, and the work can roughly quadruple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// work&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;O(log n) — logarithmic time.&lt;/strong&gt; Binary search is the classic example: instead of checking every element, you eliminate half the remaining search space each step (1,000,000 → 500,000 → 250,000 → ... → 1). The core idea: don't just make progress, eliminate unnecessary work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Selection Sort: Simple but Expensive
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Selection Sort&lt;/strong&gt; repeatedly finds the smallest remaining element and moves it into place. For &lt;code&gt;4 2 7 1 5&lt;/code&gt;, you find &lt;code&gt;1&lt;/code&gt;, move it to the front, then find the next smallest, and so on.&lt;/p&gt;

&lt;p&gt;It's easy to understand and implement, but it performs roughly &lt;code&gt;n²/2&lt;/code&gt; comparisons, still &lt;code&gt;O(n²)&lt;/code&gt;. For small collections that's often fine. For large ones, it's a sign to look for something better. Lesson: the simplest algorithm isn't always the best one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Divide and Conquer
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Merge Sort&lt;/strong&gt; is a classic divide-and-conquer algorithm: split the data into smaller pieces, sort those, then merge them back in order.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[8 3 5 1 4 2]
   /       \
[8 3 5]   [1 4 2]
 /   \      /   \
...  ...  ...  ...
   \       /
    merge
      |
[1 2 3 4 5 8]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Merge Sort runs in &lt;code&gt;O(n log n)&lt;/code&gt; in both the average and worst cases.This is a meaningful improvement over quadratic sorts like bubble sort and selection sort for large datasets, though it typically needs extra memory for merging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Radix Sort and Binary Representation
&lt;/h2&gt;

&lt;p&gt;One of the more interesting algorithms I ran into is &lt;strong&gt;Radix Sort&lt;/strong&gt;. Unlike Bubble or Merge Sort, it doesn't compare elements directly, it sorts based on their representation, digit by digit or bit by bit.&lt;/p&gt;

&lt;p&gt;For binary Radix Sort, take &lt;code&gt;2, 3, 4, 5&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2 → 010
3 → 011
4 → 100
5 → 101
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Process one bit position at a time, starting from the least significant bit. Partition the numbers by whether that bit is &lt;code&gt;0&lt;/code&gt; or &lt;code&gt;1&lt;/code&gt;, then move to the next bit, and the next. After processing all bit positions, the numbers end up sorted.&lt;/p&gt;

&lt;p&gt;The key idea: instead of comparing whole numbers, you can process a small part of their representation at each stage. This works because integers have structure you can exploit, you don't always need direct comparisons to organize data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On complexity:&lt;/strong&gt; for &lt;code&gt;n&lt;/code&gt; numbers with &lt;code&gt;k&lt;/code&gt; bits (or digits) each, binary/digit Radix Sort does roughly &lt;code&gt;O(nk)&lt;/code&gt; work. &lt;code&gt;k&lt;/code&gt; here is the number of bits (or digits) needed to represent the largest value for fixed-size integers (like 32-bit ints), &lt;code&gt;k&lt;/code&gt; is a constant, so the sort behaves close to linear in &lt;code&gt;n&lt;/code&gt;. But &lt;code&gt;k&lt;/code&gt; isn't free: for arbitrarily large or variable-length keys, it matters, and Radix Sort also needs extra space for the buckets/counting step. It's not "always better" it's a good fit for specific kinds of data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Algorithms Have Trade-Offs
&lt;/h2&gt;

&lt;p&gt;Time complexity isn't the only thing that matters. You should also weigh memory usage, implementation complexity, stability, and how well an algorithm fits your actual data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Algorithm       Average Complexity
----------------------------------
Bubble Sort     O(n²)
Selection Sort  O(n²)
Merge Sort      O(n log n)
Quick Sort      O(n log n)*
Radix Sort      O(nk)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quick Sort's worst case is &lt;code&gt;O(n²)&lt;/code&gt;, depending on pivot choice and implementation.&lt;/p&gt;

&lt;p&gt;There's no algorithm that wins in every situation, the "best" one depends on context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Constraints Can Change the Best Algorithm
&lt;/h2&gt;

&lt;p&gt;If you can use any operation you want, sorting is straightforward. Now imagine you're given two stacks, a limited set of operations, no direct indexing, and a goal of minimizing the number of moves that's roughly the Push-Swap problem. Suddenly the "best" algorithm isn't the one with the best theoretical complexity; it's the one that respects the constraints you actually have.&lt;/p&gt;

&lt;p&gt;This happens constantly in real software:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limited memory → pick a memory-efficient algorithm.&lt;/li&gt;
&lt;li&gt;Huge dataset → pick something that scales well.&lt;/li&gt;
&lt;li&gt;Low latency requirement → optimize the critical path.&lt;/li&gt;
&lt;li&gt;Limited bandwidth → reduce the data you transfer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Constraints aren't just restrictions, they help determine the solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Greedy Thinking
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;greedy algorithm&lt;/strong&gt; makes the best-looking choice at each step, without looking ahead. This doesn't always produce a globally optimal result, but for the right class of problems, it does. Recognizing when greedy thinking is appropriate is a skill on its own, and it shows up well beyond sorting in scheduling, resource allocation, shortest-path problems, and compression. At its core, it's a decision-making pattern: look at the current state, pick the best local option, move to the next state, repeat.&lt;/p&gt;

&lt;h2&gt;
  
  
  Algorithmic Thinking Over Memorization
&lt;/h2&gt;

&lt;p&gt;You don't need to memorize every sorting algorithm. What matters more is asking the right questions when you face a problem:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What's the input?&lt;/strong&gt; Numbers, strings, graphs, objects, files?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What's the output?&lt;/strong&gt; What exactly counts as "correct"?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What constraints exist?&lt;/strong&gt; Memory, time, allowed operations, input size?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What patterns exist in the data?&lt;/strong&gt; Sorted already? Bounded values? Repeats?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How does the solution scale?&lt;/strong&gt; What happens at 10 items vs. 1,000,000?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can you reduce unnecessary work?&lt;/strong&gt; Often the most important question of all.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why This Matters Beyond Sorting
&lt;/h2&gt;

&lt;p&gt;You might think: "I build web apps, why do I need sorting algorithms?" The thinking behind them applies everywhere.&lt;/p&gt;

&lt;p&gt;If your API searches records, you can scan everything, or use an appropriate data structure and search strategy. If your app recalculates the same expensive result repeatedly, you can compute it every time, or cache it. If you're processing millions of records, you can reach for a quadratic approach, or look for something closer to &lt;code&gt;O(n log n)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The language, framework, or database might change. The core question remains: how do you solve this efficiently, given your constraints?&lt;/p&gt;

&lt;h2&gt;
  
  
  Algorithms Make You Think Before You Code
&lt;/h2&gt;

&lt;p&gt;Without algorithmic thinking, development can turn into: hit a problem, start coding, something breaks, add more code, add another condition, add another loop, hope it works.&lt;/p&gt;

&lt;p&gt;Algorithmic thinking pushes a different process instead: understand the constraints, model the problem, choose a strategy, analyze the complexity, implement, test, optimize if needed. It's a stronger habit, and it pays off even outside classic algorithm problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  You Don't Need the "Best" Algorithm
&lt;/h2&gt;

&lt;p&gt;It's also easy to over-optimize. Not every problem needs the most sophisticated solution. If you have ten elements, an &lt;code&gt;O(n²)&lt;/code&gt; approach might be completely fine. If you have ten million, it's worth thinking harder.&lt;/p&gt;

&lt;p&gt;The useful question isn't "what's the fastest algorithm?" it's "what's the appropriate algorithm for this problem?" That's a much more practical engineering mindset.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Working through a sorting problem reminded me that algorithms aren't just academic exercises, they're a way of thinking. They teach you to break problems down, recognize patterns, understand constraints, measure complexity, and weigh trade-offs.&lt;/p&gt;

&lt;p&gt;Knowing how to write code lets you make a program work. Understanding algorithms lets you ask a better question: will this still work well when the problem gets much bigger? That's the difference between writing code and engineering a solution.&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>computerscience</category>
      <category>learning</category>
      <category>programming</category>
    </item>
    <item>
      <title>What Happens Behind the Code?</title>
      <dc:creator>Rosebella Wandere</dc:creator>
      <pubDate>Mon, 10 Aug 2026 06:28:43 +0000</pubDate>
      <link>https://dev.to/bwandere/what-happens-behind-the-code-d27</link>
      <guid>https://dev.to/bwandere/what-happens-behind-the-code-d27</guid>
      <description>&lt;h2&gt;
  
  
  Compilers vs. Interpreters: What Really Happens Behind the Code?
&lt;/h2&gt;

&lt;p&gt;As developers, we spend a lot of time writing code, but how often do we stop to think about what actually happens after we write it?&lt;/p&gt;

&lt;p&gt;Understanding how computers work behind the scenes is not just theoretical knowledge. It can help us understand why programs behave the way they do, where errors come from, and how to approach debugging more effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compiler vs. Interpreter
&lt;/h2&gt;

&lt;p&gt;At a high level, both compilers and interpreters help a computer understand and execute the code we write, but they do it differently.&lt;/p&gt;

&lt;p&gt;A compiler translates the entire program into machine code before the program is executed.&lt;/p&gt;

&lt;p&gt;An interpreter, on the other hand, translates and executes the program as it runs, rather than producing the complete machine-code program beforehand.&lt;/p&gt;

&lt;h2&gt;
  
  
  A simple way to understand it
&lt;/h2&gt;

&lt;p&gt;Imagine you have a book written in French, but you only understand English.&lt;/p&gt;

&lt;p&gt;With a compiler, you would translate the entire book first. Once the translation is finished, you can sit down and read the English version without having to stop and translate every sentence.&lt;/p&gt;

&lt;p&gt;With an interpreter, you would translate the book sentence by sentence while reading it. You translate one sentence, read it, then move on to the next sentence.&lt;/p&gt;

&lt;p&gt;The first approach requires more preparation upfront, but once the translation is complete, reading can be much faster.&lt;/p&gt;

&lt;p&gt;This is a simple analogy for why compiled programs can generally have better execution performance as much of the translation work has already been done before the program runs.&lt;/p&gt;

&lt;p&gt;Understanding this distinction has become particularly interesting to me as a go lang beginner. &lt;br&gt;
Go is a compiled language. When I write Go code, the Go compiler translates the source code into machine code that the computer can execute.&lt;br&gt;
For example:&lt;br&gt;
&lt;code&gt;go build main.go&lt;/code&gt;&lt;br&gt;
This compiles the Go program and produces an executable file.&lt;br&gt;
I can then run that compiled program without having to translate the source code every time it executes.&lt;br&gt;
Compared with an interpreted language, this gives compiled languages some important advantages:&lt;/p&gt;

&lt;p&gt;Faster execution: The translation into machine code happens before execution.&lt;br&gt;
Early error detection: The compiler can catch many errors before the program runs.&lt;br&gt;
Efficient execution: The computer executes compiled machine code directly rather than repeatedly interpreting the source code.&lt;br&gt;
Standalone executables: Go can compile programs into executable binaries that can be distributed and run on compatible systems.&lt;/p&gt;

&lt;p&gt;Interpreted languages also have their own advantages, particularly when it comes to flexibility and rapid development. However, because interpretation happens during execution, there can be additional runtime overhead compared with already-compiled code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does This Matter to Developers?
&lt;/h2&gt;

&lt;p&gt;Understanding concepts such as compilation, interpretation, memory, processes, and execution gives developers a better mental model of what happens between writing code and seeing the result.&lt;/p&gt;

&lt;p&gt;This can make debugging easier because instead of treating errors as random problems, we can start reasoning about where and why something went wrong.&lt;/p&gt;

&lt;p&gt;Learning to code is not just about learning syntax or memorizing functions.&lt;br&gt;
I am beginning to realize that becoming a better developer also means understanding what happens underneath the code we write.&lt;br&gt;
As I continue learning Go, concepts like compilers and interpreters are helping me connect the code I write with what the computer is actually doing behind the scenes.&lt;br&gt;
And I think that understanding is just as important as knowing how to write the code itself.&lt;/p&gt;

</description>
      <category>coding</category>
      <category>computerscience</category>
      <category>programming</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Git is Much bigger than I ever Imagined</title>
      <dc:creator>Rosebella Wandere</dc:creator>
      <pubDate>Wed, 29 Jul 2026 08:40:07 +0000</pubDate>
      <link>https://dev.to/bwandere/git-is-much-bigger-than-i-ever-imagined-2i7m</link>
      <guid>https://dev.to/bwandere/git-is-much-bigger-than-i-ever-imagined-2i7m</guid>
      <description>&lt;p&gt;Over the past few days, I've been diving deep into Git, and one thing surprised me the most:&lt;/p&gt;

&lt;p&gt;Git is much bigger than I thought.&lt;/p&gt;

&lt;p&gt;Like many beginners, I used to think Git was mainly about commands like:&lt;br&gt;
&lt;code&gt;git clone&lt;/code&gt;&lt;br&gt;
&lt;code&gt;git pull&lt;/code&gt;&lt;br&gt;
&lt;code&gt;git push&lt;/code&gt;&lt;br&gt;
&lt;code&gt;git branch&lt;/code&gt;&lt;br&gt;
&lt;code&gt;git merge&lt;/code&gt;&lt;br&gt;
&lt;code&gt;git status&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;They're important, but they're only scratching the surface.&lt;br&gt;
Working through a comprehensive Git project pushed me beyond the everyday commands. I learned about branching strategies, merge conflicts, rebasing, tags, remotes, bare repositories, reflog and even explored what actually lives inside the .git directory.&lt;/p&gt;

&lt;p&gt;One of the biggest eye-openers was exploring the .git folder. Before this project, it was just a hidden directory I never paid attention to. Now I understand it's the heart of every Git repository. It stores commits, trees, blobs, references, configuration, and everything Git needs to track a project's history.&lt;/p&gt;

&lt;p&gt;Another fascinating discovery was &lt;code&gt;Git Reflog&lt;/code&gt;. I had no idea Git keeps a record of where your branches and HEAD have been, making it possible to recover work that seems "lost." That completely changed how I think about mistakes in Git.&lt;/p&gt;

&lt;p&gt;One of my biggest takeaways was realizing how Git enable teams to collaborate efficiently. Understanding merges, rebases, conflict resolution, branch tracking, remotes and shared repositories has given me much greater confidence in contributing to collaborative software projects.&lt;/p&gt;

&lt;p&gt;This journey reminded me that learning Git isn't about memorizing a handful of commands. It's about understanding how Git works under the hood and knowing which tool to use for different situations.&lt;/p&gt;

&lt;p&gt;I'm still learning, but I can already see how this knowledge will make me a better developer and teammate.&lt;/p&gt;

&lt;p&gt;What's one Git feature you discovered much later than you wish you had?&lt;/p&gt;

</description>
      <category>git</category>
      <category>opensource</category>
      <category>learning</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
