<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Steve Brownlee - Steve Brownlee]]></title><description><![CDATA[I'm altering the Internet, pray I don't alter it any further]]></description><link>https://www.stevebrownlee.com/</link><image><url>http://www.stevebrownlee.com/favicon.png</url><title>Steve Brownlee - Steve Brownlee</title><link>https://www.stevebrownlee.com/</link></image><generator>Ghost 1.20</generator><lastBuildDate>Sun, 05 Apr 2026 06:16:45 GMT</lastBuildDate><atom:link href="https://www.stevebrownlee.com/author/steve/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[The Goal Was To Cut AI Agent Behavioral Overhead by 90%]]></title><description><![CDATA[Three compression strategies for the instructions that tell your AI assistant how to think.]]></description><link>https://www.stevebrownlee.com/cut-ai-agent-overhead-by-90-percent/</link><guid isPermaLink="false">69a3451cceadb00ae6ef0065</guid><dc:creator><![CDATA[Steve Brownlee]]></dc:creator><pubDate>Sat, 28 Feb 2026 20:06:33 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p><em>Three compression strategies for the instructions that tell your AI assistant how to think.</em></p>
<hr>
<p>You've spent time wiring up an AI coding assistant. You've configured it with behavioral rules: initialize from a memory database, check governance decisions before touching the codebase, log what you did before calling it done. Your instructions are thorough. They're precise. They handle edge cases.</p>
<p>They're also enormous—and they're running up a tab every time your assistant opens its eyes.</p>
<p>This is the hidden cost that most teams building with AI agents eventually stumble into: <strong>the instructions for how the agent should behave are themselves consuming the space the agent needs to actually do the work.</strong> It's a bit like hiring an expert and giving them such a detailed employee handbook that they spend the whole morning reading it before they can help a single customer.</p>
<p>This post is about three strategies I developed while working on <a href="https://engram.sh">Engrams</a> that collectively cut behavioral instruction overhead by roughly 80–90%, without reducing how well agents follow those instructions.</p>
<hr>
<h2 id="aquickwordonhowthisallworks">A Quick Word on How This All Works</h2>
<p>Before we dive in, a one-paragraph primer for anyone new to this space.</p>
<p>Tools like Engrams work through something called the <strong>Model Context Protocol (MCP)</strong> — a standard that lets AI assistants (like the ones built into Cursor, Windsurf, Roo Code, or Claude) call external tools the same way a web browser calls APIs. When you open a project, your AI assistant gets loaded up with a set of instructions: <em>&quot;here's who you are, here's how you behave, here are the tools you can call.&quot;</em> That instruction block is called the <strong>context window</strong>, and it has a size limit — typically around 200,000 tokens (roughly 150,000 words). Every token of instructions you add is one fewer token available for actual code, files, or conversation.</p>
<p>The instructions we're talking about compressing are the behavioral rules that tell the agent <em>how</em> to use the memory tools: when to load context, when to run governance checks, when to log decisions. These rules, in their original form, are long. Very long.</p>
<hr>
<h2 id="theprobleminnumbers">The Problem, in Numbers</h2>
<p>The Engrams system ships with a strategy file — a set of behavioral instructions — that agents load at the start of every session. It's structured in YAML (a format popular for configuration files), and it's thorough.</p>
<p>Maybe too thorough.</p>
<p>Each version of the file runs 375–415 lines. And because Engrams supports seven different AI tools (Cursor, Windsurf, Roo Code, Claude Code, Cline, and more), there are seven copies of this file — one customized for each tool's quirks.</p>
<p>These seven files are roughly 90% identical. The differences between them amount to a few lines of tool-specific wording. The other 90% is the same behavioral logic, repeated seven times.</p>
<p>In token terms: each file consumes about <strong>10–12K tokens</strong>. On a 200K context window, that's 5–6% of your available space consumed before the user types a single word. Then add the tool schema definitions (also injected at startup), and the results from the initialization tool calls, and you're looking at <strong>25–30K tokens</strong> burned on overhead before any productive work begins.</p>
<p>Think of it like renting a storage unit and using the first 15% just to store the shelving units.</p>
<h2 id="strategy1teachondemandnotallatonce">Strategy 1: Teach on Demand, Not All at Once</h2>
<p><strong>The concept:</strong> Replace the 400-line instruction file with a short table of contents. Only load the full details for a section <em>when the agent actually needs it</em>.</p>
<p>This is the &quot;just-in-time&quot; approach — a concept borrowed from manufacturing, where you don't stock warehouse shelves with inventory until a customer actually orders something.</p>
<p>In practice, the 400-line strategy file gets replaced with a <strong>30-line bootstrap stub</strong> that looks something like this:</p>
<pre><code>ENGRAMS STRATEGY — Section Directory
  INIT: Check for engrams/context.db. If found → load contexts. If not → offer setup.
  GOVERNANCE: Before mutating workspace → call get_relevant_context(task_description, budget=2000).
  POST_TASK: Before completion → run checks, log outcomes.
    Detail: get_custom_data(&quot;engrams_strategy&quot;, &quot;post_task&quot;)
  SYNC: On &quot;Sync Engrams&quot; → pause, review chat, log all changes.
    Detail: get_custom_data(&quot;engrams_strategy&quot;, &quot;sync&quot;)
  LINKING: Proactively suggest links between discussed Engrams items.
    Detail: get_custom_data(&quot;engrams_strategy&quot;, &quot;linking&quot;)
</code></pre>
<p>Notice the <code>Detail:</code> pointers. For simple behaviors (like the initialization check), a one-line summary is enough — the agent doesn't need a five-page explanation to check whether a file exists. For complex, multi-step workflows (like the post-task completion gate), the agent can fetch the full instructions from the server <em>only when that workflow is actually triggered</em>.</p>
<p>The full strategy sections are stored as built-in defaults inside the MCP server itself, not even in the database. They're shipped with the code and returned on demand — no database round-trip needed for the initial fetch.</p>
<p><strong>What this saves:</strong></p>
<ul>
<li>System prompt drops from ~10,000 tokens to ~800 tokens (the bootstrap + directory)</li>
<li>Per-session, only the sections that actually trigger get loaded: roughly 1,000–3,000 tokens total</li>
<li><strong>Effective reduction: 80–90% in a typical session</strong></li>
</ul>
<p>The trade-off is one extra tool call when a new strategy section is first needed. But you're already making 7–8 initialization calls per session; a few more for on-demand strategy sections barely registers.</p>
<h2 id="strategy2saywhatyoumeannoteverythingyouknow">Strategy 2: Say What You Mean, Not Everything You Know</h2>
<p><strong>The concept:</strong> LLMs understand terse instructions just as well as verbose ones. Cut the scaffolding, not the substance.</p>
<p>Here's a real example. The original YAML for one section — the first-time project setup questionnaire — runs <strong>50 lines</strong>:</p>
<pre><code class="language-yaml">post_task_setup_questionnaire:
  description: |
    Runs during first-time Engrams setup to configure project-specific verification checks
    that will be automatically executed as part of the post_task_completion gate.
    The agent auto-detects the project type and suggests relevant checks.
  trigger: &quot;During handle_new_engrams_setup, after projectBrief import...&quot;
  steps:
    - step: 1
      action: &quot;Auto-detect project type by scanning workspace root for manifest files.&quot;
      detection_rules:
        - indicator: &quot;package.json&quot;
          suggests: [&quot;npm test&quot;, &quot;npm run lint&quot;, &quot;npm run build&quot;, &quot;npx tsc --noEmit&quot;]
          project_type: &quot;Node.js/TypeScript&quot;
        - indicator: &quot;pyproject.toml OR requirements.txt OR setup.py&quot;
          suggests: [&quot;pytest&quot;, &quot;flake8 .&quot;, &quot;mypy .&quot;, &quot;python -m py_compile&quot;]
          project_type: &quot;Python&quot;
        ... (5 more language blocks)
</code></pre>
<p>Here's the compressed equivalent — <strong>12 lines</strong>:</p>
<pre><code>POST_TASK_SETUP (first-time only, after DB init):
  1. Detect project type from manifest:
     package.json→Node, pyproject.toml/requirements.txt→Python,
     Cargo.toml→Rust, go.mod→Go, pom.xml/build.gradle→Java,
     Gemfile→Ruby, composer.json→PHP
  2. Suggest test/lint/build checks for detected type
  3. Let user toggle/customize checks, set severity (blocking|warning)
  4. Store → log_custom_data(category=&quot;post_task_checks&quot;, key=&quot;verification_commands&quot;)
  5. Record → log_decision with tags [post-task-checks, project-setup, dx]
</code></pre>
<p>The information content is identical. The model gets the same instruction either way. What changed is the packaging.</p>
<p>A few specific patterns that bloat AI instruction files:</p>
<p><strong>Empty <code>thinking_preamble</code> blocks.</strong> The original file had <em>eight</em> of these — YAML keys with a pipe character (<code>|</code>) and no content beneath them. They were placeholders, never filled in. Each one still consumes tokens. Removing them cost nothing and saved hundreds of tokens.</p>
<p><strong>YAML structure applied to non-hierarchical data.</strong> Detection rules for project types are a flat lookup table. Representing them as nested YAML objects with <code>indicator</code>, <code>suggests</code>, and <code>project_type</code> keys for each entry uses roughly 4× the tokens of a simple colon-separated mapping on a single line.</p>
<p><strong>Step-by-step descriptions of things the model already knows.</strong> &quot;Auto-detect project type by scanning workspace root for manifest files&quot; is a complete sentence that means exactly what &quot;Detect project type from manifest&quot; means. The longer version doesn't add information — it adds tokens.</p>
<p>The analogy here is the difference between a recipe that says <em>&quot;In a large mixing bowl, which should be clean and dry, add the flour&quot;</em> and one that just says <em>&quot;Add flour.&quot;</em> A trained chef doesn't need the bowl specification. Neither does a trained model.</p>
<h2 id="strategy3stopmaintainingsevencopiesofthesamething">Strategy 3: Stop Maintaining Seven Copies of the Same Thing</h2>
<p><strong>The concept:</strong> Keep one authoritative source, generate the rest.</p>
<p>The seven strategy files for different AI tools are nearly identical. The differences are cosmetic: the name of the tool in the header comment, the variable name for the workspace path, and one or two tool-specific function names.</p>
<p>Instead of maintaining seven full files, the architecture shifts to:</p>
<ul>
<li><strong>One <code>_core_strategy.yaml</code></strong> containing the shared ~95% of content</li>
<li><strong>Seven thin <code>_delta_*.yaml</code> files</strong> containing only the tool-specific overrides:</li>
</ul>
<pre><code class="language-yaml"># _delta_roo.yaml
header_comment: &quot;# Install: Roo Code loads rules from .roo/rules/&quot;
workspace_id_source: &quot;Available as ${workspaceFolder}...&quot;
tool_specific_references:
  ask_question: &quot;Use `ask_followup_question`&quot;
  execute_cmd: &quot;Use `execute_command`&quot;
</code></pre>
<p>At build time (or install time), the delta gets merged with the core to produce the final strategy file for each tool. The output is the same — users get a single, complete file for their tool — but the <em>maintenance surface</em> shrinks dramatically.</p>
<p>This matters for a less obvious reason: <strong>this architecture makes Strategy 2 (semantic compression) much easier to apply.</strong> When you have seven copies, compressing one means compressing seven — and keeping them in sync as the compression evolves. With a single core file, you apply the compression once and all seven outputs benefit automatically.</p>
<p>It's the same principle behind any shared library or abstraction in software development. Stop repeating yourself so you can stop making the same mistake seven times.</p>
<p><strong>What this saves:</strong> Nothing on per-user token cost — the output file is the same size. But it cuts maintenance cost dramatically and creates a compounding leverage point for the other strategies.</p>
<h2 id="howthestrategiesstack">How the Strategies Stack</h2>
<p>These three strategies aren't independent — they compound.</p>
<p>Start with the deduplicated architecture (Strategy 3): you now have one source of truth for the behavioral instructions. Apply semantic compression (Strategy 2) to that source: the compressed version is shorter and clearer. Then deploy the just-in-time loading approach (Strategy 1): instead of injecting the compressed file at startup, serve it from the server on demand, section by section.</p>
<p>The result is a system where:</p>
<ul>
<li>The cold-start cost (tokens consumed before any user interaction) drops from ~10K to ~800</li>
<li>The total per-session cost depends on which workflows actually trigger, not on the worst-case size of the full instruction set</li>
<li>The maintenance cost of updating behavioral instructions drops to editing one file</li>
</ul>
<p>In concrete terms: a developer opening a project at the start of a workday used to &quot;spend&quot; 10,000 tokens on behavioral instructions before their AI assistant could respond to their first message. After applying all three strategies, that cost is 800 tokens. The agent gets smarter, faster access to relevant instructions <em>and</em> has more context window available for the actual codebase.</p>
<h2 id="thebiggerlesson">The Bigger Lesson</h2>
<p>These strategies are specific to AI agent behavioral instructions, but the underlying principles apply anywhere you're shipping configuration or instructions that need to be compact and maintainable:</p>
<ol>
<li><strong>Don't load everything upfront.</strong> Load what you need, when you need it. This is just lazy evaluation, applied to prompts.</li>
<li><strong>Don't say more than you need to.</strong> Structural formatting and verbose phrasing are free in human-written documentation, but expensive in machine-consumed prompts. Write for the model, not for the formatting linter.</li>
<li><strong>Don't repeat yourself across seven files.</strong> A shared source with thin per-variant deltas is almost always better than N full copies — for prompts, for config, for anything.</li>
</ol>
<p>The irony of a memory tool that consumes too much memory to be useful isn't lost on me. These strategies exist because we hit that irony directly and had to work our way out of it.</p>
<p>If you're building with AI agents at any scale, chances are you'll hit it too.</p>
<hr>
<p><em>Engrams is an open-source MCP server for persistent AI agent memory and team governance. Source and documentation at <a href="https://engram.sh">engram.sh</a>.</em></p>
</div>]]></content:encoded></item><item><title><![CDATA[Prompt-first Frustration to Plan-First Success]]></title><description><![CDATA[<div class="kg-card-markdown"><p>This article is for developers already using LLM coding assistants who want to sharpen their workflow. I won't be explaining what an LLM is or how to set up your first AI coding tool. Instead, I'll walk through the tooling, habits, and hard-won lessons I've picked up over two years</p></div>]]></description><link>https://www.stevebrownlee.com/llm-prompting-to-planning/</link><guid isPermaLink="false">6992aba8ceadb00ae6ef0053</guid><dc:creator><![CDATA[Steve Brownlee]]></dc:creator><pubDate>Mon, 16 Feb 2026 05:32:28 GMT</pubDate><media:content url="https://www.stevebrownlee.com/content/images/2026/02/human-llm-planning-team.jpeg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://www.stevebrownlee.com/content/images/2026/02/human-llm-planning-team.jpeg" alt="Prompt-first Frustration to Plan-First Success"><p>This article is for developers already using LLM coding assistants who want to sharpen their workflow. I won't be explaining what an LLM is or how to set up your first AI coding tool. Instead, I'll walk through the tooling, habits, and hard-won lessons I've picked up over two years of daily LLM-assisted development.</p>
<p>The single biggest shift in that time: I stopped treating LLMs as code generators and started treating them as collaborators that need a plan.</p>
<h2 id="thetoolingstack">The Tooling Stack</h2>
<p>I've been using <a href="https://roocode.com/">Roo Code</a> for the longest time. Its appeal is flexibility — it works with anything, supports multiple modes, and is deeply customizable. Recently, I switched to <a href="https://kilo.ai/">Kilo Code</a>, which adds one critical feature Roo Code lacked: autocomplete. Kilo Code uses the Codestral model running locally via Ollama for this, which means fast completions with zero cloud cost.</p>
<p>On the context side, I use the <a href="https://github.com/GreatScottyMac/context-portal">Context Portal MCP</a> server to persist long-term context across sessions — architectural decisions, patterns, conventions, and to-do items. This acts as a project's living memory that any mode can reference.</p>
<p>I also use custom Roo Flow prompts, which I've tuned to reduce token usage. One recent change worth noting: I had to modify the default Roo Flow prompts to remove XML-based tool usage directions and switch to native tool calling. If you're still on the XML-based prompts, it's worth making that switch.</p>
<h2 id="thearchitectworkflow">The Architect Workflow</h2>
<p>Early on, my process looked like this: write a prompt, get code back, iterate on the code, get frustrated, iterate more. The generated code was often close but structurally wrong in ways that took multiple rounds to fix. I was spending most of my time reacting to output instead of shaping it.</p>
<p>Now, I spend almost all of my time in Flow Architect mode. I generate a plan, iterate on that plan until I'm satisfied with every detail, and only then move to code generation. The result is that code generated in Flow Code mode — or the walkthrough generated in Flow Ask mode — is nearly flawless on the first pass.</p>
<p>This was the single biggest improvement in my entire workflow. Everything else I'll describe builds on top of it.</p>
<p>When a task is fully documented and follows the single responsibility principle, I feed the design document from Architect mode as initial context into a new Flow Code conversation. If there are multiple clearly defined tasks, I switch to Flow Orchestrator mode and let it manage parallel conversations. The key is that no code gets written until the plan is solid.</p>
<h2 id="modelselection">Model Selection</h2>
<p>Not every task needs the most powerful model. Setting the exact default model per mode has been one of the simplest ways to control cost without sacrificing quality.</p>
<p>My current breakdown: Opus for architecture work, where reasoning depth matters most. Sonnet for complex technical tasks that require nuance. Haiku for straightforward, well-known tasks — even high-volume code generation — which, honestly, is the majority of the work. Most coding tasks are not novel; they're well-established patterns that a lighter model handles perfectly.</p>
<h2 id="promptdiscipline">Prompt Discipline</h2>
<p>A few things I've learned about how to talk to these models effectively.</p>
<p>Be specific in your instructions, and tell the LLM what it should not do. This is just as important as telling it what you want. Without negative constraints, models will infer scope and often infer too broadly.</p>
<p>Front-load context. I load as much relevant context as I can think of in the initial prompt — files, architecture docs, prior decisions. The more the model knows upfront, the less it guesses.</p>
<p>Add rules incrementally, per project. I don't rely solely on what I've stored in Conport. Small, targeted rules in the <code>.kilocode/rules</code> directory accumulate over the life of a project and catch the specific behaviors I want to enforce or prevent. For example, every project gets a rule enforcing no emojis and requiring succinct, direct output. Recent models have defaulted to being irritatingly verbose and chatty, and this keeps them in check.</p>
<p>Be explicit about file scope. I tell the model exactly which files to work on. I then watch the output as it's generated. If I see it touching other files with good justification, I let it continue. If it's drifting, I stop the work immediately and re-prompt with more context.</p>
<h2 id="reviewinggeneratedcode">Reviewing Generated Code</h2>
<p>I check every single line of generated code, then evaluate it as a whole. This is non-negotiable, even for simple tasks.</p>
<p>What I consistently find: the code is often more verbose than necessary. It uses odd techniques that it was trained on but that don't fit the project's conventions. It's not always DRY. It can lean on overly simplified patterns that technically work but aren't how I envision the strategy.</p>
<p>That said, reviewing code has also been one of the best ways to learn. The models have shown me techniques and approaches I hadn't considered before. It's a two-way street — you're checking their work, but you're also absorbing new ideas.</p>
<h2 id="debugging">Debugging</h2>
<p>For stack traces, I copy the output and paste it inside triple backticks. For UI issues involving layout, sizing, or placement, I send a screenshot — these models are vision-capable now, and a picture communicates a layout problem far more efficiently than a text description.</p>
<p>The screenshot workflow extends to wireframes. Even a rough hand-drawn wireframe, photographed and sent to the model, gives it enough to work with. This is one of the most underused capabilities I've seen — most people don't think to send visual input to a coding assistant.</p>
<h2 id="testing">Testing</h2>
<p>Test strategy gets decided in Architect mode, alongside everything else. Ninety-five percent of the time, I let the LLM generate the tests. If it's something I'm uncertain about — an unfamiliar testing pattern or an edge case I want to understand deeply — I switch to Flow Ask mode and build the tests out myself, step by step.</p>
<h2 id="learningnewthings">Learning New Things</h2>
<p>When I'm working with a new concept, tool, or language, I never let the model generate code for me. I switch to Flow Ask mode and have it walk me through implementation step by step. I write every line myself. This is slower, but it means I actually understand what I've built, and I can maintain it without the model's help later.</p>
<h2 id="therulesiwishidknownearlier">The Rules I Wish I'd Known Earlier</h2>
<p>It's not Google. Don't treat it as a search engine. It's a reasoning tool that generates output based on patterns, and it needs to be directed, not queried.</p>
<p>Always review the code, even for simple tasks. You will always catch something. But you'll also learn something — those two things happen in roughly equal measure.</p>
<p>If you find yourself writing more than two prompts about the same block of code, stop and write it yourself. The model isn't going to get there, and you're burning tokens and time. Step in, write the code, and move on.</p>
<p>The shift from iterating on code to iterating on plans was the turning point. Once I internalized that the quality of the output is determined by the quality of the plan, everything got faster, cheaper, and more reliable.</p>
<h2 id="buildingagents">Building Agents</h2>
<p>Beyond using LLMs as tools, I've started building with them. As a personal project, I'm using Pydantic AI to build a D&amp;D Dungeon Master agent that runs locally. It's been an education in a completely different set of concerns.</p>
<p>Model selection matters far more when you're running small local models. A model that excels at narrative generation might be terrible at structured output or tool calling. You can't just pick the &quot;best&quot; model — you have to pick the best model for the specific task your agent performs, and that often means testing several.</p>
<p>The parameters you'd normally ignore start to matter. Temperature, max tokens, and retrieval_k all have a direct, noticeable impact on output quality and consistency. Small changes in these values can be the difference between a coherent game session and nonsense.</p>
<p>History processing is deceptively tricky. Conversation history grows fast in a D&amp;D session, and you have to make deliberate choices about when to summarize history versus when to truncate it outright. Summarization preserves context but costs tokens and can lose important details. Cutting history is cheaper but risks the agent forgetting something the player said three turns ago. There's no universal answer — it depends on what your agent needs to remember and what it can afford to forget.</p>
<h2 id="writingsystemprompts">Writing System Prompts</h2>
<p>One skill that's grown significantly over the past two years is writing system prompts — not just for coding, but for any task where I need consistent, specialized behavior from a model.</p>
<p>The best example is outside of software entirely. I'm writing a book, and I've written a system prompt that instructs an LLM to act as my editor. I generate one to three chapters of content, then provide them as context in a custom Book Editor mode with that system prompt. It gives me structured feedback on weak verbs, passive voice, character inconsistencies, overly complex language that makes passages hard to read, world-building inconsistencies, and missed opportunities to build tension or develop characters.</p>
<p>This works because the system prompt is specific about what to look for and how to deliver the feedback. The same principles that make coding prompts effective — be explicit, define scope, state what not to do — apply directly to any domain. Once you've internalized how to write a good system prompt for code, you've learned a transferable skill.</p>
<h2 id="whereiamnow">Where I Am Now</h2>
<p>Three years in, my relationship with LLM tooling has fundamentally changed. I spend the majority of my time thinking and planning, not prompting and fixing. The code generation step, which used to be where all the friction lived, is now the easiest part. The hard work — and the valuable work — happens before a single line of code is written.</p>
<p>The models will keep getting better. The tooling will keep evolving. But the meta-skill — knowing when to architect, when to generate, when to learn manually, and when to just write the code yourself — that's the part that compounds.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Your Child Is Being Trained to Pass Tests, Not to Think — And It's Going to Cost Them]]></title><description><![CDATA[<div class="kg-card-markdown"><p>I've had to console grown men and women who were crying in frustration, and I want to tell you about one of them.</p>
<p>Miguel was twenty-six years old with a college degree and good grades his whole life. He'd just failed his third self-assessment project — couldn't get it to work</p></div>]]></description><link>https://www.stevebrownlee.com/children-learning-to-think/</link><guid isPermaLink="false">697a7370ceadb00ae6ef0042</guid><dc:creator><![CDATA[Steve Brownlee]]></dc:creator><pubDate>Mon, 16 Feb 2026 05:02:34 GMT</pubDate><media:content url="https://www.stevebrownlee.com/content/images/2026/02/father-helping-daughter.jpeg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://www.stevebrownlee.com/content/images/2026/02/father-helping-daughter.jpeg" alt="Your Child Is Being Trained to Pass Tests, Not to Think — And It's Going to Cost Them"><p>I've had to console grown men and women who were crying in frustration, and I want to tell you about one of them.</p>
<p>Miguel was twenty-six years old with a college degree and good grades his whole life. He'd just failed his third self-assessment project — couldn't get it to work per the requirements — and he was breaking down.</p>
<p>&quot;I don't understand,&quot; he said, voice cracking. &quot;I've never failed at anything. Why can't I do this?&quot;</p>
<p>I knew the answer. I've seen it hundreds of times over eleven years running a software development bootcamp. The problem wasn't that Miguel couldn't learn to code. The problem was that he'd never learned to think.</p>
<p>Your child is heading down the same path right now, and I want to tell you about it before it's too late.</p>
<p>Oh, and Miguel? About a year after he graduated, he made a LinkedIn post explaining that he'd finally realized what I had been doing for six months, and all the pieces clicked for him. But I'm getting ahead of myself.</p>
<h2 id="whatiactuallydoandwhatyourchildneeds">What I Actually Do (And What Your Child Needs)</h2>
<p>For eleven years, I led a team of software development coaches in a bootcamp. Whenever I hired instructors, I always told them the same thing:</p>
<p><strong>&quot;Your job is not to teach people how to code. Your job is to coach people through the process of learning how to become an analytical and algorithmic thinker.&quot;</strong></p>
<p>If someone learns to think analytically and algorithmically, coding follows naturally. Without those thinking skills, they fail the moment they hit a problem we didn't explicitly teach them how to solve.</p>
<p>This is what Miguel didn't understand for six months. This is what schools stopped prioritizing twenty-three years ago. And this is what your child needs far more than good grades.</p>
<p>I'm not just an educator — <strong>I'm also a parent of two teenagers.</strong> I've spent their entire childhood deliberately building the thinking skills that school won't teach. It worked, and it can work for you too.</p>
<h2 id="thecrisisiseeeveryday">The Crisis I See Every Day</h2>
<p>My students arrive with impressive credentials. They were the &quot;smart kid.&quot; Teachers loved them. Honor roll, AP classes, never below a B.</p>
<p>Then they encounter something genuinely difficult, and they completely fall apart.</p>
<p>Not because the material is impossibly hard — because their identity shatters. They've spent eighteen years learning that success means &quot;getting it done&quot; and that smart people &quot;get it&quot; immediately. Now they're discovering that what they had wasn't intelligence; it was just an easy curriculum.</p>
<p>The behaviors I see are heartbreakingly predictable. Twenty-four-year-olds begging me to just tell them the answer. Complete shutdowns when frustration sets in. Declarations like &quot;I'm just not a technical person&quot; after a single failed attempt. And plagiarism — which is exactly what they learned to do when the goal was always &quot;right answer by Friday, don't care how.&quot;</p>
<p>Teachers, you see this too. The gifted student who melts down when challenged. The honor student who'd rather cheat than risk being wrong. The kid asking &quot;Will this be on the test?&quot; about everything.</p>
<p>Here's what we actually had to teach people to do: how to break problems into pieces (they couldn't), how to learn efficiently (they didn't know how), how to handle ambiguity without panicking (they'd never done it), and how to learn from mistakes (they saw mistakes as failure). All of this should be automatic by age sixteen, but we were teaching it from the ground up at twenty-five.</p>
<p>And some didn't make it through. Not because they weren't smart — because they couldn't let go of their ego and adopt a growth mindset. Their minds had been shaped by a lifetime of the wrong incentives.</p>
<p>These are your kids in ten years.</p>
<h2 id="howwegotherethetestingera">How We Got Here: The Testing Era</h2>
<p>If your child is in school right now, their education has been shaped by a 2001 law called No Child Left Behind.</p>
<p>In the simplest terms, here's how it worked: schools get money based on test scores, teachers get evaluated on test scores, and principals keep their jobs based on test scores. The result is that everyone optimizes for test scores.</p>
<p>The problem is that test scores and thinking skills are not the same thing — in many ways, they're mutually exclusive. Teaching kids to think takes time, exploration, and mistakes. Tests reward speed, pattern-matching, and one &quot;correct&quot; answer.</p>
<h3 id="theincentivetrap">The Incentive Trap</h3>
<p>Your child's school operates like a hedge fund manager of mediocrity, optimizing for students hovering around &quot;proficient.&quot;</p>
<p>If your kid is already proficient, then mission accomplished — nobody's paying attention to them anymore. If your kid is advanced and bored and needs further development, forget about it. The system has no incentive to provide resources or time for them. And if your kid is below proficiency? That's where every resource goes.</p>
<h3 id="butdidnttheyfixthisin2015">&quot;But Didn't They Fix This in 2015?&quot;</h3>
<p>Sort of. Not really.</p>
<p>The Every Student Succeeds Act replaced NCLB in 2015, giving states more control over how to manage education. But notice what didn't change: the annual testing requirements, the funding tied to performance, and the teaching-to-the-test culture that had been deeply embedded for over a decade.</p>
<p>You can't reverse thirteen years of institutional momentum with a new law. The first NCLB kids were already adults by 2015. They're the ones who ended up in my bootcamp.</p>
<p><strong>The law changed. The culture didn't.</strong></p>
<h3 id="whatgotcut">What Got Cut</h3>
<p>Everything that develops thinking was gradually pushed aside: gifted programs (those students are already proficient, so there's no funding incentive), art, music, and recess (not quantifiable on a standardized test), science experiments (too messy — facts are easier to test), essay writing (multiple choice is faster to grade), class discussions (you can't attach a defensible number to discussion quality), student questions (off-script and wastes test-prep time), and deep exploration of any kind (coverage matters more than understanding).</p>
<p>Your child is being trained to be really good at something that doesn't matter.</p>
<h2 id="whyeverychildisbeingfailed">Why Every Child Is Being Failed</h2>
<h3 id="giftedkidsquietlyneglected">Gifted Kids: Quietly Neglected</h3>
<p>Imagine your child is naturally fast at running — so fast that the gym teacher never makes them practice and just tells them to sit on the bench while slower kids train.</p>
<p>Then there's an actual race. Your kid discovers that being fast and <em>knowing how to race</em> are very different things. They've never learned pacing, strategy, or fatigue management. They lose, they're devastated, and they conclude they're not actually good at running.</p>
<p><strong>That's what's happening academically.</strong> Your gifted child never learns to struggle, never develops persistence, never picks up study strategies. Their entire identity gets built on effortless success. Then they hit college or the working world and fall apart.</p>
<p>This could have been my daughters. I saw it coming and intervened.</p>
<h3 id="strugglingkidstrainednoteducated">Struggling Kids: Trained, Not Educated</h3>
<p>Kids who are behind get intense focus on test-taking strategies — bubbling techniques, keyword recognition, process of elimination. These help with tests, but they are <em>not</em> thinking skills. When these students leave school and face real problems that aren't multiple choice, they're lost.</p>
<h3 id="averagekidshittingbenchmarksnotlearning">Average Kids: Hitting Benchmarks, Not Learning</h3>
<p>The average student gets the most resources and the most test prep. And what they're actually learning is that right answers matter more than understanding why, that speed matters more than depth, and that compliance matters more than curiosity.</p>
<p>They'll probably graduate. They'll probably go to college. And then they'll be in my bootcamp at twenty-five, unable to solve problems nobody handed them a formula for.</p>
<h2 id="thefivemissingskills">The Five Missing Skills</h2>
<h3 id="1metacognitionthedashboard">1. Metacognition: The Dashboard</h3>
<p>This is your child's ability to monitor their own understanding — the internal voice that says, &quot;Wait, I don't actually get this.&quot;</p>
<p>When it's present, a student can say, &quot;I thought I understood, but now I'm not sure.&quot; When it's missing, they can't even identify what they're confused about and are blindsided by bad grades.</p>
<p><strong>Quick check:</strong> Ask your child, &quot;How do you know you're right?&quot; If they can't explain their reasoning, that's a red flag.</p>
<h3 id="2productivestruggleembracingdifficulty">2. Productive Struggle: Embracing Difficulty</h3>
<p>This is the ability to stay engaged with hard problems without panicking or giving up.</p>
<p>When it's present, a child tries multiple approaches and says things like, &quot;This is frustrating, but I can figure it out.&quot; When it's missing, they immediately say &quot;I can't,&quot; shut down emotionally, or demand that you solve it for them.</p>
<p><strong>Quick check:</strong> Give them a slightly-too-hard puzzle and watch what happens. Do they engage or give up?</p>
<p>My daughters still have emotional reactions to difficulty — they're teenagers. But they work through it.</p>
<h3 id="3problemdecompositiononebiteatatime">3. Problem Decomposition: One Bite at a Time</h3>
<p>This is the skill of breaking complex problems into manageable chunks.</p>
<p>Ask someone to &quot;eat an elephant&quot; and they freeze. Ask them to &quot;take one bite&quot; and they can do it. Our schools are handing kids elephants and timing them.</p>
<p>When it's present, a child can say, &quot;First I need to do this, then I can do that.&quot; When it's missing, they say, &quot;This is too much,&quot; and can't even identify where to start.</p>
<p><strong>Quick check:</strong> Give them a multi-step task and see if they can sequence the steps on their own.</p>
<h3 id="4assumptionvalidationdebuggingyourthinking">4. Assumption Validation: Debugging Your Thinking</h3>
<p>This is the habit of testing whether your reasoning is actually correct before moving on.</p>
<p>When it's present, a child says, &quot;Let me check if this works,&quot; and tests edge cases. When it's missing, they assume their first answer is correct and never check their work.</p>
<p><strong>Quick check:</strong> After homework, ask, &quot;How did you verify that your answers are right?&quot;</p>
<h3 id="5growthmindsetintelligenceisdevelopable">5. Growth Mindset: Intelligence Is Developable</h3>
<p>This is the belief that abilities develop through effort rather than being fixed traits you're born with.</p>
<p>When it's present, a child thinks, &quot;I keep getting these problems wrong, so I need to review the material again.&quot; When it's missing, they think, &quot;I'm just not a math person.&quot; That fixed mindset — trying once, not getting it, and concluding you're not good at it — is like going to the gym once and deciding you're &quot;not a fitness person.&quot;</p>
<p><strong>Quick check:</strong> Listen to how your child talks about challenges.</p>
<p><strong>The bottom line:</strong> Without these five skills, your child can memorize facts and pass tests but can't actually <em>think</em>. With them, they can learn anything.</p>
<p>The good news is that all of these can be taught at home, but you have to start early — ideally as soon as your child starts school. If you don't catch these before your child is thirteen, it's going to be a much bumpier ride.</p>
<h2 id="whywaitingmakesitharder">Why Waiting Makes It Harder</h2>
<p>Your child's brain is at its most flexible during childhood and adolescence. The prefrontal cortex — the region responsible for executive function, planning, and problem-solving — develops between roughly ages ten and twenty-five.</p>
<p><strong>This is the window.</strong> Miss it, and you're trying to build these skills after the easy period has closed. Teaching adults the thinking skills they should have started learning at ten is like teaching someone to use a computer when they're seventy. It's possible, but so much harder than it needed to be.</p>
<p>In the bootcamp, I watched this play out constantly. Adults needed about three months just to <em>believe</em> that thinking is a learnable skill. Some plateaued after six months despite intensive coaching. We were trying to build in six months what should have developed over fifteen years.</p>
<p>And then there's the identity problem. By adulthood, a person's identity is built around their academic experience. If you start early, analytical thinking is just how your child learns. If you start late, it becomes identity warfare — they have to unlearn who they believe they are before they can grow.</p>
<h2 id="whatactuallyworksfivestrategiesfortonight">What Actually Works: Five Strategies for Tonight</h2>
<h3 id="strategy1socraticquestioning">Strategy 1: Socratic Questioning</h3>
<p>Instead of giving answers, ask questions that guide your child toward answers.</p>
<p>Here's what it looks like in practice. Your kid says, &quot;I don't get this math problem.&quot; Instead of explaining it, you ask: &quot;What is the problem asking for?&quot; Then, &quot;What information do you have?&quot; Then, &quot;What's your first step?&quot; And finally, &quot;How can you check if that's right?&quot;</p>
<p>Each question moves them one step closer to solving it themselves — and more importantly, teaches them how to approach the <em>next</em> problem you won't be there for.</p>
<h3 id="strategy2processpraiseoveroutcomepraise">Strategy 2: Process Praise Over Outcome Praise</h3>
<p>When your child succeeds, praise the effort, not the trait. Instead of &quot;You're so smart! A+ on your test!&quot; try something like, &quot;You worked hard for three days to understand dividing decimals — look at how that paid off.&quot; Instead of &quot;You're a natural at science,&quot; try, &quot;I'm proud that you didn't give up when you were struggling with organic chemistry.&quot;</p>
<p>I get it — you're proud when your child succeeds, and it took me years of practice to make sure I always praised my daughters for their effort rather than their ability. Telling your child she's smart feels good and may make her feel good momentarily, but over time it builds an identity that crumbles the moment something is actually hard.</p>
<h3 id="strategy3modelthinkingoutloud">Strategy 3: Model Thinking Out Loud</h3>
<p>Thinking is usually invisible. Make it visible by narrating your problem-solving so your child can hear what thinking actually sounds like.</p>
<p>Here's a real example from my house. Our internet kept dropping one evening while both daughters were home. Instead of quietly troubleshooting, I talked through it out loud:</p>
<p>&quot;Okay, internet's out. Let me figure this out. Is it just my device, or is everything down? Let me check my phone. Phone's out too. So it's either the router or the service. Let me restart the router first — that's the easiest thing to test...&quot;</p>
<p>My older daughter chimed in: &quot;Or call them?&quot;</p>
<p>&quot;Good thinking,&quot; I said. &quot;What info would I need before calling?&quot;</p>
<p>&quot;Account number?&quot;</p>
<p>What happened in that moment was that she heard me break down a problem, test hypotheses in a logical order, and involve her in the process. She learned something about how to approach ambiguous problems — and I never sat her down for a &quot;lesson.&quot; I just made thinking visible during normal life.</p>
<h3 id="strategy4normalizestruggleandmistakes">Strategy 4: Normalize Struggle and Mistakes</h3>
<p>Make it clear that difficulty is normal and that mistakes are information, not failure.</p>
<p>When your child is struggling, you might say, &quot;This is hard, isn't it? Hard things are where real learning happens.&quot; Or, &quot;Mistakes are how we debug our thinking.&quot; When they're frustrated, try, &quot;Frustration means you're at your learning edge — that's exactly where you want to be.&quot;</p>
<p>Here's a real example — and one where teenagers really test you. My younger daughter was learning algebra one evening and started crying: &quot;I'm so stupid! I can't do this!&quot;</p>
<p>I didn't say, &quot;Don't say that, you're not stupid!&quot; That doesn't help. I didn't say, &quot;This is easy once you get it.&quot; That makes her feel worse.</p>
<p>What I said was, &quot;Yeah, algebra is genuinely hard. Your brain is doing something new — dealing with unknowns. That's uncomfortable. But uncomfortable is where learning happens. Let's take a break, then break this down together.&quot;</p>
<p>I let her cry for a minute. The emotion was information — she was at her learning edge. That's actually a good thing, even though it doesn't feel like one in the moment.</p>
<h3 id="strategy5letthemfailthehardestone">Strategy 5: Let Them Fail (The Hardest One)</h3>
<p>This is the strategy that separates parents who build thinking skills from parents who just talk about building them.</p>
<p>A few years ago, my daughter had a big project due that was worth thirty percent of her total grade. She left it to the last minute — the night before, if I recall.</p>
<p>&quot;I need help! I can't finish this!&quot; she said.</p>
<p>Every instinct in my body screamed: <em>Rescue her. Stay up all night. Prevent the failure.</em></p>
<p>Instead, I said, &quot;That's tough. What do you think you should do?&quot;</p>
<p>&quot;I don't know! Can you help me?&quot;</p>
<p>&quot;I can answer questions and point you in the right direction, but I can't do it for you. What are your options?&quot;</p>
<p>She was crying and angry. &quot;I don't have options! I'm going to fail!&quot;</p>
<p>She made a plan and executed it poorly because she was exhausted. She failed that project, and I did not rescue her.</p>
<p>Three weeks later, a new project was assigned. She started immediately, planned it out, and finished two days early.</p>
<p>&quot;I noticed you started this one right away,&quot; I said.</p>
<p>&quot;Yeah,&quot; she said. &quot;I didn't want to do that panic thing again. That sucked.&quot;</p>
<p>What she learned from that experience was worth more than any grade: consequences are real, she can survive failure, she can learn from her mistakes, she can plan ahead, and Mom won't rescue her — so she needs to rescue herself. In a word, she learned <strong>agency.</strong></p>
<p>A year later, she manages her time well, plans ahead, and asks for help strategically rather than desperately.</p>
<p>The short-term rescue would have felt better for both of us. The long-term lesson was immeasurably better.</p>
<h2 id="realtransformationswhatchanges">Real Transformations: What Changes</h2>
<p>Here's what my graduates tell me, and the pattern is remarkably consistent:</p>
<p>&quot;I came to learn to code. But what I actually learned was how to think. Now I approach my entire life differently.&quot;</p>
<p>They tell me they feel more in control — of their careers, their decisions, their lives. They tell me they can actually solve problems now, and not just coding problems but life problems. They tell me they don't panic anymore when things get hard because they have strategies. And more than a few have told me they feel like a different person — calmer, more confident, more capable.</p>
<p>One student put it perfectly: &quot;I thought you were teaching me JavaScript. You were actually teaching me how to be an effective learner.&quot;</p>
<h3 id="sarahfrompanictoagency">Sarah: From Panic to Agency</h3>
<p>Sarah was twenty-three with a college degree and plenty of intelligence. Her first genuinely hard coding problem led to a full panic attack. During her first month, she cried twice a week and almost quit. I wouldn't let her.</p>
<p>Six months later, she was talking my ear off about how she no longer made decisions emotionally. She could think through difficult situations and feel confident she was making smart choices.</p>
<p>Her whole life was different from that point on.</p>
<h2 id="fromoneparenttoanotherthehardtruth">From One Parent to Another: The Hard Truth</h2>
<p>I won't pretend this is easy, because it isn't.</p>
<p>It's slower. Letting your child think takes far longer than just telling them the answer. It's frustrating, because you <em>know</em> the answer — you can <em>see</em> what they need to do — and you have to sit there and watch them struggle. They get mad at you. &quot;Just TELL me!&quot; is something I hear weekly, sometimes through tears, sometimes through yelling.</p>
<p>You'll doubt yourself constantly. Am I being too hard? Should I just help? And teenagers are especially challenging — emotional intensity plus cognitive development is a lot to navigate.</p>
<p>Other parents will judge you for it, too. I've gotten comments like, &quot;You let her turn in <em>that</em> project? You could have helped more.&quot; Yes. I could have. I chose not to.</p>
<h3 id="butitworks">But It Works</h3>
<p>Are my daughters perfect? No. Do they still have meltdowns? Yes — they're teenagers. Do they make bad decisions? Absolutely.</p>
<p>But they have tools. And I watch them reach for those tools more and more as they grow.</p>
<p>If it works for me — juggling a demanding job, parenting chaos, and two very different kids — it can work for you. You don't have to be perfect. You just have to be intentional.</p>
<p>Start where you are. Your kids will thank you. Maybe not this year. Maybe not until they're twenty-five.</p>
<p>But they will.</p>
<h2 id="miguelsepiphany">Miguel's Epiphany</h2>
<p>Remember Miguel from the beginning? The one who was frustrated with me for six months straight?</p>
<p>About a year after graduation, I saw his LinkedIn post. His company was training him to mentor junior developers, and he'd taken an introductory coaching class. Here's what he wrote:</p>
<blockquote>
<p><em>Something clicked today. I recently started taking a few courses in professional coaching, and I realize that this is what my instructor was doing for six months.</em></p>
<p><em>He never gave me the answers. He just asked me questions and made me come up with the answers myself. I thought he was being difficult. Or didn't want to help. Or liked watching us struggle.</em></p>
<p><em>Turns out he was coaching me on how to think.</em></p>
</blockquote>
<p>I sat at my desk and smiled.</p>
<h2 id="quickstartfivethingsfortonight">Quick Start: Five Things for Tonight</h2>
<p>If this all feels like a lot, just start here. Tonight, do one of each:</p>
<ol>
<li><strong>Ask one Socratic question</strong> instead of giving one answer.</li>
<li><strong>Praise one process</strong> instead of one outcome.</li>
<li><strong>Think out loud once</strong> so your child can hear what reasoning sounds like.</li>
<li><strong>Normalize one struggle</strong> instead of rushing to fix it.</li>
<li><strong>Let them work through one problem</strong> on their own.</li>
</ol>
<p>That's it. Start small, be consistent, and trust the process. Your child's future self will thank you.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Evolution of Software Development: AI as a Partner, Not a Replacement]]></title><description><![CDATA[The integration of AI into software development isn't about replacement—it's about augmentation and evolution.]]></description><link>https://www.stevebrownlee.com/ai-as-partner/</link><guid isPermaLink="false">67fd5757ceadb00ae6eeffb3</guid><dc:creator><![CDATA[Steve Brownlee]]></dc:creator><pubDate>Mon, 14 Apr 2025 19:12:16 GMT</pubDate><media:content url="https://www.stevebrownlee.com/content/images/2025/04/ai-partner-2.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://www.stevebrownlee.com/content/images/2025/04/ai-partner-2.png" alt="Evolution of Software Development: AI as a Partner, Not a Replacement"><p>In the rapidly evolving landscape of technology, AI code generation has emerged as a transformative—and contentious—force in software development. Yet, amidst the buzz, uninformed opinions, and typical mass-media hyperbole that dominate professional platforms, it's critical to establish a grounded perspective on what AI really means for developers and the future of our profession.</p>
<h2 id="aicodegenerationevolutionnotrevolution">AI Code Generation: Evolution, Not Revolution</h2>
<p>AI code generation isn't a sudden disruption—it's simply the natural evolution of what developers have been doing for decades. Our core responsibility has never been about typing code; it's about solving problems and defining resilient, scalable, and efficient solutions.</p>
<p>Think back to our progression over the decades:</p>
<ul>
<li>We started with manual coding of everything</li>
<li>Then adopted libraries to avoid reinventing the wheel</li>
<li>Then embraced frameworks that provided structural patterns</li>
<li>Then built our own social platforms where code could be shared</li>
<li>Then utilized code generators and snippets to accelerate common tasks</li>
<li>Now we're employing AI to handle the &quot;busy work&quot; of implementation</li>
</ul>
<p>This progression has consistently moved us away from the mechanical aspects of coding toward focusing on the more valuable aspects of development: architecture, design patterns, and business requirements. With AI handling implementation details, we aren't becoming obsolete—we're evolving into highly trained prompt designers and solution architects.</p>
<h2 id="jobsecurityintheaiera">Job Security in the AI Era</h2>
<p>No, AI will not take our jobs. Rather, it will vastly accelerate our work if we adapt our skills to provide comprehensive context and clearly defined plans to our AI tools. The developers who thrive will be those who:</p>
<ul>
<li>Understand systems holistically</li>
<li>Can translate business requirements into technical specifications</li>
<li>Know how to guide AI tools with contextually rich prompts</li>
<li>Can validate, refine, and integrate AI-generated outputs</li>
<li>Maintain a critical eye for edge cases and potential issues</li>
</ul>
<p>The value proposition of developers is shifting from</p>
<blockquote>
<p>&quot;I can write this code&quot;</p>
</blockquote>
<p>to</p>
<blockquote>
<p>&quot;I can envision this solution and orchestrate its implementation.&quot;</p>
</blockquote>
<p>This is a higher-order skill that AI enhances rather than replaces—which is a good thing because we aren't paid by a business to write code, but rather in return for the value we provide in building their products that generate revenue.</p>
<p>It is our professional integrity that ensures that the code is structurally and systemically sound, and is highly efficient and maintainable.</p>
<h2 id="theriseofinternalaisystems">The Rise of Internal AI Systems</h2>
<p>As the limitations and security concerns of public LLMs become more apparent, forward-thinking companies are increasingly investing in building internal AI systems. These proprietary solutions offer significant advantages:</p>
<ul>
<li>Protection of intellectual property and trade secrets</li>
<li>Domain-specific training that understands company architecture and coding standards</li>
<li>Integration with internal systems and codebases</li>
<li>Compliance with industry-specific regulations</li>
</ul>
<p>This trend creates new opportunities for developers with expertise in AI infrastructure, model fine-tuning, and system integration. Far from eliminating jobs, it's creating entirely new specialized roles within the development ecosystem.</p>
<h2 id="theemergingtpobpotandem">The Emerging TPO/BPO Tandem</h2>
<p>The future of product development likely involves a restructuring of traditional roles into a tandem team approach:</p>
<ul>
<li><strong>Business Product Owners (BPOs)</strong> will focus on client relationships, gathering requirements, and defining features from a business perspective.</li>
<li><strong>Technical Product Owners (TPOs)</strong> will translate those requirements into technical specifications and work with agentic AI tools to produce the code and systems for implementation.</li>
</ul>
<p>This partnership model leverages AI while maintaining the crucial human elements of client understanding and technical oversight. The TPO role becomes less about direct coding and more about system design, prompt engineering, mentorship, and quality assurance.</p>
<h2 id="thecriticalroleofmentorship">The Critical Role of Mentorship</h2>
<p>The most important of those skills for the long-term health of any organization is the constant development of strong mentorship skills. As AI handles more routine coding tasks, the transmission of deeper architectural knowledge and system thinking becomes essential. TPOs might typically be responsible for training 1-3 apprentices in the skillset needed to thrive in this new paradigm.</p>
<p>This mentorship component addresses one of the most legitimate concerns about AI in development: how will the next generation learn if they don't begin with the fundamentals? The answer lies in intentional apprenticeship structures where experienced TPOs guide newcomers through understanding not just what code does, but why certain approaches are chosen and how systems work together.</p>
<h2 id="thefuture">The Future</h2>
<p>The integration of AI into software development isn't about replacement—it's about augmentation and evolution. By embracing AI as a partner rather than fearing it as a competitor, developers can focus on the higher-value aspects of their profession while accelerating delivery and innovation.</p>
<p>Those who adapt their skills to include prompt engineering, system architecture, and mentorship will not only survive but thrive in this new era of development. The future belongs not to those who can code faster, but to those who can envision solutions more clearly and guide both humans and AI tools toward their successful implementation.</p>
<p>You can either fight this trend because you feel threatened by it, or you can develop your growth mindset and embrace this new tool and help guide its integration into our profession. If you choose the former, you are largely guaranteeing your obsolescence.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Lore: Reliable AI Response Streaming with TCP-Inspired Buffer Management]]></title><description><![CDATA[Learn how I built a reliable AI chat system using TCP-inspired design: sequence numbers, acknowledgments, and retransmission. The result? Zero lost messages in production while maintaining real-time streaming performance.]]></description><link>https://www.stevebrownlee.com/lore/</link><guid isPermaLink="false">678f29aaceadb00ae6eeff94</guid><dc:creator><![CDATA[Steve Brownlee]]></dc:creator><pubDate>Sun, 16 Feb 2025 01:36:22 GMT</pubDate><media:content url="https://www.stevebrownlee.com/content/images/2025/02/uthenbryt_arcane_style_crystal_ball_with_the_word_LORE_floating_4e986dd5-41c7-4663-aef9-e89c254872e9.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://www.stevebrownlee.com/content/images/2025/02/uthenbryt_arcane_style_crystal_ball_with_the_word_LORE_floating_4e986dd5-41c7-4663-aef9-e89c254872e9.png" alt="Lore: Reliable AI Response Streaming with TCP-Inspired Buffer Management"><p>When building <a href="https://github.com/stevebrownlee/service-lore">Lore</a>, a service that provides AI-generated programming concept explanations to beginners, I faced an interesting challenge: How could I ensure reliable delivery of streamed responses while maintaining real-time performance?</p>
<p>The solution drew inspiration from one of networking's most battle-tested protocols - TCP's sliding window mechanism.</p>
<blockquote>
<p>If you are new to TCP, I highly recommend reading &quot;<a href="https://www.geeksforgeeks.org/what-is-transmission-control-protocol-tcp/">What is TCP (Transmission Control Protocol)?</a>&quot;</p>
</blockquote>
<h2 id="thechallenge">The Challenge</h2>
<p>Streaming AI-generated text presents several reliability concerns:</p>
<ul>
<li>Network interruptions could cause lost chunks of text</li>
<li>Client-side processing delays might miss chunks</li>
<li>Server-side buffer overflows could drop content</li>
<li>Out-of-order delivery would create nonsensical responses</li>
</ul>
<p>Traditional request/response patterns wouldn't work well here. I needed a way to stream content as it was generated while ensuring every piece reached the client in the correct order.</p>
<h2 id="thetcpinspiration">The TCP Inspiration</h2>
<p>TCP's sliding window protocol has managed reliable data transfer across unreliable networks for decades. Its core concepts seemed perfect for this use case:</p>
<ul>
<li>Sequence numbers for tracking chunks</li>
<li>Window-based flow control</li>
<li>Acknowledgment system</li>
<li>Retransmission of lost data</li>
</ul>
<h2 id="videodemo">Video Demo</h2>
<p>I recorded the <a href="https://app.screencastify.com/v3/watch/Rqi6XbDyeHT10I9bjEKI">initial service demo</a> immediately after I had a reliable, working version. There are mny things that need to be done to make it robust and scalable to more than one user, but I'm excited that I got the basics to work.</p>
<h2 id="implementation">Implementation</h2>
<p>I designed a buffering system that mirrors these TCP concepts:</p>
<pre><code class="language-python">class ChunkBuffer:
    def __init__(self, request_id: int, window_size: int = 5):
        self.request_id: int = request_id
        self.window_size: int = window_size
        self.buffer: dict[int, TextChunk] = {}
        self.next_sequence: int = 0
        self.last_acked: int = -1
        self.unacked_chunks: dict[int, TextChunk] = {}
        self.last_transmit: dict[int, float] = {}
        self.condition = threading.Condition()
</code></pre>
<p>The buffer maintains a window of unacknowledged chunks. Chunks are built up as my model generates new text from a streamer.</p>
<pre><code class="language-py"># Initialize a streamer so I don't have to wait for entire response
streamer = TextIteratorStreamer(
    self.tokenizer,
    timeout=None,
    skip_prompt=True,
    skip_special_tokens=True
)
</code></pre>
<p>Then a new thread is started in which the <code>generate()</code> method on the model is called.</p>
<pre><code class="language-py">thread = threading.Thread(
    target=self.model.generate,
    kwargs={
        &quot;input_ids&quot;: inputs[&quot;input_ids&quot;],
        &quot;streamer&quot;: streamer,
        &quot;max_new_tokens&quot;: self.settings.MODEL_MAX_LENGTH,
        &quot;do_sample&quot;: True,
        &quot;temperature&quot;: self.settings.MODEL_TEMPERATURE,
        &quot;top_p&quot;: 0.9,
        &quot;top_k&quot;: 50,
        &quot;repetition_penalty&quot;: 1.2,
        &quot;no_repeat_ngram_size&quot;: 3
    }
)
thread.start()
</code></pre>
<p>The cool thing about this is that I can now just wait for new bits text to be generated by the model, and build up chunks to be sent to the client.</p>
<pre><code class="language-py"># Process generated chunks
current_chunk = &quot;&quot;
for new_text in streamer:
    current_chunk += new_text

    # Buffer chunks when they reach defined size
    if len(current_chunk) &gt;= self.settings.BUFFER_CHUNK_SIZE:
        chunk_obj = buffer.add_chunk(current_chunk)
        current_chunk = &quot;&quot;

        # Publish new chunk to the message bus
        self.valkey.publish(
            f'{self.settings.RESPONSE_CHANNEL_PREFIX}{question.request_id}',
            chunk_obj.model_dump_json()
        )
</code></pre>
<h2 id="theflowcontroldance">The Flow Control Dance</h2>
<p>Just like TCP, the system uses back pressure to prevent overwhelming any component:</p>
<ol>
<li>The model generates text chunks</li>
<li>Chunks enter the buffer until it reaches window_size</li>
<li>Generation pauses until acknowledgments arrive</li>
<li>Each acknowledgment frees buffer space</li>
<li>Generation resumes when space is available</li>
</ol>
<p>This creates a natural flow control system where the client's processing speed influences the generation pace.</p>
<h2 id="multithreadedarchitecture">Multi-Threaded Architecture</h2>
<p>The service runs multiple concurrent threads to handle different responsibilities:</p>
<ol>
<li>Question Thread: Listens for incoming questions and initiates response generation</li>
<li>AI Thread: Handles the model inference and chunk generation</li>
<li>Acknowledgment Thread: Processes chunk acknowledgments</li>
<li>Retransmission Thread: Monitors for and handles lost chunks</li>
</ol>
<p>Here's how the service initializes the initial threads. The text generation thread was shown above.</p>
<pre><code class="language-python">def start(self) -&gt; None:
    &quot;&quot;&quot;Start all service threads&quot;&quot;&quot;
    try:
        # Initialize and start service threads
        self.question_thread = threading.Thread(
            target=self._process_questions,
            name=&quot;question_thread&quot;
        )
        self.ack_thread = threading.Thread(
            target=self._process_acks,
            name=&quot;ack_thread&quot;
        )
        self.retransmit_thread = threading.Thread(
            target=self._process_retransmits,
            name=&quot;retransmit_thread&quot;
        )
        
        # Start threads
        self.question_thread.start()
        self.ack_thread.start()
        self.retransmit_thread.start()
        
</code></pre>
<h2 id="monitoringwithprometheusandgrafana">Monitoring with Prometheus and Grafana</h2>
<p>To ensure reliability and performance, the service includes comprehensive monitoring using Prometheus and Grafana running in Docker containers. The Lore service publishes metrics data in key places, which is available from a Prometheus HTTP server. Grafana, running as a separate service, periodically scrapes that raw data to display it in a more visuall appealing way.</p>
<h3 id="prometheusmetricscollection">Prometheus Metrics Collection</h3>
<p>The service exposes key metrics through a Prometheus endpoint:</p>
<ul>
<li>Buffer utilization rates</li>
<li>Chunk transmission latency</li>
<li>Acknowledgment processing times</li>
<li>Retransmission counts</li>
<li>Model generation speed</li>
</ul>
<h2 id="realtimedeliverywithserversentevents">Real-Time Delivery with Server-Sent Events</h2>
<p>Lore implements real-time response streaming using Server-Sent Events (SSE), enabling chunk-by-chunk delivery of AI responses to clients. The streaming process involves three main components working in concert.</p>
<h3 id="messageflow">Message Flow</h3>
<p>First, Lore generates response chunks and publishes them to Valkey. Each chunk is a complete package of information.</p>
<ul>
<li>Sequence number</li>
<li>Text generated by model</li>
<li>Request ID</li>
<li>Completion status</li>
</ul>
<p>The Django API acts as the intermediary, subscribing to these chunks from Valkey as they arrive. It creates a streaming response using <code>StreamingHttpResponse</code> and formats each chunk as an SSE event. Throughout this process, the API maintains an open connection, staying ready to receive and forward chunks until the final one arrives.</p>
<p>On the frontend, the client establishes an SSE connection to receive these chunks in real-time. As each chunk arrives, the client processes it and sends back an acknowledgment to confirm receipt. This acknowledgment system is crucial for reliability—if any chunks go missing in transit, they'll be automatically retransmitted. The entire process is designed for smooth, efficient operation from start to finish, with clean connection handling throughout.</p>
<p>This architecture ensures:</p>
<ul>
<li>Real-time delivery of responses</li>
<li>Reliable message delivery with acknowledgments</li>
<li>Automatic retransmission of lost chunks</li>
<li>Clean connection handling</li>
</ul>
<h2 id="results">Results</h2>
<p>The TCP-inspired design of this system has exceeded expectations in production. By implementing sequence numbers, acknowledgments, and retransmission, I've achieved perfect reliability — not a single chunk has been lost.</p>
<p>The sequencing system ensures responses always arrive in the correct order, while the windowing mechanism provides natural flow control. When the client application process chunks slowly, the system adapts automatically rather than overwhelming them with data.</p>
<p>Even network interruptions are handled gracefully, with the system picking up right where it left off when the connection is restored.</p>
<h2 id="conclusion">Conclusion</h2>
<p>By borrowing concepts from TCP and implementing a multi-threaded architecture with robust monitoring, I turned a potentially fragile streaming system into a reliable, observable, production-ready service. It's a reminder that often the best solutions come from adapting proven patterns to new contexts while ensuring proper observability.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Pioneering Education Strategies in Software Developer Bootcamps: Fading Into Independence]]></title><description><![CDATA[<div class="kg-card-markdown"><p>This article is part of the <strong>Follow the Science</strong> series where I share our team's journey in developing a learning experience based on modern cognitive science, learning science, and educational psychology.</p>
<h2 id="introduction">Introduction</h2>
<p>In our software development bootcamp, we employ a powerful educational strategy known as &quot;Faded Worked Examples&quot;</p></div>]]></description><link>https://www.stevebrownlee.com/follow-the-science-series-faded-worked-examples/</link><guid isPermaLink="false">654b137e8ecff66aeb892d2a</guid><dc:creator><![CDATA[Steve Brownlee]]></dc:creator><pubDate>Tue, 21 Jan 2025 04:57:48 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>This article is part of the <strong>Follow the Science</strong> series where I share our team's journey in developing a learning experience based on modern cognitive science, learning science, and educational psychology.</p>
<h2 id="introduction">Introduction</h2>
<p>In our software development bootcamp, we employ a powerful educational strategy known as &quot;Faded Worked Examples&quot; to enable our learners to develop targeted vocabulary and understanding. This method starts with high support in new content areas and gradually reduces assistance, fostering independent problem-solving skills. Cognitive science underpins this approach by acknowledging the benefits of decreasing instructional guidance to enhance learning.</p>
<h2 id="whatarefadedworkedexamples">What are Faded Worked Examples?</h2>
<p>Faded Worked Examples (FWEs) are a step-by-step demonstration of tasks, slowly removing the training wheels as students gain competency. This technique aligns with cognitive load theory, which posits that learning is more effective when unnecessary mental work is removed, allowing students to focus on problem-solving.</p>
<blockquote>
<p>Hattie (2009) reported in his synthesis of research on learning and teaching that conventional worked examples, when compared to learning by problem solving, have medium to strong effects (see also the classic studies by Sweller &amp; Cooper, 1985) ... When self-explanations are fostered the positive effect roughly doubles to a strong effect (Hattie, 2009; Renkl, in press-a).</p>
<p><sub><a href="https://teachpsych.org/ebooks/asle2014/index.php">Applying Science of Learning in Education</a> - Learning From Worked Examples: How to Prepare Students for Meaningful Problem Solving (Alexander Renkl)</sub></p>
</blockquote>
<p>The combination of FWE and reflection has a measured strong, positive effect on a learner's ability to integrate new competencies and concepts into their problem-solving skills.</p>
<h3 id="ourimplementation">Our Implementation</h3>
<p>Once we switched the structure of the coursework to follow this strategy, we immediately saw the following outcomes:</p>
<ol>
<li>Higher ownership of learning by the student.</li>
<li>Greater independence <em>(especially combined with the small team approach we take)</em>.</li>
<li>Stronger competencies during group projects.</li>
<li>More understanding when meeting with students to discuss their self-reflections.</li>
</ol>
<p>Each section of the course introduces a small set of new concepts that build on what was learned in the last section <em>(a.k.a. scaffolding)</em>. We then design 4 projects that the learners will build in which they will apply those concepts and skills. The context swtiching slightly from project to project to ensure that they learner</p>
<ul>
<li><strong>Initial Exposure:</strong> Students first receive comprehensive, step-by-step guidance on new concepts.</li>
<li><strong>Progressive Reduction:</strong> With each new project, less of the solution is provided upfront, challenging students to apply their understanding.</li>
<li><strong>Full Implementation:</strong> Eventually, students tackle projects without provided examples, fully applying their knowledge.</li>
</ul>
<h2 id="cognitivesciencejustification">Cognitive Science Justification</h2>
<p>FWEs work hand-in-hand with cognitive science research by honoring the limitations and strengths of working memory.</p>
<h3 id="reducingcognitiveload">Reducing Cognitive Load</h3>
<ul>
<li><strong>Segmenting Information:</strong> Breaking down tasks into smaller parts helps manage cognitive load for novice learners.</li>
<li><strong>Providing a Strong Foundation:</strong> Early comprehensive guidance helps build a robust knowledge base, crucial for tackling more complex problems later.</li>
</ul>
<h3 id="promotingactivelearning">Promoting Active Learning</h3>
<ul>
<li><strong>Engagement With Material:</strong> As guidance fades, students must engage more deeply with the material, which improves retention and understanding.</li>
<li><strong>Encouraging Mental Effort:</strong> The gradual increase in difficulty requires students to invest mental effort, solidifying their learning and enhancing problem-solving skills.</li>
</ul>
<h2 id="implementingfwesinthebootcamp">Implementing FWEs in the Bootcamp</h2>
<p>Our curriculum is crafted to integrate FWEs in a manner that respects the individual's learning curve while promoting steady progress.</p>
<h3 id="earlystagehighsupport">Early Stage: High Support</h3>
<p>In the beginning, our coaches provide detailed explanations and complete code examples, ensuring foundational concepts are clear.</p>
<h3 id="middlestageguidedpractice">Middle Stage: Guided Practice</h3>
<p>As students progress, they receive partial solutions alongside their projects, encouraging them to think critically to complete the tasks.</p>
<h3 id="finalstageindependentgroupprojects">Final Stage: Independent &amp; Group Projects</h3>
<p>In the advanced phase, students receive project briefs that they must plan and execute independently, using the skills developed in earlier stages.</p>
<h2 id="benefitsforstudents">Benefits for Students</h2>
<p>The FWE strategy offers multiple benefits, preparing students for real-world software development challenges.</p>
<h3 id="confidencebuilding">Confidence Building</h3>
<p>Starting with full support and moving to independent work helps students build confidence in their abilities to solve programming challenges.</p>
<h3 id="skillsapplication">Skills Application</h3>
<p>By progressively challenging students, they learn not just to replicate solutions but to create them, fostering deep learning and creativity.</p>
<h3 id="preparationforemployment">Preparation for Employment</h3>
<p>The transition from worked examples to independent problem-solving prepares students for the autonomy required in a professional setting.</p>
<h2 id="challengesandconsiderations">Challenges and Considerations</h2>
<p>Applying FWEs effectively requires careful consideration of the pacing and complexity of the faded guidance.</p>
<h3 id="individualpacing">Individual Pacing</h3>
<p>Not all students progress at the same rate, necessitating adjustments to the fading speed to accommodate different learning speeds.</p>
<h3 id="qualityofworkedexamples">Quality of Worked Examples</h3>
<p>The worked examples must be well-designed to ensure they are instructive and relevant to the tasks students will eventually face independently.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Faded Worked Examples represent a pedagogical commitment to empowering students, backed by cognitive science. By carefully structuring lessons to transition from complete guidance to independent coding, our bootcamp ensures that students are not just learning to code—they're learning to think and act like professional developers.</p>
</div>]]></content:encoded></item><item><title><![CDATA[The First Principles of the High Value Software Developer]]></title><description><![CDATA[Much like a painting maestro would never hand beginners brushes and paint and tell them to start painting, beginner software developers should not be told that their primary goal is to write code.]]></description><link>https://www.stevebrownlee.com/first-princples-software-developer/</link><guid isPermaLink="false">639d25668ecff66aeb892d12</guid><category><![CDATA[software development]]></category><category><![CDATA[learning]]></category><category><![CDATA[education]]></category><dc:creator><![CDATA[Steve Brownlee]]></dc:creator><pubDate>Tue, 21 Jan 2025 04:44:30 GMT</pubDate><media:content url="https://www.stevebrownlee.com/content/images/2025/01/First_Principles.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://www.stevebrownlee.com/content/images/2025/01/First_Principles.png" alt="The First Principles of the High Value Software Developer"><p>If you ask most people what the most important skill a software developer needs is, the answer would likely be &quot;good code.&quot; If you stop thinking about it at that point, then the apparent plan to train beginners in software development would be to simply teach them how to code. There are many tales fraught with the errors of this misguided approach.</p>
<p>My assertion is that the ability to efficiently solve problems with technology is what brings value. The medium by which a software developer solves problems is, most often, code.</p>
<p>The ability to produce accurate, reliable code is an emergent behavior of four fundamental skills, or principles. If you can coach someone to strengthen these essential skills, then their ability to provide value to an organization through their code is a natural outcome of the expression of those skills.</p>
<p>Much like a painting maestro would never hand beginners brushes and paint and tell them to start painting, beginner software developers should not be told that their <strong>primary</strong> goal is to write code.</p>
<p>To continue the analogy, before a person can focus on creating art, the following foundational pillars of the craft must be developed:</p>
<ol>
<li>Composition</li>
<li>Color theory</li>
<li>Anatomy and figure drawing</li>
<li>Perspective</li>
<li>Art history</li>
</ol>
<h2 id="firstpillarcommunication">First Pillar: Communication</h2>
<p>To solve a problem, one must first understand the problem.</p>
<p>The only way to understand the problem is to be able to communicate with the people around you. This skill must be strengthened to produce a valuable software developer since she must communicate effectively with technical and non-technical people.</p>
<p>Modern software development is a team sport.</p>
<ol>
<li>Master complex communication during group-based work.</li>
<li>Use correct vocabulary when describing technical concepts.</li>
<li>Know how and when to ask for help from a senior technical resource.</li>
<li>Know how and when to ask for clarification from customers, product managers, and product designers.</li>
<li>Document solutions and challenges with clear, easily understood language.</li>
</ol>
<h2 id="secondpillaranalyticalthinking">Second Pillar: Analytical Thinking</h2>
<p>Once a problem is understood, one must analyze it and break it down into technical tasks.</p>
<p>Imagine that your product managers have discovered a need by your customers. They need to see the daily report of yearly sales trends. Each night, a day's sales need to be processed and added to a database. By the next day, business owners should see the total sales, by product category, across the entire year, including the previous day's sales.</p>
<p>When a software developer looks at a business problem like this, <strong>analytical thinking</strong> is required to identify all the technical tasks necessary to accomplish this goal.</p>
<ol>
<li>Ensure that the graph data includes the previous day's sales.</li>
<li>Be alerted when daily sales fail to be loaded into the database.</li>
<li>Execute a process to get daily sales loaded to load into the database.</li>
<li>Transform the raw data into a format that is needed for the graph.</li>
</ol>
<p>This is a small sample of smaller tasks that, when completed, will work together to solve the problem. Possible tools are identified, and then each one is evaluated to determine which one would be the most effective for each task.</p>
<h2 id="thirdpillaralgorithmicthinking">Third Pillar: Algorithmic Thinking</h2>
<p>Once a problem is understood, analyzed, and deconstructed into functional units, <strong>algorithmic thinking</strong> develops a logical, efficient series of steps to solve each unit. Each functional unit is broken down into basic operations (BO) or elementary operations (EO).</p>
<p>A software developer must identify and understand the dependencies in the task list and document an order of operations that must be followed.An efficient developer would rearrange the tasks into the following order in the example series of tasks identified in the previous section.</p>
<ol>
<li>Execute a process to get daily sales loaded into the database.</li>
<li>Be alerted when daily sales fail to be loaded into the database.</li>
<li>Transform the raw data into a format that is needed for the graph.</li>
<li>Ensure that the graph data includes the previous day's sales.</li>
</ol>
<p>Then each task would be broken down further into small, discrete operations. For example, the operations for the first task could be defined with the following list.</p>
<ol>
<li>Update the sales database table to include a timestamp.</li>
<li>Define a code module that would accept data from retail locations, and include validation that it is in the expected format.</li>
<li>Update the database access module to allow the daily sales to be inserted into the database.</li>
<li>Create a new endpoint in the API that all retail locations would send their daily sales.</li>
<li>Document the endpoint, parameters, and validations so they can be sent to the retail locations to be implemented.</li>
</ol>
<p><strong>Algorithmic thinking</strong> is critical to ensure an effective workflow for the entire team so that the solution can be delivered to the customer in a reasonable amount of time and for a reasonable cost.</p>
<p>Doing things in the wrong order ensures wasted efforts, failing tests, and increased costs.</p>
<h2 id="fourthpillarefficientlearning">Fourth Pillar: Efficient Learning</h2>
<p>Talk to any software developer about the state of the profession, and the topic of the rapid pace of new technologies and tools being produced will come up. As a community, software developers continually devise new tools, and new languages, with the intent of making the job easier and the code more efficient.</p>
<p>This happens quite often, so a software developer must be efficient at learning these new tools to keep their skills sharp and provide maximum value.</p>
<p>Efficient learners take the time to use every resource available to learn a new skill or implement a non-mastered skill in a new context. Some specific tools and skills must be used for beginners to learn the basics.</p>
<ol>
<li>Referencing previous solutions</li>
<li>Expert debugging skills</li>
<li>Context-complete generative AI prompting</li>
<li>Browser developer tools</li>
<li>Searching the Web for resources, and evaluating results</li>
</ol>
<p>Efficient learners also take a critical approach to <strong>what</strong> must be learned next. Learning the latest and greatest tool is often not the best approach to ensure you are increasing your value. I believe a balanced approach of learning fundamental concepts and skills along with modern tools serves technologists, and the businesses they support, best.</p>
</div>]]></content:encoded></item><item><title><![CDATA[The Rise and Fall of TypeScript]]></title><description><![CDATA[<div class="kg-card-markdown"><h1 id="ananalysisofitsimpactonwebdevelopment">An Analysis of its Impact on Web Development</h1>
<h2 id="introduction">Introduction</h2>
<p>Since the inception of the World Wide Web in the early 1990s, JavaScript has been the primary language for creating interactive and sophisticated user interfaces in web browsers. As an interpreted language, JavaScript lacks static typing in its core specification, offering</p></div>]]></description><link>https://www.stevebrownlee.com/the-rise-and-fall-of-typescript/</link><guid isPermaLink="false">66d14a468ecff66aeb892d57</guid><dc:creator><![CDATA[Steve Brownlee]]></dc:creator><pubDate>Tue, 21 Jan 2025 03:47:24 GMT</pubDate><media:content url="https://www.stevebrownlee.com/content/images/2025/01/The_Rise_and_Fall_of_Typecript.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><h1 id="ananalysisofitsimpactonwebdevelopment">An Analysis of its Impact on Web Development</h1>
<h2 id="introduction">Introduction</h2>
<img src="https://www.stevebrownlee.com/content/images/2025/01/The_Rise_and_Fall_of_Typecript.png" alt="The Rise and Fall of TypeScript"><p>Since the inception of the World Wide Web in the early 1990s, JavaScript has been the primary language for creating interactive and sophisticated user interfaces in web browsers. As an interpreted language, JavaScript lacks static typing in its core specification, offering flexibility and ease of use that have contributed to its widespread adoption. However, in recent years, Microsoft's TypeScript has gained significant popularity among developers, sparking debates about its value and impact on web development.</p>
<p>This article aims to provide a balanced, evidence-based analysis of the impact of TypeScript on web development, comparing it to traditional JavaScript. We will explore the claimed benefits of TypeScript, examine criticisms and challenges, review available empirical evidence, and consider the broader context of the evolving JavaScript ecosystem.</p>
<h2 id="theriseoftypescript">The Rise of TypeScript</h2>
<h3 id="background">Background</h3>
<p>TypeScript, first released by Microsoft in 2012, is a strict syntactical superset of JavaScript that adds optional static typing to the language. It compiles to plain JavaScript, allowing it to run in any environment that supports JavaScript, including browsers, Node.js, and Deno.</p>
<p>The key features that distinguish TypeScript from JavaScript include:</p>
<ol>
<li>Static typing</li>
<li>Class-based object-oriented programming</li>
<li>Improved tooling support</li>
<li>ECMAScript features from future JavaScript versions</li>
</ol>
<p>TypeScript was designed to address perceived shortcomings in JavaScript, particularly for large-scale applications. Its development was led by Anders Hejlsberg, the lead architect of C# at Microsoft, which partly explains its appeal to developers from statically-typed language backgrounds.</p>
<h3 id="reasonsforadoption">Reasons for Adoption</h3>
<p>The adoption of TypeScript has been driven by several factors:</p>
<ol>
<li>
<p><strong>Enhanced Developer Experience</strong>: TypeScript's static typing enables better IDE support, including improved autocompletion, navigation, and refactoring tools. This can lead to a more efficient development process, especially in larger codebases.</p>
</li>
<li>
<p><strong>Error Detection</strong>: The type system allows many errors to be caught at compile-time rather than runtime, potentially reducing the number of bugs that make it to production.</p>
</li>
<li>
<p><strong>Code Documentation</strong>: Types can serve as a form of self-documentation, making it easier for developers to understand and work with existing code.</p>
</li>
<li>
<p><strong>Scalability</strong>: For large projects with multiple developers, TypeScript's features can help enforce more consistent coding patterns and make it easier to maintain and refactor code over time.</p>
</li>
<li>
<p><strong>Familiarity for Java/C# Developers</strong>: The static typing and object-oriented features of TypeScript can make JavaScript development more approachable for developers coming from languages like Java or C#.</p>
</li>
<li>
<p><strong>Corporate Backing</strong>: Microsoft's support and continued development of TypeScript have given it credibility in enterprise environments.</p>
</li>
</ol>
<h3 id="reasonsnottoadopt">Reasons Not to Adopt</h3>
<p>Despite its growing popularity, there are several reasons why some developers and organizations choose not to adopt TypeScript:</p>
<ol>
<li>
<p><strong>Added Complexity</strong>: TypeScript introduces additional concepts and syntax that developers need to learn, which can increase the learning curve for those already proficient in JavaScript.</p>
</li>
<li>
<p><strong>Compilation Overhead</strong>: TypeScript requires a compilation step, which can add complexity to the build process and potentially slow down development cycles.</p>
</li>
<li>
<p><strong>Type Definition Maintenance</strong>: For projects using third-party libraries, maintaining and updating type definitions can be an ongoing challenge.</p>
</li>
<li>
<p><strong>Overengineering Risk</strong>: In some cases, developers often overuse TypeScript's features, leading to unnecessarily complex code that's harder to maintain.</p>
</li>
<li>
<p><strong>Limited Runtime Benefits</strong>: TypeScript's benefits are primarily during development; it doesn't offer performance improvements at runtime compared to equivalent JavaScript code.</p>
</li>
<li>
<p><strong>Ecosystem Maturity</strong>: While improving, not all JavaScript libraries and frameworks have robust TypeScript support, which can lead to integration challenges.</p>
</li>
<li>
<p><strong>Project Size Considerations</strong>: For smaller projects or rapid prototyping, the benefits of TypeScript most likely do not outweigh the initial setup and ongoing maintenance costs.</p>
</li>
</ol>
<p>In the following sections, we will delve deeper into both the claimed benefits and criticisms of TypeScript, examining the available evidence to provide a balanced view of its impact on web development.</p>
<h2 id="claimedbenefitsoftypescript">Claimed Benefits of TypeScript</h2>
<p>Proponents of TypeScript often highlight several key advantages over traditional JavaScript. Let's explore these claimed benefits in detail, while also considering potential counterarguments to provide a balanced perspective.</p>
<h3 id="typesafety">Type Safety</h3>
<p>One of the primary selling points of TypeScript is its static typing system, designed to catch type-related errors during development before the code is executed. With TypeScript, developers can annotate variables, function parameters, and return types with specific types such as string, number, boolean, or custom interfaces. The TypeScript compiler then checks these annotations against the actual usage in the code, flagging any mismatches as errors.</p>
<p>This type checking mechanism is said to offer several benefits. Firstly, it allows for early error detection, potentially reducing the number of bugs that make it to production. By catching type-related issues during development, programmers can address problems sooner, potentially saving time and resources in the long run.</p>
<p>Secondly, advocates argue that static typing leads to improved code quality. The process of thinking about and defining types can encourage developers to write more robust and self-documenting code. This added layer of information can make it easier for developers to understand the intended use of various components within a system.</p>
<h4 id="criticalconsiderations">Critical Considerations</h4>
<p>The effectiveness of static typing in preventing bugs is a topic of ongoing debate in the programming community. Some argue that comprehensive unit testing can achieve similar or better results in terms of catching errors. Additionally, there's a trade-off to consider between the time spent defining types and the time potentially saved by catching type-related errors early. It's also worth noting that while TypeScript can catch many type-related errors during development, it doesn't eliminate the need for runtime type checking, especially when dealing with external data sources.</p>
<h3 id="developerexperience">Developer Experience</h3>
<p>TypeScript aims to enhance the developer experience, particularly when working with large codebases or in team environments. One of the most touted benefits is the improved tooling and IDE support that comes with static typing.</p>
<p>With TypeScript, developers often experience better autocompletion and IntelliSense in their code editors. This means more accurate and context-aware code suggestions as they type, which can speed up the coding process and reduce simple errors. Enhanced code navigation features, such as &quot;go to definition&quot; and &quot;find all references,&quot; can also make it easier for developers to understand and work with large codebases.</p>
<p>These features can be particularly beneficial for team collaboration. Types can serve as a form of live documentation, making it easier for developers to understand and work with code written by others. This can lead to increased confidence when refactoring or modifying existing code, as the compiler will catch many potential issues.</p>
<h4 id="criticalconsiderations">Critical Considerations</h4>
<p>It's important to note that the benefits of improved tooling may be less noticeable in smaller projects or for developers already proficient with JavaScript tooling. Some developers argue that the additional cognitive load of working with types can slow down the development process, especially during the initial learning phase. There's also a risk of over-reliance on tooling, which might lead to less attention being paid to writing clear, self-explanatory code. Furthermore, the need to maintain type definitions for third-party libraries can sometimes lead to version conflicts and additional maintenance overhead.</p>
<h3 id="codemaintainability">Code Maintainability</h3>
<p>Advocates of TypeScript often claim that it leads to more maintainable code, especially in larger projects. The argument is that type annotations can make the intent of the code clearer, reducing the need for additional comments. Interfaces and type definitions can serve as contracts between different parts of the application, making it easier to understand how components interact.</p>
<p>For large-scale projects, TypeScript can offer several maintainability benefits. It can make onboarding new team members easier, as types provide additional context about the codebase. There's also a reduced risk when refactoring, as many potential issues will be caught by the compiler. Furthermore, TypeScript can help enforce consistency in data structures and function signatures across the project.</p>
<h4 id="criticalconsiderations">Critical Considerations</h4>
<p>These maintainability benefits may be less pronounced in smaller projects or those with a short lifespan. It's also worth considering that overly complex type definitions can potentially make code harder to read and maintain. The maintainability benefits rely on consistent and judicious use of TypeScript features across the project. There's a risk of &quot;type creep,&quot; where developers spend excessive time crafting elaborate type structures that add more complexity than clarity. Additionally, in fast-moving projects or those with changing requirements, the need to constantly update type definitions could potentially slow down development and become a maintenance burden in itself.</p>
<p>While TypeScript offers several potential benefits in terms of type safety, developer experience, and code maintainability, it's important to consider these advantages in the context of your specific project needs and team dynamics. The critical considerations highlighted for each benefit underscore the importance of carefully evaluating whether TypeScript is the right choice for your particular use case. In the following sections, we'll explore further criticisms and challenges associated with TypeScript adoption, providing a balanced view of its impact on web development.</p>
<h2 id="criticismsandchallengesoftypescript">Criticisms and Challenges of TypeScript</h2>
<p>While TypeScript has gained popularity and offers several potential benefits, it's not without its critics. In this section, we'll explore some of the main criticisms and challenges associated with adopting TypeScript in web development projects.</p>
<h3 id="learningcurveandcomplexity">Learning Curve and Complexity</h3>
<p>One of the primary criticisms of TypeScript is the additional complexity it introduces to the development process. For developers who are already proficient in JavaScript, learning TypeScript requires understanding new concepts and syntax related to static typing.</p>
<p>The type system in TypeScript, while powerful, can be intricate. Developers need to learn about interfaces, generics, union types, and other advanced typing features. This learning curve can be steep, especially for those new to statically-typed languages.</p>
<p>Moreover, as projects grow in complexity, so too can the type definitions. In some cases, developers might find themselves spending significant time wrestling with the type system to express complex relationships between different parts of their codebase.</p>
<p>It is becoming common to hear developers complain that time spent wrangling complex types takes longer than development of the feature that was built. Certainly not good news.</p>
<h4 id="criticalconsiderations">Critical Considerations</h4>
<p>The investment in learning TypeScript needs to be weighed against the potential long-term benefits. For small teams or projects with a short lifespan, the time spent learning and implementing TypeScript might not pay off. Additionally, the complexity of the type system can sometimes lead to overly verbose code, potentially reducing readability instead of enhancing it.</p>
<h3 id="developmentspeed">Development Speed</h3>
<p>Another common criticism of TypeScript is its potential impact on development speed, particularly in the early stages of a project or when onboarding new team members.</p>
<p>The need to define types and interfaces before writing functional code can slow down the initial development process. This is especially true in rapid prototyping scenarios or when working on small, short-lived projects where the benefits of static typing might not be fully realized.</p>
<p>Furthermore, when working with third-party libraries, developers often need to install and manage type definitions separately. This can add an extra step to the development process and potentially lead to version conflicts.</p>
<h4 id="criticalconsiderations">Critical Considerations</h4>
<p>While TypeScript advocates argue that the time invested in defining types pays off in the long run through fewer runtime errors and easier refactoring, there is rarely any actual data to support the assertion. The impact on development speed can vary greatly depending on the project's size, complexity, and the team's familiarity with TypeScript.</p>
<h3 id="runtimeperformance">Runtime Performance</h3>
<p>It's important to note that TypeScript's benefits are primarily realized during development. Once compiled, TypeScript code is converted to JavaScript, and all type information is erased. This means that there's no inherent performance benefit at runtime.</p>
<p>In some cases, the compiled JavaScript from TypeScript might even be slightly larger or more complex than hand-written JavaScript, although the difference is usually negligible with proper configuration.</p>
<h4 id="criticalconsiderations">Critical Considerations</h4>
<p>The lack of runtime performance improvements can be a point of contention, especially when weighing the added complexity of TypeScript against its benefits. Some developers argue that well-written JavaScript with comprehensive testing can achieve similar levels of reliability without the overhead of TypeScript.</p>
<h3 id="toolingandbuildprocesscomplexity">Tooling and Build Process Complexity</h3>
<p>Adopting TypeScript typically means adding an extra step to the build process. The TypeScript compiler needs to transpile the code to JavaScript before it can be run in a browser or Node.js environment.</p>
<p>This additional compilation step can increase build times, especially for larger projects. It also adds complexity to the development toolchain, which can be a barrier for some teams or projects.</p>
<h4 id="criticalconsiderations">Critical Considerations</h4>
<p>While modern build tools have made integrating TypeScript easier, the added complexity in the build process can still be a concern. This is especially true for teams that value simplicity in their toolchain or for projects that require quick iteration cycles.</p>
<h3 id="falsesenseofsecurity">False Sense of Security</h3>
<p>One subtle but important criticism of TypeScript is that it can sometimes provide a false sense of security. While the type system catches many errors at compile-time, it doesn't eliminate the need for thorough testing and careful coding practices.</p>
<p>TypeScript's type system is also not sound, meaning there are cases where type checks can be bypassed, potentially leading to runtime errors that weren't caught during compilation.</p>
<h4 id="criticalconsiderations">Critical Considerations</h4>
<p>Over-reliance on TypeScript's type system at the expense of other good development practices like unit testing, integration testing, and code reviews can potentially lead to issues. It's crucial for development teams to understand the limitations of TypeScript's type checking and not view it as a replacement for other quality assurance measures.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Pioneering Education Strategies in Software Developer Bootcamps: Always Projects]]></title><description><![CDATA[<div class="kg-card-markdown"><p>This article is part of the <strong>Follow the Science</strong> series where I share our team's journey in developing a learning experience based on modern cognitive science, learning science, and educational psychology.</p>
<h2 id="introduction">Introduction</h2>
<p>Project-based learning (PBL) is an instructional methodology that enables students to learn by engaging in projects that are</p></div>]]></description><link>https://www.stevebrownlee.com/follow-the-science-series-2/</link><guid isPermaLink="false">654b0ba18ecff66aeb892d24</guid><dc:creator><![CDATA[Steve Brownlee]]></dc:creator><pubDate>Thu, 29 Aug 2024 02:30:10 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>This article is part of the <strong>Follow the Science</strong> series where I share our team's journey in developing a learning experience based on modern cognitive science, learning science, and educational psychology.</p>
<h2 id="introduction">Introduction</h2>
<p>Project-based learning (PBL) is an instructional methodology that enables students to learn by engaging in projects that are complex, require sustained attention, and involve real-world challenges and applications.</p>
<p>PBL shifts the focus from traditional teacher-led instruction to student-driven exploration. Projects are typically centered around questions or problems that compel students to engage in design, problem-solving, decision-making, or investigative activities, giving them a sense of ownership over their learning.</p>
<h2 id="ourmethodology">Our Methodology</h2>
<p>Everything is project work in our learning experience. There are no lectures. There are no repetitive exercises. There are no useless brain twisters or esoteric puzzles for the learner to solve.</p>
<p>PBL is especially powerful for adult learners who are in an accelerated bootcamp to shift quickly into a new career - especially when done in our collaboration focused learning experience.</p>
<p>Malcolm Knowles is a reknowned educator who specialized in the study of adult learninng. He distilled his research into 4 princples.</p>
<hr>
<h3 id="knowles4principlesofandragogy">Knowles’ 4 Principles Of Andragogy</h3>
<ol>
<li>Adults need to be involved in the planning and evaluation of their instruction.</li>
<li>Experience (including mistakes) provides the basis for the learning activities.</li>
<li>Adults are most interested in learning subjects that have immediate relevance and impact to their job or personal life.</li>
<li>Adult learning is problem-centered rather than content-oriented.<br>
<sub><a href="https://elearningindustry.com/the-adult-learning-theory-andragogy-of-malcolm-knowles">The Adult Learning Theory - Andragogy - of Malcolm Knowles</a></sub></li>
</ol>
<hr>
<p>It is the last two principles that directly apply to how valuable PBL is for adults. By focusing exclusively on learning concepts and building competencies on a project has immediate relevance to their ability to quickly integrate with a team in their first job as a software developer.</p>
<p>Also, project work constantly feeds the learner novel problems to solve <em>(i.e features to implement)</em>, and allows the learner to tap into an existing set of life experience that can be applied to the project, and shared with teammates.</p>
<p>Since we break the entire cohort of learners down into smaller teams of 3-5 people on a weekly basis, or when working on long-term and complex projects, we ensure a few things as they work on their individual or group projects.</p>
<ol>
<li>Psychological safety amongst the learners develops quickly.</li>
<li>Each learner has a consistent group of people to explore concepts with and never are left isolated and lost.</li>
<li>Instructors, as coaches, have the ability to learn the individual strengths of each teammate and can enable higher collaboration and more valuable guidance.</li>
</ol>
<h2 id="collaboration">Collaboration</h2>
<p>Another kind of project-based work that learners take part in is group projects. Group projects are different than the other project work they take part in because they are all working as a professional team to build a large scale project together. The core course projects must be built by each learner individually, even though they share ideas and problem-solve together.</p>
<p>Group project involve true teamwork, mirroring the collaborative nature of real-world problem solving. Students must communicate, negotiate, and manage conflicts, which not only aids in the learning process but also helps in developing interpersonal skills vital for the workplace.</p>
<p>Also, learners must gain a level of comfort with the workflow of building features separately and then merging it all together using Git and Github. Group projects solidify this for our learners. I am confident that, when they are hired as professionals, they will integrate immediately into an existing team.</p>
<p>While the final project is important, PBL emphasizes the full richness of the process of learning. Reflection on the project development process, decision-making steps, and the effectiveness of solutions is as important as the project outcome itself.</p>
<h2 id="engage">Engage</h2>
<p>I would love to hear from you about the importance of having a learning experience built around the development of projects to develop core communication and teamwork skills.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Senior/Staff Engineer Competencies]]></title><description><![CDATA[<div class="kg-card-markdown"><p>This article is largely for myself, but if you stumble upon this during your odyssey of navigating the World Wide Web, please enjoy. I spent 5 months <em>(October 2023 through February 2024)</em> scouring dozens of posted job levels for technical teammates. I also included my own opinions and observations in</p></div>]]></description><link>https://www.stevebrownlee.com/senior-staff-engineer-competencies/</link><guid isPermaLink="false">6685e22d8ecff66aeb892d45</guid><dc:creator><![CDATA[Steve Brownlee]]></dc:creator><pubDate>Thu, 29 Aug 2024 02:22:13 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>This article is largely for myself, but if you stumble upon this during your odyssey of navigating the World Wide Web, please enjoy. I spent 5 months <em>(October 2023 through February 2024)</em> scouring dozens of posted job levels for technical teammates. I also included my own opinions and observations in the descriptions below.</p>
<p>If you, like me, have discovered that the titled of <em>Senior</em> and <em>Staff</em> have largely lost any real meaning for software developers, I earnestly hope that these simple tables provide some insight and guidance for you.</p>
<h3 id="seniorsoftwareengineercompetencies">Senior Software Engineer Competencies</h3>
<table>
<thead>
<tr>
<th>Competency</th>
<th>Skills</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Technical Expertise</strong></td>
<td>Coding, debugging, code quality, technical trade-offs</td>
<td>Demonstrates high-level proficiency in programming languages and frameworks, regularly writes and reviews code, makes decisions on technical trade-offs, and understands system security and performance implications.</td>
</tr>
<tr>
<td><strong>Problem Solving</strong></td>
<td>Debugging, critical thinking, technical decision-making</td>
<td>Regularly identifies, analyzes, and resolves complex technical issues, prioritizes technical debt management, and makes pragmatic decisions on when to focus on essential features versus additional refinements.</td>
</tr>
<tr>
<td><strong>System Design</strong></td>
<td>Architecture design, system integration, performance optimization</td>
<td>Designs resilient and scalable software architectures, considers the overall technical direction of the team or department, and integrates multiple technical components efficiently.</td>
</tr>
<tr>
<td><strong>Leadership and Mentorship</strong></td>
<td>Team management, mentoring, technical guidance</td>
<td>Leads technical projects, mentors junior engineers, facilitates technical discussions, and takes ownership of complex projects. Ensures team adherence to best practices and fosters an environment of continuous learning and improvement.</td>
</tr>
<tr>
<td><strong>Communication</strong></td>
<td>Technical writing, stakeholder communication, documentation</td>
<td>Clearly communicates technical concepts to various audiences, documents complex systems and solutions, runs effective meetings, and participates in the hiring process by conducting interviews and reviewing candidates.</td>
</tr>
<tr>
<td><strong>Collaboration</strong></td>
<td>Teamwork, cross-functional communication, feedback facilitation</td>
<td>Collaborates across teams to solve problems, seeks input from other teams, and fosters a culture of open communication and productive discussions. Actively participates in team rituals and ensures clear communication of project statuses and technical challenges.</td>
</tr>
<tr>
<td><strong>Delivery and Execution</strong></td>
<td>Project management, task prioritization, agile methodologies</td>
<td>Prioritizes technical work, breaks down complex tasks into manageable user stories, ensures timely delivery of projects, and continuously improves delivery processes. Moves blockers and provides clear status updates to stakeholders and team leads.</td>
</tr>
<tr>
<td><strong>Continuous Learning</strong></td>
<td>Curiosity, adaptability, skill development</td>
<td>Stays updated with the latest industry trends and technologies, participates in continuous learning through courses and certifications, and applies new knowledge to improve team and personal performance. Encourages a learning culture within the team by sharing knowledge and best practices.</td>
</tr>
<tr>
<td><strong>Decision Making</strong></td>
<td>Technical trade-offs, risk assessment, strategic thinking</td>
<td>Evaluates technical and business trade-offs, makes informed decisions considering both short-term and long-term impacts, and articulates the rationale behind decisions. Balances innovation with pragmatic solutions to meet project goals efficiently.</td>
</tr>
<tr>
<td><strong>Innovation</strong></td>
<td>Creativity, strategic vision, forward-thinking</td>
<td>Drives innovation by exploring new technologies and methodologies, proposes creative solutions to complex problems, and aligns technical direction with overall business goals. Encourages team members to think outside the box and experiment with new approaches to enhance product and process improvements.</td>
</tr>
</tbody>
</table>
<h3 id="staffsoftwareengineercompetencies">Staff Software Engineer Competencies</h3>
<table>
<thead>
<tr>
<th>Competency</th>
<th>Skills</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Technical Expertise</strong></td>
<td>Advanced coding, debugging, architecture design, scalability</td>
<td>Demonstrates expert-level proficiency in multiple programming languages and frameworks, designs complex systems, ensures high code quality, and makes strategic technical decisions.</td>
</tr>
<tr>
<td><strong>Strategic Problem Solving</strong></td>
<td>Advanced debugging, architectural problem-solving, system optimization</td>
<td>Solves high-impact and complex technical challenges, optimizes system performance, and balances short-term and long-term technical strategies.</td>
</tr>
<tr>
<td><strong>Architectural Vision</strong></td>
<td>Enterprise architecture, large-scale system integration, technology strategy</td>
<td>Develops and implements a comprehensive technical vision that aligns with business goals, designs large-scale systems, and ensures alignment with organizational strategy.</td>
</tr>
<tr>
<td><strong>Leadership and Strategic Guidance</strong></td>
<td>Organizational leadership, mentorship, cross-team strategy</td>
<td>Provides strategic leadership, mentors senior and junior engineers, and guides cross-team initiatives. Plays a crucial role in setting the technical direction for the organization and ensuring the alignment of technical projects with business objectives.</td>
</tr>
<tr>
<td><strong>Advanced Communication</strong></td>
<td>Executive communication, technical evangelism, documentation</td>
<td>Communicates complex technical concepts to executive leadership, stakeholders, and technical teams, evangelizes new technologies and methodologies, and ensures comprehensive documentation of architectural decisions.</td>
</tr>
<tr>
<td><strong>Cross-Functional Collaboration</strong></td>
<td>Inter-departmental communication, strategic partnerships, consensus building</td>
<td>Facilitates collaboration across departments, builds strategic partnerships, and drives consensus on technical and business decisions. Actively participates in strategic planning and cross-functional projects to align technical and business objectives.</td>
</tr>
<tr>
<td><strong>Execution Excellence</strong></td>
<td>Advanced project management, strategic prioritization, agile leadership</td>
<td>Leads the execution of high-impact projects, prioritizes initiatives strategically, and implements best practices in project management and agile methodologies. Ensures that technical projects are aligned with business goals and delivered on time and within budget.</td>
</tr>
<tr>
<td><strong>Continuous Innovation</strong></td>
<td>Emerging technology adoption, process improvement, innovation strategy</td>
<td>Continuously explores and adopts emerging technologies, drives process improvements, and develops strategies for innovation. Fosters a culture of innovation within the organization by encouraging experimentation and the adoption of cutting-edge technologies and methodologies.</td>
</tr>
<tr>
<td><strong>Strategic Decision Making</strong></td>
<td>High-stakes technical decisions, risk management, long-term planning</td>
<td>Makes high-stakes technical decisions, manages technical risks, and develops long-term strategic plans that align with business goals. Evaluates the impact of technical decisions on the organization and ensures that they support the overall business strategy.</td>
</tr>
<tr>
<td><strong>Visionary Leadership</strong></td>
<td>Vision setting, strategic influence, organizational impact</td>
<td>Sets a compelling technical vision for the organization, influences strategic technical and business decisions, and drives initiatives that have a significant impact on the organization’s success. Provides visionary leadership that inspires and motivates technical teams to achieve ambitious goals.</td>
</tr>
</tbody>
</table>
<pre><code></code></pre>
</div>]]></content:encoded></item><item><title><![CDATA[Pioneering Education Strategies in Software Developer Bootcamps: Self-Directed Learning]]></title><description><![CDATA[Self directed learning develops critical thinking and problem-solving skills, as learners must obtain and apply knowledge to solve practical challenges.]]></description><link>https://www.stevebrownlee.com/self-directed-learning/</link><guid isPermaLink="false">654b10698ecff66aeb892d27</guid><dc:creator><![CDATA[Steve Brownlee]]></dc:creator><pubDate>Sun, 25 Feb 2024 04:54:56 GMT</pubDate><media:content url="https://www.stevebrownlee.com/content/images/2024/02/self-directed.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://www.stevebrownlee.com/content/images/2024/02/self-directed.png" alt="Pioneering Education Strategies in Software Developer Bootcamps: Self-Directed Learning"><p>This article is part of the <strong>Follow the Science</strong> series where I share our team's journey in developing a learning experience based on modern cognitive science, learning science, and educational psychology.</p>
<h2 id="introduction">Introduction</h2>
<p>In the evolving landscape of education, particularly within the realm of software development, the shift towards self-directed learning paradigms represents a significant departure from traditional instructional methodologies. We adopt this approach in our learning experience and place the onus of learning on the students, providing them with the resources and the autonomy to navigate their educational journey within a flexible framework.</p>
<p>This model not only facilitates a personalized learning experience but also mirrors the demands and autonomy of professional life, preparing students for the realities of the software development industry.</p>
<h2 id="theoreticalfoundationsofselfdirectedlearning">Theoretical Foundations of Self-Directed Learning</h2>
<p>Self-directed learning (SDL) is grounded in adult learning theory, particularly andragogy, which posits that adults learn differently from children. Malcolm Knowles, a pioneer in adult learning theory, suggests that adults are intrinsically motivated and self-directed (Knowles, 1975). They bring life experiences and knowledge to their learning experiences, which they want to be self-directed and relevant to their goals (Knowles, 1984).</p>
<p>Moreover, SDL aligns with the constructivist theories of learning, where knowledge is constructed rather than transmitted. Jean Piaget and Lev Vygotsky, both seminal figures in cognitive development theory, have outlined the importance of active engagement and social interaction in learning, which are key components of self-directed learning environments (Piaget, 1954; Vygotsky, 1978).</p>
<h2 id="benefitsofselfdirectedlearningforadults">Benefits of Self-Directed Learning for Adults</h2>
<h3 id="enhancedlearningoutcomes">Enhanced Learning Outcomes</h3>
<p>Self-directed learning (SDL) tailors the educational process to the individual's learning style, pace, and interests, leading to enhanced learning outcomes. This customization makes learning more relevant and engaging for the adult learner, thereby increasing motivation and the likelihood of retaining information. When learners control their educational journey, they are more likely to delve deeper into topics of interest, leading to a profound understanding of the subject matter. This depth of understanding is crucial in fields like software development, where the application of knowledge to real-world problems is key.</p>
<p>Research indicates that SDL can lead to deeper understanding and retention of material. As learners tackle subjects like Vanilla JavaScript and React at their own pace, they engage more deeply with the content, applying it to practical projects that consolidate their knowledge (Garrison, 1997).</p>
<h3 id="developmentofcriticalthinkingandproblemsolvingskills">Development of Critical Thinking and Problem-Solving Skills</h3>
<p>SDL experiences challenge learners to identify their learning needs, find resources to meet those needs, and apply the knowledge gained to solve complex problems. This process naturally develops critical thinking and problem-solving skills, as learners must evaluate the credibility of sources, synthesize information from various inputs, and apply theoretical knowledge to practical challenges.</p>
<p>Moreover, these skills are transferable across career paths and life situations, equipping learners with the ability to navigate uncertainty and complexity in professional and personal contexts.</p>
<p>The freedom to navigate challenges independently fosters critical thinking and enhances problem-solving skills, qualities that are invaluable in software development (Brookfield, 1986).</p>
<h3 id="increasedmotivationandsatisfaction">Increased Motivation and Satisfaction</h3>
<p>The autonomy afforded by SDL enhances intrinsic motivation, as learners feel their educational journey is personally meaningful and directly aligned with their goals. This sense of ownership over one’s learning process increases satisfaction and commitment, making learners more likely to persist in their studies and pursue further education.</p>
<p>The achievement of learning milestones that learners have set for themselves can be particularly rewarding, reinforcing their motivation to continue learning.</p>
<p>SDL allows learners to pursue topics that interest them within the curriculum, which can increase intrinsic motivation and satisfaction with the learning process (Deci &amp; Ryan, 1985).</p>
<h3 id="preparationforlifelonglearning">Preparation for Lifelong Learning</h3>
<p>In today's rapidly changing world, the ability to learn continuously is a critical skill. SDL encourages the development of metacognitive skills, such as self-awareness and self-assessment, which are foundational for lifelong learning. Adults engaged in SDL are better prepared to adapt to new information, technologies, and career paths because they have learned how to learn. They can independently seek out new knowledge and skills, making them resilient in the face of change.</p>
<p>By engaging in SDL, adults cultivate a proactive approach to education, where learning is seen not as a task to be completed but as an ongoing process. This mindset is essential for personal and professional development in a world where the only constant is change. Lifelong learners are more adaptable, more likely to embrace new opportunities, and better equipped to navigate the complexities of modern life and work environments.</p>
<p>The skills developed through SDL, such as time management, identifying learning needs, and seeking resources, are crucial for lifelong learning, enabling individuals to adapt to new technologies and methodologies over the course of their careers (Candy, 1991).</p>
<h2 id="applicationinourprogram">Application in Our Program</h2>
<p>Our innovative software development bootcamp is meticulously designed to champion the principles of self-directed learning (SDL), a strategy that not only respects the autonomy of adult learners but also prepares them for the dynamic demands of the tech industry. The SDL approach is deeply embedded in every facet of our learning model, from the organization of course materials on GitHub to the structuring of the curriculum and the learner-instructor  dynamics.</p>
<h3 id="contentdeliveryandstructure">Content Delivery and Structure</h3>
<p>We present the course content through GitHub, breaking it down into &quot;books&quot; and &quot;chapters&quot; that progressively build upon one another. This structure enables learners to navigate through the material at a pace that suits them best, fostering a sense of independence right from the outset. The only fixed time guidance within the first three months is the expectation to complete the Vanilla JavaScript material within eight weeks, ensuring all participants are ready to embark on at least two weeks of focused React learning before moving onto their first capstone project.</p>
<p>This phased approach allows learners to gradually enhance their skills, with each book designed to incrementally increase their competency in a way that mirrors real-world software development progression. By not imposing strict deadlines other than the three-month capstone project and the six-month graduation mark, we empower our learners to take full ownership of their educational journey.</p>
<h3 id="learnerresponsibilitiesandengagement">Learner Responsibilities and Engagement</h3>
<p>In our learning experience, the learners are entrusted with significant responsibility. They are expected to effectively manage their time, proactively request help, engage in daily vocabulary practice with their peers, and participate in instructor-led behavior modeling sessions. This framework encourages learners to develop essential soft skills, including time management, communication, and collaboration, which are as critical as technical proficiency in the software development field.</p>
<p>Unlike traditional educational models, our program eschews assigned homework and rigid project deadlines for regular work, placing the emphasis on learning through doing. This method not only enhances engagement and retention but also respects the individual learning processes of adult learners, who may have varying commitments and learning speeds.</p>
<h3 id="instructorroleandlearnersupport">Instructor Role and Learner Support</h3>
<p>Instructors in our program act more as mentors than traditional instructors. Their primary role is to oversee the learners' progress, offering support and guidance rather than direct instruction. This mentorship model is crucial for SDL, as it provides learners with a safety net when they encounter challenges, ensuring that while the learning journey is self-directed, it is not solitary.</p>
<p>Regular meetings at the end of each book of material are the touchpoints where instructors ensure that learners have adequately grasped the concepts and vocabulary necessary for technical proficiency and success in technical interviews. These interactions are among the few structured elements of our program, designed to validate the learner’s progress and readiness to move forward.</p>
<h3 id="optionalinteractionsandpeercollaboration">Optional Interactions and Peer Collaboration</h3>
<p>Crucially, aside from these scheduled check-ins, all other interactions with instructors are optional, requiring learners to be proactive in seeking out the assistance and guidance they need. This structure mimics the professional environment where initiative and self-motivation are prized, preparing learners not just technically but also mentally for their future careers.</p>
<p>The learner experience also leverages the power of peer learning, encouraging learners to collaborate and support each other's growth. This collaborative aspect of SDL not only enriches the learning experience but also builds a community of practice that can extend beyond the bootcamp into professional networks.</p>
<h2 id="references">References</h2>
<ul>
<li>Knowles, M. S. (1975). Self-Directed Learning. Chicago: Follett.</li>
<li>Knowles, M. S. (1984). Andragogy in Action. San Francisco: Jossey-Bass.</li>
<li>Piaget, J. (1954). The Construction of Reality in the Child. New York: Basic Books.</li>
<li>Vygotsky, L. (1978). Mind in Society: The Development of Higher Psychological Processes. Cambridge, MA: Harvard University Press.</li>
<li>Garrison, D. R. (1997). Self-Directed Learning: Toward a Comprehensive Model. Adult Education Quarterly, 48(1), 18-33.</li>
<li>Brookfield, S. D. (1986). Understanding and Facilitating Adult Learning. San Francisco: Jossey-Bass.</li>
<li>Deci, E. L., &amp; Ryan, R. M. (1985). Intrinsic Motivation and Self-Determination in Human Behavior. New York: Plenum.</li>
<li>Candy, P. C. (1991). Self-Direction for Lifelong Learning. San Francisco: Jossey-Bass.</li>
</ul>
</div>]]></content:encoded></item><item><title><![CDATA[GenAI Stole My Work]]></title><description><![CDATA[It was over-confident right from the get go. I couldn't wait to rub its smug face in how much I could do as a human that it couldn't.]]></description><link>https://www.stevebrownlee.com/genai-stole-my-work/</link><guid isPermaLink="false">65c6eb838ecff66aeb892d3d</guid><dc:creator><![CDATA[Steve Brownlee]]></dc:creator><pubDate>Sat, 10 Feb 2024 18:15:29 GMT</pubDate><media:content url="https://www.stevebrownlee.com/content/images/2024/02/thief.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://www.stevebrownlee.com/content/images/2024/02/thief.png" alt="GenAI Stole My Work"><p>I maintain a bespoke learning management platform application that I built for my team to track all kinds of student data. This week, I finally decided I wanted to tackle the slowest request in the entire application - students by cohort. I knew it would be a challenge to take all of the individual ORM statements I have written over the past 2 years and consolidate them into a speedier process. I was planning on spending about a week to analyze, tinker, refine and deploy a solution.</p>
<p>GenAI beat me to it.</p>
<p>It stole all that time and allowed me to do the entire process in about 10 minutes. Here's the tale about how it was able to steal my work from me.</p>
<h2 id="datacontext">Data Context</h2>
<p>First, I learned that this infernal tool can ingest the DBML for my entire database as context and understand how the structure and relationships work. Here's a screenshot of my database. It's certainly not a large database, but 38 tables can challenge the most structured mind when trying to get data that spans 10 of them, and also requires conditions, grouping, and aggregate functions.</p>
<p><img src="https://www.stevebrownlee.com/content/images/2024/02/learnops.png" alt="GenAI Stole My Work"></p>
<p>Since I know that it can parse DBML and generate high quality SQL statement from it, I decided to give this bugaboo the opportunity to fail. There was no chance that it could work at this level of complexity. I was sure of it.</p>
<blockquote>
<p>I am providing the DBML for my API project below. I need you to take on the role of a business analyst and an expert SQL developer to help me generate SQL statements for new features for the project, and optimizing existing queries.</p>
<p>```dmbl<br>
{ all my DBML here }<br>
```</p>
</blockquote>
<p>It was over-confident right from the get go. I couldn't wait to rub its smug face in how much I could do as a human that it couldn't.</p>
<blockquote>
<p>Based on your DBML for the API project, I will help generate SQL statements for new features you might be considering and making existing queries more efficient.</p>
</blockquote>
<p>Yeah, we'll see.</p>
<h2 id="slowdjangoserialization">Slow Django Serialization</h2>
<p>Again, my most egregious crime in this app is the slow build-up of more and more data being added to the information to be sent as JSON about the students in a cohort.</p>
<p>At first, it was just what project was being worked on. Then it was if an assessment was being worked on. Then weighted learning scores, assessment status, capstone submission, capstone submission statues, on and on and on. Finally, after all those additions, the HTTP request was taking over 2 full seconds to complete - unacceptable.</p>
<p>Now it was time to show GenAI how much it sucks and it will never replace humans. It's only for losers who don't know how to code in the first place. I copy-pastad my entire Django model, which has 6 methods on it used by the Serializer for producing a response. I asked it to produce a single SQL statment that would replace all of the separate ORM statements.</p>
<p>Below is an abbreviated version of the model. An experienced developer will immediately notice how much of a performance hit these will incur when run separately when used by a serializer build the JSON.</p>
<p>Time to break GenAI. Below is my prompt for ChatGPT, and I knew that I would get <strong>complete garbage</strong> as a response, and with further prompting, I <em>might</em> get something that could save me a little bit of time.</p>
<h2 id="thebigprompt">The Big Prompt</h2>
<blockquote>
<p>Here is a Django model based on the DBML above. Currently there are 6 methods - book, assessment_status, proposals, score, assessment_overview, and current_cohort - that are all used by a serializer to produce a JSON response with all of this information about a student. Because all of these execute separately, the operation can take over 2 seconds to complete. I want all of these combined into either a single Django ORM statement, or the full SQL in order to create a database function.</p>
</blockquote>
<pre><code class="language-py">class NssUser(models.Model):
    &quot;&quot;&quot;Model for NSS-specific user information beyond Django user&quot;&quot;&quot;

    @property
    def book(self):
        student_project = StudentProject.objects.filter(student=self).last()
        assigned_cohort = self.assigned_cohorts.order_by(&quot;-id&quot;).last()

        if student_project is None:
            cohort_course = CohortCourse.objects.get(cohort=assigned_cohort.cohort, index=0)
            project = Project.objects.get(
                book__course=cohort_course.course, book__index=0, index=0)

        ...
        
    @property
    def assessment_status(self):
        try:
            student_assessment = self.assessments.last()
            if student_assessment.assessment.book.id != self.book[&quot;id&quot;]:
                return 0

            status = student_assessment.status.status
        ...
        
    @property
    def proposals(self):
        try:
            lastest_status = CapstoneTimeline.objects.filter(capstone=OuterRef(&quot;pk&quot;)).order_by(&quot;-pk&quot;)

            proposals = self.capstones.annotate(
                course_name=F(&quot;course__name&quot;),
                current_status_id=Subquery(
                    lastest_status.values('status__id')[:1]
                ),
                current_status=Subquery(
                    lastest_status.values('status__status')[:1])
                )
                .values(
                    'id', 'current_status', 
                    'course_name', 'proposal_url', 
                    'current_status_id'
                )
        ...
        
    @property
    def score(self):
        scores = self.learning_records.filter(achieved=True) \
            .annotate(total_score=Sum(&quot;weight__weight&quot;)) \
            .values_list('total_score', flat=True)
        total = sum(list(scores))

        core_skill_records = list(
            self.core_skills.values_list('level', flat=True))
        ...

    @property
    def assessment_overview(self):
        for assessment in self.assessments.all().order_by(&quot;-assessment__book__index&quot;):
            assessment_list.append({
                &quot;id&quot;: assessment.id,
                &quot;name&quot;: assessment.assessment.name,
                &quot;status&quot;: assessment.status.status,
                &quot;book&quot;: assessment.assessment.assigned_book,
                &quot;reviewed_by&quot;: assessment.instructor.user.first_name
            })
        ...

    @property
    def current_cohort(self):
        assignment = self.assigned_cohorts.order_by(&quot;-id&quot;).last()

        return {
            &quot;name&quot;: assignment.cohort.name,
            &quot;id&quot;: assignment.cohort.id,
            &quot;start&quot;: assignment.cohort.start_date,
            &quot;end&quot;: assignment.cohort.end_date,
            &quot;courses&quot;: assignment.cohort.courses
                .order_by('index')
                .values('course__name', 'course__id', 'active'),
            }
</code></pre>
<h2 id="chatgptsdisgustinguselessresponse">ChatGPT's Disgusting, Useless Response</h2>
<blockquote>
<p>Combining the operations of the six methods (book, assessment_status, proposals, score, assessment_overview, and current_cohort) into a single Django ORM statement or SQL query to fetch all required information in one go is quite complex and challenging. This is mainly due to the diverse nature of the data these methods retrieve, which spans across different tables with various relationships.</p>
</blockquote>
<p><em><strong>Aha!! Gotcha!!</strong></em></p>
<p>As soon as I read that, I knew I'd won and proven my superiority. This tool is already admitting that it can't do it. One point for humans.</p>
<p><img src="https://www.stevebrownlee.com/content/images/2024/02/uthenbryt_A_human_warrior_like_Aragorn_standing_victorious_over_0347fff6-bcce-4cf9-be04-3eb699aee009.png" alt="GenAI Stole My Work"></p>
<p>Wait.... what? Are there yet more foes that need to be vanquished?</p>
<blockquote>
<p>However, I can outline an approach to create a more efficient SQL query or a set of queries that could potentially reduce the total execution time. The goal here would be to minimize the number of database hits by fetching related data in bulk and then processing it in Python.</p>
<h3 id="recommendationdatabasefunctionorstoredprocedure">Recommendation: Database Function or Stored Procedure:</h3>
<p>Given the complexity, consider implementing a database function or stored procedure that encapsulates this logic within the database. This allows you to maintain complex logic in one place and potentially improve performance by utilizing database-specific optimizations.</p>
<p>After creating the stored procedure, you can call it from Django using a raw SQL query:</p>
</blockquote>
<pre><code class="language-py">from django.db import connection

def get_student_details(user_id):
    with connection.cursor() as cursor:
        cursor.execute(&quot;CALL get_student_details(%s);&quot;, [user_id])
        result = cursor.fetchone()  # or fetchall() based on your needs
    return result
</code></pre>
<blockquote>
<h3 id="postgresqlfunctionforstudentdetails">PostgreSQL Function for Student Details</h3>
<p>This PostgreSQL function aims to provide a comprehensive overview of a student's details, including their latest book project, current cohort, assessment status, and a simplified score calculation. Given the varied nature of the data, some simplifications and assumptions are made for the sake of brevity and clarity.</p>
</blockquote>
<pre><code class="language-sql">-- I have removed much of the SQL, also for the 
-- sake of brevity of this blog post

CREATE OR REPLACE FUNCTION get_student_details(student_user_id INT)
RETURNS TABLE (
    full_name TEXT,
    latest_project_name TEXT,
    latest_book_name TEXT,
    ...
) AS $$
BEGIN
    RETURN QUERY
    WITH student_info AS (
        SELECT
            au.id,
            au.first_name || ' ' || au.last_name AS full_name
        FROM auth_user au
        WHERE au.id = student_user_id
    ),
    latest_project AS (
        SELECT
            sp.student_id,
            p.name AS project_name,
            p.id as project_id,
            ...
        FROM &quot;LearningAPI_studentproject&quot; sp
        ...
    ),
    current_cohort AS (
        SELECT
            nuc.nss_user_id,
            c.name AS cohort_name,
        ...
    ),
    assessment_status_agg AS (
        SELECT
            sa.student_id,
            sa.status_id,
            ...
        FROM &quot;LearningAPI_studentassessment&quot; sa
        ...
    ),
    score_calc AS (
        SELECT
            lr.student_id,
            SUM(lw.weight) AS total_score
        FROM &quot;LearningAPI_learningrecord&quot; lr
        JOIN ...
    )
    SELECT
        si.full_name,
        ...
        lp.book_id AS latest_book_id,
        coalesce(asa.status, 'Not Started') AS assessment_status,
        coalesce(sc.total_score, 0) AS total_score
    FROM student_info si
    LEFT JOIN latest_project lp ON si.id = lp.student_id
    ...;
END; $$
LANGUAGE plpgsql;
</code></pre>
<h1 id="">🤔</h1>
<h2 id="stunnedsilence">Stunned Silence</h2>
<p>Ok, so I copy that into my SQL file and execute it. Dubious 🤨, but hopeful because my initial scan of the query had me feeling that it looked... kinda right.</p>
<p>I ran it for one student. It was right.</p>
<p>I ran it for another student in a different project. It was right.</p>
<p>I ran it for a student that wasn't working on an assessment. It was right.</p>
<p>I ran it for a student that <em>was</em> working on an assessment. It was right.</p>
<p>I ran it for a student that hadn't submitted a proposal. It was right.</p>
<p>I ran it for a student that had a capstone proposal and it was currently being reviewed. It was right.</p>
<p>I'm not going to lie. I absolutely could have completed all of this work myself using Google and my own knowledge. It also would have taken me a week, multiple dozens of Google searches, myriad mistakes, and multiple versions until I got a working version.</p>
<p>One thing that it missed is that I wanted to get this information for every student in a cohort, so the next step is to modify it for that data. I prompted it to update the query, but it didn't do that great of a job, and I needed to take over and finish it up myself.</p>
<h2 id="idlikeasecondopinion">I'd Like A Second Opinion</h2>
<p>Ok, so ChatGPT did give it a valiant shot and saved me a considerable amount of time, but now my curiosity was piqued. I decided to shop my problem around to other interested parties. I'd heard good things of <a href="https://claude.ai/">Claude</a> so I headed down the highway to that shop.</p>
<p>I fed it the <em>exact same prompts</em> with no modifications and I was pleasantly surprised to see that it took a completely different approach. First, it produced an ORM statement that it believed met the requirements. ChatGPT didn't even try.</p>
<h3 id="theormedition">The ORM Edition</h3>
<pre><code class="language-py">from django.db.models import OuterRef, Subquery, F, Sum

class NssUser(models.Model):

    @property
    def combined_data(self):
        subquery = StudentProject.objects.filter(student=OuterRef('pk')).order_by('-date_created')
        
        return self.prefetch_related('assessments', 'assessments__status', 'capstones', 'learning_records', 'core_skills', 'assigned_cohorts').annotate(
            latest_student_project = Subquery(subquery.values('project__book__id')[:1]),
            latest_student_project_name = Subquery(subquery.values('project__book__name')[:1]),
            latest_student_project_index = Subquery(subquery.values('project__book__index')[:1]),
            latest_student_project_date = Subquery(subquery.values('date_created')[:1]),
            latest_assessment = Subquery(self.assessments.filter(assessment__book=OuterRef('latest_student_project')).order_by('-date_created').values('status__status')[:1]),
            learning_record_score = Subquery(self.learning_records.filter(achieved=True).annotate(total=Sum('weight__weight')).values('total')[:1], output_field=models.IntegerField()),
            current_cohort = Subquery(self.assigned_cohorts.order_by('-id').values('cohort__name')[:1])
        ).values(
            'latest_student_project', 
            'latest_student_project_name',
            'latest_assessment',
            'learning_record_score',
            'current_cohort',
            # add other needed fields here
        )
</code></pre>
<h3 id="theleftjoinedition">The LEFT JOIN Edition</h3>
<p>Now that was a great start, but it didn't stop there. It also generated SQL, but instead of using CTEs it just <code>LEFT JOIN</code>ed the heck out it.</p>
<pre><code class="language-sql">SELECT 
    nu.user_id,
    nu.first_name || ' ' || nu.last_name AS user_name,
    sp.project_id AS latest_project_id,
    p.name AS latest_project_name,        
    sa.status AS latest_assessment_status,
    lr.total_score AS learning_record_score,
    c.name AS current_cohort
FROM LearningAPI_nssuser nu
JOIN LearningAPI_nssusercohort nc 
    ON nc.nss_user_id = nu.id
JOIN LearningAPI_cohort c 
    ON c.id = nc.cohort_id
LEFT JOIN LearningAPI_studentproject sp 
    ON sp.student_id = nu.id AND sp.date_created = (
        SELECT MAX(date_created) 
        FROM LearningAPI_studentproject 
        WHERE student_id = nu.id
    )
LEFT JOIN LearningAPI_project p 
    ON p.id = sp.project_id
LEFT JOIN LearningAPI_studentassessment sa 
    ON sa.student_id = nu.id AND sa.date_created = (
        SELECT MAX(date_created) 
        FROM LearningAPI_studentassessment 
        WHERE student_id = nu.id
    )
LEFT JOIN (
    SELECT lre.student_id, SUM(lw.weight) AS total_score
    FROM LearningAPI_learningrecord lr
    JOIN LearningAPI_learningrecordentry lre ON lre.record_id = lr.id
    JOIN LearningAPI_learningweight lw ON lw.id = lr.weight_id
    WHERE lr.achieved = true
    GROUP BY lre.student_id
) lr ON lr.student_id = nu.id
WHERE nc.cohort_id = cohort_id;
</code></pre>
<p>Again, that gets me about 90% of where I want to be and saved a lot of  mistakes and me stupidly typing in syntax errors and yelling at myself. After tinkering with it for about 10 minutes, I got this version working the way I wanted.</p>
<p>So after all of this, I have two versions of a Postgres function that I can use in my app. Now I can take on the task of actually evaluating their performance in my actual application and make a judgement call on which one to use.</p>
<h2 id="timetoaskmycopilot">Time to Ask My Copilot</h2>
<p>Until I originally published this article, I had never used Github Copilot.</p>
<h4 id="updateonmarch12024">Update on March 1, 2024</h4>
<p>I made the assumption that since Copilot is an extension for VS Code that it had the capability of navigating my database structure via the Django models that are right there in the project. Based on that assumption, I provide the more concise prompt below.</p>
<blockquote>
<p>Generate a read-only property that uses a direct connection to the database and a SQL statement to get the following information related to NSSUser. The current book the user is assigned to, the status of the current StudentAssessment being worked on (if any), a list of related Capstone rows, the SUM() of the <code>weight</code> field on the LearningRecord rows assigned to the user, all of the information from Cohort and CohortInfo for the most recent cohort the user is assigned to, all of the StudentNote records assigned to the user, and all of the Tag records assigned to the user via the StudentTag model. This is to replace all of the existing methods in this model. The generated code should not utilize any existing method or property.</p>
</blockquote>
<p>The prompt was specific and provided guidance on exactly what I needed. Unfortunately, it did not produce a very accurate SQL statement. I include it below, but also removed chunks of it for brevity's sake. Because I didn't provide the DBML, it also misspelled some of the table names.</p>
<p>Once again the strategy for the SQL statement is very different from either ChatGPT or Claude. This produced more nested subqueries than the other two, and used some different functions.</p>
<pre><code class="language-sql">SELECT
        COALESCE(p.book_id, 0) AS book_id,
        COALESCE(p.name, '') AS book_name,
        COALESCE(a.status, '') AS assessment_status,
        c.id AS cohort_id,
        c.name AS cohort_name,
        ci.client_course_url,
        ci.server_course_url,
        ci.zoom_url,
        c.start_date,
        c.end_date,
        ci.student_organization_url,
        SUM(lr.weight) AS learning_record_weight_sum,
        ARRAY_AGG(DISTINCT sn.id) AS student_note_ids,
        ARRAY_AGG(DISTINCT t.id) AS tag_ids
FROM
        &quot;LearningAPI_nssuser&quot; AS u
        LEFT JOIN (
            -- Subquery
            WHERE sp.date_created = (
                -- Sub subquery
            )
        ) AS p ON u.id = p.student_id
        LEFT JOIN (
            SELECT *
            FROM &quot;LearningAPI_studentassessment&quot; AS sa
            INNER JOIN ...
            WHERE sa.date_created = (
                -- Another sub subquery
            )
        ) AS a ON u.id = a.student_id
        LEFT JOIN (
            -- More sub queries and sub subqueries
        ) AS c ON u.id = c.id
        LEFT JOIN &quot;LearningAPI_learningrecord&quot; AS lr ON u.id = lr.student_id
        LEFT JOIN &quot;LearningAPI_studentnote&quot; AS sn ON u.id = sn.student_id
        LEFT JOIN &quot;LearningAPI_studenttag&quot; AS st ON u.id = st.student_id
        LEFT JOIN &quot;LearningAPI_tag&quot; AS t ON st.tag_id = t.id
WHERE
        u.id = 414
GROUP BY
        u.id, p.book_id, etc...
        ;
</code></pre>
<h2 id="thetruepowerofgenai">The True Power of GenAI</h2>
<p>The point of this article was to demonstrate how ridiculously sophisticated these GenAI tools are, and how much time can be saved by software developers... if they learn how to generate powerful prompts and provide the context the tool needs.</p>
<p>As of right now, I find 100x time more value when I ask it to help me improve my code instead of asking it to generate new code from scratch.This saved me a tremendous amount of very complex, and cognitively challenging work, but it didn't do it <em>for me</em>.</p>
<p>It's not like I was working at my desk and it came up behind me like, <em>&quot;Hey dude, it's Gene. I saw you working on this ticket, but it looked cool so I did it for you. Here's the code.&quot;</em></p>
<p><em>(side note: I didn't like Gene)</em></p>
<ul>
<li>I had to understand the real problem.</li>
<li>I had to know how to prompt a GenAI for valuable responses.</li>
<li>I had to have the DBML for my database generated.</li>
<li>I had to know which model, and which methods on that model were the bad actors.</li>
<li>I had to design a very comprehensive, and specific, prompt that told it exactly what problem needed to be solved.</li>
<li>I had to tell it how I wanted it to act and respond to my queries.</li>
<li>I made sure to verify each solution and provide adjustments 3 times.</li>
</ul>
<p>I feel pity for the low to mid-value developers on the Web that bash GenAI as a hack or a cheat that only losers use.</p>
<p>It's a new tool with a tremendous amount of power, for good or evil. It has some people <em>(like me)</em> thrilled and excited about the benefits that it brings to the world of software development. Some people are curmudgeons and say how much it sucks, or that it's a crutch for bad software developers.</p>
<p>I get it. Coming from a place of fear and anxiety is pretty normal for humans when confronted with something new like this.</p>
<blockquote>
<p>&quot;I learned it {insert some old way} and I turned out just fine! You kids these days want to take the easy way out.&quot;</p>
</blockquote>
<p>To which I always call bullshit. If this tool was available to any of these folks when they were just starting out, it would have been like a miracle and they all would have used it.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Pioneering Education Strategies in Software Developer Bootcamps: The Reflective Coder]]></title><description><![CDATA[<div class="kg-card-markdown"><p>This article is part of the <strong>Follow the Science</strong> series where I share our team's journey in developing a learning experience based on modern cognitive science, learning science, and educational psychology.</p>
<h2 id="introduction">Introduction</h2>
<p>In today's rapidly evolving world, the ability to learn effectively is not just a skill but a necessity,</p></div>]]></description><link>https://www.stevebrownlee.com/follow-the-science-series-3/</link><guid isPermaLink="false">654b0f5e8ecff66aeb892d26</guid><dc:creator><![CDATA[Steve Brownlee]]></dc:creator><pubDate>Fri, 29 Dec 2023 18:53:26 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>This article is part of the <strong>Follow the Science</strong> series where I share our team's journey in developing a learning experience based on modern cognitive science, learning science, and educational psychology.</p>
<h2 id="introduction">Introduction</h2>
<p>In today's rapidly evolving world, the ability to learn effectively is not just a skill but a necessity, especially in fields like software development. Our exploration into the cognitive benefits of reflective learning has unveiled meaningful benefits to our learning experience, reshaping our understanding of how people learn and grow. Reflective learning, a metacognitive task, is not merely about reviewing what one has learned; it's about diving deep into the 'why' and 'how' of our learning processes.</p>
<p>In this article, we'll uncover how reflective learning enhances problem-solving skills and critical thinking in software development, transcending beyond mere pattern recognition to a deeper understanding of concepts. We'll explore the benefits of reflective practices, from enhanced understanding and improved decision-making to increased retention and heightened self-awareness.</p>
<p>Further, we delve into the practical implementation of reflective learning in educational settings, discussing innovative strategies and addressing the challenges faced in integrating these practices. The insights shared here are grounded in our extensive research and hands-on experiences, offering valuable takeaways for educators, learners, and professionals alike.</p>
<h3 id="reflection">Reflection</h3>
<p>Reflection is the cognitive process of thinking critically about one's own learning and experiences. It involves analyzing how one approached a problem, what strategies were used, what was successful, what failed, and how one's understanding of a subject has changed or grown. This metacognitive process is fundamental to deep learning and is a core component of developing problem-solving skills.</p>
<p>Intentional reflection provides many benefits.</p>
<ol>
<li><strong>Enhanced Understanding:</strong> Reflection helps learners understand the deeper principles underlying their actions, leading to a richer understanding of the subject matter.</li>
<li><strong>Critical Thinking:</strong> By reflecting on their experiences, students can develop a more nuanced approach to problem-solving that involves critical thinking and self-questioning.</li>
<li><strong>Better Decision Making:</strong> Regular reflection allows learners to pause and consider their learning journey, which can lead to better decisions about future learning paths and problem-solving approaches.</li>
<li><strong>Increased Retention:</strong> The act of reflecting on learned material can aid in the retention of information by reinforcing the memory trace in the brain. Read more about the benefits of <a href="https://educationblog.oup.com/secondary/science/using-retrieval-to-support-long-term-learning-in-science">Retrieval</a>.</li>
<li><strong>Self-Awareness:</strong> Reflective practices cultivate self-awareness, helping learners recognize their strengths and areas for improvement.</li>
</ol>
<h3 id="implementationofreflection">Implementation of Reflection</h3>
<p>In our learning experience, once the students have completed the projects in the first section, they are asked to reflect on their understanding - and not through writing code. They are asked to reflect on the <strong>why</strong> of the code, or the benefits of specific strategies.</p>
<p>For example, understanding functions is a core learning objective of the first section of the course. Yes, a student must have the ability to use the correct syntax for defining and invoking a function, but they are also asked this.</p>
<blockquote>
<p>Explain why a function that works correctly with one set of arguments might not work with another. How would you go about troubleshooting this?</p>
</blockquote>
<p>This ensures that their focus is not just on <em>&quot;I got it to work&quot;</em>, but rather on <em>&quot;this is why it works and why it might not&quot;</em>. When the focus is just on producing working code, a learner misses the opportunity to deepen problem solving abilities. It also leads a learner down the path of exploring the uncertain, rather than focusing on the certain.</p>
<p>Once each learner has spent time reflecting on their current competencies and comprehension, time is schedule with an instructor to report their observations and the two people can work together to devise a strategy for the learner to fill in any gaps. At that point, the learner has complete ownership of, and accountability for, following that strategy.</p>
<p>Another strategy that we use is deconstruction. There are opportunities for learner to examine an existing project, and then deconstruct it into its individual components and algorithms. One such scenario is covered in the <a href="https://stevebrownlee.com/follow-the-science-problem-solvers/#thegiffygramscenario">Cultivating Problem Solvers</a> article. This requires that the learners reflect on strategies that have been learned, and use analytical thinking to determine which ones were used to build the project.</p>
<h2 id="challengesofreflectivelearning">Challenges of Reflective Learning</h2>
<p>There are challenges that you must be aware of if you plan on integrating reflective practices into your learning experience.</p>
<h3 id="pasttraumas">Past Traumas</h3>
<p>Some learners have such poisonous past experiences where judgement of their abilities leave them unable to open up with a coach and be objective about their understanding. You must be willing to have the patience to slowly build trust with those learners.</p>
<p>You need to constantly acknowledge that being a beginner is difficult, and have the ability to meet the learner where they are without judgement.</p>
<h3 id="timingiseverything">Timing is Everything</h3>
<p>Spacing the opportunity for reflecting on understanding of concepts is a challenge. If a learner spends a significant amount of time and cognitive effort on a large set of objectives, it can be hard for them to reflect on the whole set. If you space them too quickly, then the power of metacognitive task of <a href="https://educationblog.oup.com/secondary/science/using-retrieval-to-support-long-term-learning-in-science">Retrieval</a> is not utilized.</p>
<h3 id="youllmakemistakes">You'll Make Mistakes</h3>
<p>It requires adequate training and experience for a coach/instructor to be able to help a learner be accountable to meeting goals without having the learner feel harshly judged. This can be a challenge for a new coach/teacher/etc.</p>
<p>Take some time to learn about the basics of <a href="https://www.mindtools.com/aqxwcpa/cognitive-load-theory">cognitive load theory</a>, and then read a wonderful overview of how to account for working memroy limits in a learning environment in the <a href="https://journals.sagepub.com/doi/full/10.1177/0963721420922183">Cognitive-Load Theory: Methods to Manage Working Memory Load in the Learning of Complex Tasks<br>
</a> article.</p>
<h2 id="thefutureoflearningreflectionatthecore">The Future of Learning: Reflection at the Core</h2>
<p>By utilizing the power of reflection, education would emphasize not just the acquisition of knowledge but also the process of learning itself. Students would be trained to think about how they think, leading to better problem-solving and analytical skills.</p>
<p>As students reflect on their learning journeys, they become more adept at self-assessment and self-directed learning, skills crucial for lifelong learning - an admirable goal for any educator.</p>
<p>In the coming years, as artificial intelligence grows in adoption, the tools could be used to analyze students' reflective writings and provide personalized feedback or learning recommendations. Education would increasingly tailor to individual learning styles and needs. Reflective practices encourage learners to understand their own learning processes, leading to more personalized and effective learning strategies.</p>
<h2 id="reflectionincognitivescience">Reflection in Cognitive Science</h2>
<p>If you want to learn more about cognitive science research into the power of reflection, here are some articles to investigate.</p>
<p><strong>Schön, Donald A. (1983). <a href="https://www.google.com/books/edition/The_Reflective_Practitioner/ceJIWay4-jgC?hl=en&amp;gbpv=1&amp;dq=The+Reflective+Practitioner:+How+Professionals+Think+in+Action.&amp;printsec=frontcover">&quot;The Reflective Practitioner: How Professionals Think in Action.&quot;</a></strong></p>
<p>Schön's work is seminal in the field of reflective practice. He explores how professionals, particularly in design and management, learn from their experiences in real-time. This book is a foundational text in understanding the role of reflection in professional development.</p>
<p><strong>Mezirow, Jack. (1990). <a href="https://www.google.com/books/edition/Adult_and_Continuing_Education_Teaching/DL-ITGH1io0C?hl=en&amp;gbpv=1&amp;dq=How+Critical+Reflection+triggers+Transformative+Learning&amp;pg=PA199&amp;printsec=frontcover">&quot;How Critical Reflection triggers Transformative Learning.&quot;</a> In J. Mezirow &amp; Associates (Eds.), &quot;Fostering Critical Reflection in Adulthood.&quot;</strong></p>
<p>Mezirow's work on transformative learning emphasizes the role of critical reflection in facilitating significant personal change and learning. This study is especially relevant in adult education.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Pioneering Education Strategies in Software Developer Bootcamps: Cultivating Problem Solvers]]></title><description><![CDATA[This article explores how we integrate core problem-solving skills development into the experience, and how competence in code syntax is viewed as an important, but secondary, skill to learn.]]></description><link>https://www.stevebrownlee.com/follow-the-science-problem-solvers/</link><guid isPermaLink="false">654b09618ecff66aeb892d23</guid><category><![CDATA[learning]]></category><category><![CDATA[software development]]></category><category><![CDATA[cognitive science]]></category><dc:creator><![CDATA[Steve Brownlee]]></dc:creator><pubDate>Wed, 06 Dec 2023 23:30:49 GMT</pubDate><media:content url="https://www.stevebrownlee.com/content/images/2023/11/problem-solving.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://www.stevebrownlee.com/content/images/2023/11/problem-solving.png" alt="Pioneering Education Strategies in Software Developer Bootcamps: Cultivating Problem Solvers"><p>This article is part of the <strong>Follow the Science</strong> series where I share our team's journey in developing a learning experience based on modern cognitive science, learning science, and educational psychology.</p>
<h2 id="introduction">Introduction</h2>
<p>Coding bootcamps are often thought of as intensive coding tutorial sessions where the only focus is on pounding out line after line of code. What if the ability to produce code is simply an emergent behavior of more fundamental skills that must be developed first?</p>
<p>This article explores how we integrate core problem-solving skills development into the experience, and how competence in code syntax is viewed as an important, but secondary, skill to learn.</p>
<h2 id="thegiffygramscenario">The Giffygram Scenario</h2>
<blockquote>
<p>The 2023 team called me into their breakout room around mid-morning of the 3rd day to show me what they had pieced together. I was <strong><em>stunned</em></strong>.</p>
</blockquote>
<p>In 2023, I had a team of developers that had the option to choose from 5 different projects that were designed for them to develop their communication and teamwork skills. One of those projects is called Giffygram. It is a simplified version of a social media platform where people create posts that contain only animated GIF images.</p>
<p>I gave the team an overview of the project and explained that their initial goal was to deconstruct an existing implementation and generate a technical specification that details how it was constructed. The code itself was compressed and uglified so they could not rely on using the source code to build the spec. They had to use their existing understanding of the strategies and concepts, and use all of the other diagnostic tools at their disposal to figure it out.</p>
<p>They had 5 days to deconstruct the project and then build their own implemetation from the spec.</p>
<p>This team took their job seriously. They spent 3 of the 5 days deconstructing the code, documenting how the HTML was structured, the CSS classes used, the payload/response signatures of each HTTP request, and the organization of the modules that had been downloaded to the client. They also built an incredibly accurate sequence diagram that fully articulated the flow of each feature in the application.</p>
<p>It was a testament to how to debug, investigate, and use analytical and algorithmic thinking skills. Truly one of the most impressive efforts that I've ever seen a team put into a group project.</p>
<p>Traditionally, I observe teams spend about 1 to 1.5 days on the deconstruction and problem-solving stage because they are focused on getting to the code writing stage as quickly as possible. They want to get it done rather than understand it.</p>
<p>This leads to the inevitable conclusion of having an incomplete project after 5 days that is rife with errors, and features that are half-implemented or implemented incorrectly. It's all part of being a beginner to learn those lessons the hard way.</p>
<p>The 2023 team called me into their breakout room around mid-morning of the 3rd day to show me what they had pieced together. I was <strong><em>stunned</em></strong>. I know many seasoned pros who could not produce the quality of documentation, depth of analytical and algorithmic thinking, and professional dedication that this team demonstrated to me.</p>
<p>After I made a couple minor corrections to their ERD and documentation, they forged ahead with coding the solution. At that moment, I was so proud that I didn't care at all that they would barely get any of the code written and wouldn't have much to show. After all, they had just over 1.5 days left to develop what is a complex application for beginners.</p>
<p>Imagine the depth of my astonishment when, at the end of the 5th day, they messaged me and said they wanted to demo their completed application.</p>
<p>That's right.</p>
<p>They built the entire thing in one and a half days. A team of beginners who didn't know what a function was just 50 days ago. It was a full stack application that made fetch calls to a JSON API service. It was a single-page application that dynamically rendered components given different states. It had a main feed with the ability to favorite posts, a new post component, a messaging component, a user profile component, with simplistic login/logout capabilities.</p>
<p>It was all done with Vanilla JavaScript. No advanced state-driven component library like React or Vue.</p>
<p>All of that was possible because they followed our advice -</p>
<blockquote>
<p><em>Never try to solve a problem with code. Solve the problem, then code the solution.</em></p>
</blockquote>
<h2 id="thescienceofproblemsolving">The Science of Problem-Solving</h2>
<p>Research in cognitive science suggests that effective problem solvers are not just knowledgeable in their field but also skilled in analytical thinking, algorithmic thinking, and efficient learning. Our strategy encompasses all these aspects to ensure a comprehensive learning experience.</p>
<blockquote>
<p>Advances in technology and changes in necessary workplace skills have made the ability to think critically more important than ever before, yet there is ample evidence that many adults consistently engage in flawed thinking.</p>
<p><sub>&quot;Teaching Critical Thinking for Transfer Across Domains&quot; - Diane Halpern (1998)</sub></p>
</blockquote>
<p>Being able to think analytically and algorithmically are crucial to software developers because they provide value not through their code, but through their ability to solve problems. Code is simply the vehicle by which a solution is delivered.</p>
<p>The good news is that being aware of modern cognitive science about how the human brain learns means that you can craft a learning experience that methodically builds problem-solving skills.</p>
<h2 id="ourmethodology">Our Methodology</h2>
<p>Our experience is crafted around reinforcing core problem-solving skills. It's not about the quantity of code written but the quality of the thought process behind it.</p>
<p>We have discovered over the years that many of our students begin day one with a diminished ability to think critically <em>(i.e. analytically and algorithmically)</em>. The first section of the course introduces them immediately to two tools that help them strengthen the skill.</p>
<ol>
<li><strong>The Debugger</strong> - This allows them to track the data used in the application and understand the signal flow of basic software instructions.</li>
<li><strong>Sequence Diagrams</strong> - This gives them the ability to build a visualization of an algorithm, which is immensely helpful to a beginner.</li>
</ol>
<p>These valuable tools help learners build the foundation for how software works and enables them to design a solution for novel problems. Knowing the syntax for code is not enough. A learner needs to know exactly how the code is designed and executed.</p>
<p>Learners begin by seeing solutions for problems similar to what they will be asked to solve. They learn the basic tools and strategies they will be using professionally. Then they are asked to implement the strategies and tools to solve similar problems.</p>
<p>To help them effectively build these skills in problem solving, we use another strategy called Faded Worked Examples, which will be covered in another article.</p>
<h2 id="problemsolvingprocess">Problem Solving Process</h2>
<p>Here is an overview of the steps involved for a software developer to solve a business problem and deliver an effective solution.</p>
<ol>
<li>Understand the problem</li>
<li>Break down the problem into atomic tasks</li>
<li>Consider solutions to each task</li>
<li>Implement solution for each task</li>
<li>Deliver solution to the problem</li>
</ol>
<p>Because most of our learners begin the program unsure how to methodically solve problems using critical thinking skills, we model the process for them and expertly guide them through each step. We do this via three mechanisms.</p>
<ol>
<li>Project based coursework</li>
<li>Collaborative sessions</li>
<li>Behavior modeling sessions</li>
</ol>
<h3 id="projectbasedcourse">Project Based Course</h3>
<p>Project-based learning will be explored in-depth in a separate article. At a high level, each section of the course focuses on a few core learning objectives, and students build 3 or 4 small-scale projects that are focused on developing the competencies in those objectives.</p>
<p>The first project provides them with a walkthrough of a solution that includes copious explanations, supporting videos they can watch to gain different perspectives, and graphics that help their brains learn through dual modalities. The last project they work on in the section simply provides the requirements and they must develop it completely from the ground up.</p>
<h3 id="collaborationsessions">Collaboration Sessions</h3>
<p>Weekly collaboration sessions are where student teams, usually comprising of 4 or 5 learner, use analytical and algorithmic thinking skills to solve a problem together with an instructor present. The instructor is not involved in building the solution, but rather serves as a coach during the process.</p>
<p>The learners are guided to first understand the problem that is presented for the project. Then, using only English comments, they developer their analytical thinking skills break down the project into the smallest operations possible.</p>
<p>Once the individual tasks have been defined, the learners then use their algorithmic thinking skills to rearrange them in the order in which they should be written. This tends to generate the most discussion, and a bit of coaching from the experienced coach to ask targeted questions about order of operations.</p>
<p>Finally, the students collaboratively start writing the code to implement each step in the algorithm.</p>
<p>Once they write all of the code and fix any remaining syntax errors, each team realizes that the code was obvious and they can get a working solution very quickly. It's the most effective way to demonstrate to beginners that code is the last part of the process. Coming into the program, their instinct is to start coding immediately and then fix it all as it becomes increasing complex and broken.</p>
<p>We give them the confidence to break that instinct and follow a process the valuable professionals follow.</p>
<h3 id="behaviormodeling">Behavior Modeling</h3>
<p>These sessions are where an instructor breaks down a problem, decides on a strategy for a solution, and slowly implements the solution while allowing learners to contribute if they want and answer all questions along the way.</p>
<p>It is a opportunity that students find highly valuable. They can listen to an experienced developer think through a problem, see how tickets are written, absorb more advanced analytical thinking and algorithmic thinking processes, and have some cognitive dots connected as the coach talks through their code implementation.</p>
<p>Ask most beginners and they will tell you that watching an experienced developer go through the process of solving a problem is an invaluable resource.</p>
<h2 id="theresult">The Result</h2>
<p>By taking this approach, one grounded in learning science, successfully develops professionals who are prepared to navigate the modern technological landscape. They are capable, well-rounded problem solvers equipped that can learn efficiently and provide value to their teams and customers.</p>
<p>I encourage educators and learners alike to embrace evidence-based practices. Think about how these insights can reshape your educational endeavors and share your thoughts or questions.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Pioneering Education Strategies in Software Developer Bootcamps: Introduction]]></title><description><![CDATA[In this first article of the "Follow the Science" series, you will learn about the goals of the series and get an overview of the concepts that will be covered.]]></description><link>https://www.stevebrownlee.com/follow-the-science-introduction/</link><guid isPermaLink="false">654b0d3d8ecff66aeb892d25</guid><category><![CDATA[learning]]></category><category><![CDATA[software development]]></category><category><![CDATA[cognitive science]]></category><dc:creator><![CDATA[Steve Brownlee]]></dc:creator><pubDate>Mon, 04 Dec 2023 17:12:23 GMT</pubDate><media:content url="https://www.stevebrownlee.com/content/images/2023/11/light-6161-4d5a-b930-03c31e49c78d.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><h2 id="followthescienceseriesintroduction">Follow the Science Series Introduction</h2>
<img src="https://www.stevebrownlee.com/content/images/2023/11/light-6161-4d5a-b930-03c31e49c78d.png" alt="Pioneering Education Strategies in Software Developer Bootcamps: Introduction"><p>In this first article of the <strong>&quot;Follow the Science&quot;</strong> series, you will learn about the goals of the series and get an overview of the concepts that will be covered.</p>
<p>The goal of this series is to share how we constructed a learning experience based on the results of modern cognitive science, learning science, and educational psychology. Traditional educational strategies were considered suspect unless they were backed by science and proven to be effective.</p>
<p>As an accelerated software development bootcamp, we were free of the constraints of the existing higher education system, and my hopes were to construct an effective, engaging, and hopefully fun learning experience based on science, not dogma.</p>
<h2 id="audience">Audience</h2>
<p>I'm sharing this information in the hopes that it can provide some value, or generate productive conversations, for educators, students, policymakers or educational designers who are interested  in learning science and coding education.</p>
<p>When educators follow the science, they position themselves at the vanguard of pedagogical innovation. This pursuit allows for constant evolution of teaching methods, making learning more effective and enjoyable.</p>
<h2 id="coreprinciples">Core Principles</h2>
<p>Above the science, I have five driving goals for the learning experience.</p>
<ol>
<li>Developing general problem-solving competence.</li>
<li>Student ownership of learning.</li>
<li>Personalizing the learning experience.</li>
<li>Differentiating to match individual zones of proximal development.</li>
<li>Coaching over traditional teaching.</li>
</ol>
<h2 id="thescienceoflearning">The Science of Learning</h2>
<p>Modern education has access to some exciting developments over the last 20 years, thanks in large part to breakthroughs in learning and cognitive science. As educators, course designers, or facilitators of learning experiences, it's crucial to stay abreast of this cutting-edge research.</p>
<p>Why?</p>
<p>Because the insights it offers allow us to create educational environments that are more effective, inclusive, and inspiring. This focus is not a luxury but a necessity for several compelling reasons.</p>
<p>Here are some high level concepts that will be explored in future articles that we use to guide how to nurture the experience.</p>
<ul>
<li>Project based learning</li>
<li>Cognitive load theory</li>
<li>Faded worked examples</li>
<li>Reflection, interleaving, spacing, variation, elaboration, and retrieval</li>
<li>Scaffolding</li>
<li>Coaching/learning culture</li>
</ul>
<h2 id="startingtheconversation">Starting the Conversation</h2>
<p>I will be sharing these article on various social media platform in the hopes that we can all learn from each other. I am hoping that you can engage with this content to share real experiences, failures, and successes just as I will.</p>
<p>I have learned more by reading and listening to others <em>(including the students)</em> than I have by using my own creative thinking skills.</p>
<h2 id="meetingtheneedsofadigitalage">Meeting the Needs of a Digital Age</h2>
<p>In an era where technology is ubiquitous, cognitive research often intersects with technology and learning.</p>
<p>By following the science, we can ensure that our teaching methods evolve as our understanding of the learning process deepens. It's a commitment to never settling for &quot;good enough,&quot; constantly seeking to understand our students better, and refining our craft to deliver the best possible educational outcomes.</p>
<p>I look forward to learning from you.</p>
</div>]]></content:encoded></item></channel></rss>