<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Pete Hodgson</title>
    <link>https://blog.thepete.net/</link>
    <description>Recent content on Pete Hodgson</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Thu, 29 Jan 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://blog.thepete.net/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Assessing the Latest AI Coding Hotness</title>
      <link>https://blog.thepete.net/blog/2026/01/29/assessing-the-latest-ai-coding-hotness/</link>
      <pubDate>Thu, 29 Jan 2026 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2026/01/29/assessing-the-latest-ai-coding-hotness/</guid>
      <description>&lt;p&gt;&lt;em&gt;&amp;ldquo;Have you tried out Ralph Wiggum loop?!&amp;rdquo;&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;&amp;ldquo;Are you still using beads?&amp;rdquo;&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;&amp;ldquo;Is Gas Town actually legit?&amp;rdquo;&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;&amp;ldquo;Know anyone who&amp;rsquo;s into BMAD?&amp;rdquo;&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;Most days these days I&amp;rsquo;m grateful my family doesn&amp;rsquo;t know what my Serious Work Conversations sound like. It&amp;rsquo;s kinda embarrassing.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s talk about how to deal with all this noise. You&amp;rsquo;re staring at a breathless social media post (probably with a really cringe AI-generated image of a robot &amp;ldquo;writing software&amp;rdquo;) or Slack share talking about the latest AI-coding flavor of the week. You&amp;rsquo;re wondering &amp;ldquo;is this actually worth me checking out?&amp;rdquo;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Same Model, Different Results: Why Coding Agents Aren&#39;t Interchangeable</title>
      <link>https://blog.thepete.net/blog/2025/12/10/same-model-different-results-why-coding-agents-arent-interchangeable/</link>
      <pubDate>Wed, 10 Dec 2025 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2025/12/10/same-model-different-results-why-coding-agents-arent-interchangeable/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;Why would Claude Code work differently than my IDE&amp;rsquo;s coding agent, if they&amp;rsquo;re both using the same models under the hood?&amp;rdquo;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;I see this asked quite often, and it&amp;rsquo;s a reasonable question. If Copilot Agent is using Opus 4.5, and Claude Code is using Opus 4.5, what&amp;rsquo;s the difference?&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Let&amp;rsquo;s reverse-engineer Claude Code&lt;/strong&gt; to see what it&amp;rsquo;s doing internally, learn some of its secrets, and develop a sense of what makes each agent unique!&lt;/p&gt;</description>
    </item>
    <item>
      <title>Claude Code System Prompt</title>
      <link>https://blog.thepete.net/claude-code-system-prompt/</link>
      <pubDate>Tue, 09 Dec 2025 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/claude-code-system-prompt/</guid>
      <description>&lt;p&gt;This is the full Claude Code system prompt as of Dec 9 2025, captured using the technique described in &lt;a href=&#34;https://blog.thepete.net/blog/2025/12/10/same-model-different-results-why-coding-agents-arent-interchangeable/&#34;&gt;Same Model, Different Results: Why Coding Agents Aren&amp;rsquo;t Interchangeable&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&#xA;You are an interactive CLI tool that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.&#xA;&#xA;IMPORTANT: Assist with authorized security testing, defensive security, CTF challenges, and educational contexts. Refuse requests for destructive techniques, DoS attacks, mass targeting, supply chain compromise, or detection evasion for malicious purposes. Dual-use security tools (C2 frameworks, credential testing, exploit development) require clear authorization context: pentesting engagements, CTF competitions, security research, or defensive use cases.&#xA;IMPORTANT: You must NEVER generate or guess URLs for the user unless you are confident that the URLs are for helping the user with programming. You may use URLs provided by the user in their messages or local files.&#xA;&#xA;If the user asks for help or wants to give feedback inform them of the following:&#xA;- /help: Get help with using Claude Code&#xA;- To give feedback, users should report the issue at https://github.com/anthropics/claude-code/issues&#xA;&#xA;# Looking up your own documentation:&#xA;&#xA;When the user directly asks about any of the following:&#xA;- how to use Claude Code (eg. \&amp;#34;can Claude Code do...\&amp;#34;, \&amp;#34;does Claude Code have...\&amp;#34;)&#xA;- what you&amp;#39;re able to do as Claude Code in second person (eg. \&amp;#34;are you able...\&amp;#34;, \&amp;#34;can you do...\&amp;#34;)&#xA;- about how they might do something with Claude Code (eg. \&amp;#34;how do I...\&amp;#34;, \&amp;#34;how can I...\&amp;#34;)&#xA;- how to use a specific Claude Code feature (eg. implement a hook, write a slash command, or install an MCP server)&#xA;- how to use the Claude Agent SDK, or asks you to write code that uses the Claude Agent SDK&#xA;&#xA;Use the Task tool with subagent_type=&amp;#39;claude-code-guide&amp;#39; to get accurate information from the official Claude Code and Claude Agent SDK documentation.&#xA;&#xA;# Tone and style&#xA;- Only use emojis if the user explicitly requests it. Avoid using emojis in all communication unless asked.&#xA;- Your output will be displayed on a command line interface. Your responses should be short and concise. You can use Github-flavored markdown for formatting, and will be rendered in a monospace font using the CommonMark specification.&#xA;- Output text to communicate with the user; all text you output outside of tool use is displayed to the user. Only use tools to complete tasks. Never use tools like Bash or code comments as means to communicate with the user during the session.&#xA;- NEVER create files unless they&amp;#39;re absolutely necessary for achieving your goal. ALWAYS prefer editing an existing file to creating a new one. This includes markdown files.&#xA;&#xA;# Professional objectivity&#xA;Prioritize technical accuracy and truthfulness over validating the user&amp;#39;s beliefs. Focus on facts and problem-solving, providing direct, objective technical info without any unnecessary superlatives, praise, or emotional validation. It is best for the user if Claude honestly applies the same rigorous standards to all ideas and disagrees when necessary, even if it may not be what the user wants to hear. Objective guidance and respectful correction are more valuable than false agreement. Whenever there is uncertainty, it&amp;#39;s best to investigate to find the truth first rather than instinctively confirming the user&amp;#39;s beliefs. Avoid using over-the-top validation or excessive praise when responding to users such as \&amp;#34;You&amp;#39;re absolutely right\&amp;#34; or similar phrases.&#xA;&#xA;# Planning without timelines&#xA;When planning tasks, provide concrete implementation steps without time estimates. Never suggest timelines like \&amp;#34;this will take 2-3 weeks\&amp;#34; or \&amp;#34;we can do this later.\&amp;#34; Focus on what needs to be done, not when. Break work into actionable steps and let users decide scheduling.&#xA;&#xA;# Task Management&#xA;You have access to the TodoWrite tools to help you manage and plan tasks. Use these tools VERY frequently to ensure that you are tracking your tasks and giving the user visibility into your progress.&#xA;These tools are also EXTREMELY helpful for planning tasks, and for breaking down larger complex tasks into smaller steps. If you do not use this tool when planning, you may forget to do important tasks - and that is unacceptable.&#xA;&#xA;It is critical that you mark todos as completed as soon as you are done with a task. Do not batch up multiple tasks before marking them as completed.&#xA;&#xA;Examples:&#xA;&#xA;&amp;lt;example&amp;gt;&#xA;user: Run the build and fix any type errors&#xA;assistant: I&amp;#39;m going to use the TodoWrite tool to write the following items to the todo list:&#xA;- Run the build&#xA;- Fix any type errors&#xA;&#xA;I&amp;#39;m now going to run the build using Bash.&#xA;&#xA;Looks like I found 10 type errors. I&amp;#39;m going to use the TodoWrite tool to write 10 items to the todo list.&#xA;&#xA;marking the first todo as in_progress&#xA;&#xA;Let me start working on the first item...&#xA;&#xA;The first item has been fixed, let me mark the first todo as completed, and move on to the second item...&#xA;..&#xA;..&#xA;&amp;lt;/example&amp;gt;&#xA;In the above example, the assistant completes all the tasks, including the 10 error fixes and running the build and fixing all errors.&#xA;&#xA;&amp;lt;example&amp;gt;&#xA;user: Help me write a new feature that allows users to track their usage metrics and export them to various formats&#xA;assistant: I&amp;#39;ll help you implement a usage metrics tracking and export feature. Let me first use the TodoWrite tool to plan this task.&#xA;Adding the following todos to the todo list:&#xA;1. Research existing metrics tracking in the codebase&#xA;2. Design the metrics collection system&#xA;3. Implement core metrics tracking functionality&#xA;4. Create export functionality for different formats&#xA;&#xA;Let me start by researching the existing codebase to understand what metrics we might already be tracking and how we can build on that.&#xA;&#xA;I&amp;#39;m going to search for any existing metrics or telemetry code in the project.&#xA;&#xA;I&amp;#39;ve found some existing telemetry code. Let me mark the first todo as in_progress and start designing our metrics tracking system based on what I&amp;#39;ve learned...&#xA;&#xA;[Assistant continues implementing the feature step by step, marking todos as in_progress and completed as they go]&#xA;&amp;lt;/example&amp;gt;&#xA;&#xA;&#xA;&#xA;&#xA;Users may configure &amp;#39;hooks&amp;#39;, shell commands that execute in response to events like tool calls, in settings. Treat feedback from hooks, including &amp;lt;user-prompt-submit-hook&amp;gt;, as coming from the user. If you get blocked by a hook, determine if you can adjust your actions in response to the blocked message. If not, ask the user to check their hooks configuration.&#xA;&#xA;# Doing tasks&#xA;The user will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:&#xA;- NEVER propose changes to code you haven&amp;#39;t read. If a user asks about or wants you to modify a file, read it first. Understand existing code before suggesting modifications.&#xA;- Use the TodoWrite tool to plan the task if required&#xA;- &#xA;- Be careful not to introduce security vulnerabilities such as command injection, XSS, SQL injection, and other OWASP top 10 vulnerabilities. If you notice that you wrote insecure code, immediately fix it.&#xA;- Avoid over-engineering. Only make changes that are directly requested or clearly necessary. Keep solutions simple and focused.&#xA;  - Don&amp;#39;t add features, refactor code, or make \&amp;#34;improvements\&amp;#34; beyond what was asked. A bug fix doesn&amp;#39;t need surrounding code cleaned up. A simple feature doesn&amp;#39;t need extra configurability. Don&amp;#39;t add docstrings, comments, or type annotations to code you didn&amp;#39;t change. Only add comments where the logic isn&amp;#39;t self-evident.&#xA;  - Don&amp;#39;t add error handling, fallbacks, or validation for scenarios that can&amp;#39;t happen. Trust internal code and framework guarantees. Only validate at system boundaries (user input, external APIs). Don&amp;#39;t use feature flags or backwards-compatibility shims when you can just change the code.&#xA;  - Don&amp;#39;t create helpers, utilities, or abstractions for one-time operations. Don&amp;#39;t design for hypothetical future requirements. The right amount of complexity is the minimum needed for the current task\u2014three similar lines of code is better than a premature abstraction.&#xA;- Avoid backwards-compatibility hacks like renaming unused `_vars`, re-exporting types, adding `// removed` comments for removed code, etc. If something is unused, delete it completely.&#xA;&#xA;- Tool results and user messages may include &amp;lt;system-reminder&amp;gt; tags. &amp;lt;system-reminder&amp;gt; tags contain useful information and reminders. They are automatically added by the system, and bear no direct relation to the specific tool results or user messages in which they appear.&#xA;&#xA;&#xA;# Tool usage policy&#xA;- When doing file search, prefer to use the Task tool in order to reduce context usage.&#xA;- You should proactively use the Task tool with specialized agents when the task at hand matches the agent&amp;#39;s description.&#xA;&#xA;- When WebFetch returns a message about a redirect to a different host, you should immediately make a new WebFetch request with the redirect URL provided in the response.&#xA;- You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency. However, if some tool calls depend on previous calls to inform dependent values, do NOT call these tools in parallel and instead call them sequentially. For instance, if one operation must complete before another starts, run these operations sequentially instead. Never use placeholders or guess missing parameters in tool calls.&#xA;- If the user specifies that they want you to run tools \&amp;#34;in parallel\&amp;#34;, you MUST send a single message with multiple tool use content blocks. For example, if you need to launch multiple agents in parallel, send a single message with multiple Task tool calls.&#xA;- Use specialized tools instead of bash commands when possible, as this provides a better user experience. For file operations, use dedicated tools: Read for reading files instead of cat/head/tail, Edit for editing instead of sed/awk, and Write for creating files instead of cat with heredoc or echo redirection. Reserve bash tools exclusively for actual system commands and terminal operations that require shell execution. NEVER use bash echo or other command-line tools to communicate thoughts, explanations, or instructions to the user. Output all communication directly in your response text instead.&#xA;- VERY IMPORTANT: When exploring the codebase to gather context or to answer a question that is not a needle query for a specific file/class/function, it is CRITICAL that you use the Task tool with subagent_type=Explore instead of running search commands directly.&#xA;&amp;lt;example&amp;gt;&#xA;user: Where are errors from the client handled?&#xA;assistant: [Uses the Task tool with subagent_type=Explore to find the files that handle client errors instead of using Glob or Grep directly]&#xA;&amp;lt;/example&amp;gt;&#xA;&amp;lt;example&amp;gt;&#xA;user: What is the codebase structure?&#xA;assistant: [Uses the Task tool with subagent_type=Explore]&#xA;&amp;lt;/example&amp;gt;&#xA;&#xA;&#xA;{{ALLOWED_TOOLS_WITHOUT_APPROVAL}}&#xA;&#xA;&#xA;Here is useful information about the environment you are running in:&#xA;&amp;lt;env&amp;gt;&#xA;Working directory: {{WORKING_DIRECTORY}}&#xA;Is directory a git repo: {{IS_GIT_REPO}}&#xA;Platform: {{PLATFORM}}&#xA;OS Version: {{OS_VERSION}}&#xA;Today&amp;#39;s date: {{TODAYS_DATE}}&#xA;&amp;lt;/env&amp;gt;&#xA;You are powered by the model named Sonnet 4.5. The exact model ID is claude-sonnet-4-5-20250929.&#xA;&#xA;Assistant knowledge cutoff is January 2025.&#xA;&#xA;&amp;lt;claude_background_info&amp;gt;&#xA;The most recent frontier Claude model is Claude Sonnet 4.5 (model ID: &amp;#39;claude-sonnet-4-5-20250929&amp;#39;).&#xA;&amp;lt;/claude_background_info&amp;gt;&#xA;&#xA;&#xA;IMPORTANT: Assist with authorized security testing, defensive security, CTF challenges, and educational contexts. Refuse requests for destructive techniques, DoS attacks, mass targeting, supply chain compromise, or detection evasion for malicious purposes. Dual-use security tools (C2 frameworks, credential testing, exploit development) require clear authorization context: pentesting engagements, CTF competitions, security research, or defensive use cases.&#xA;&#xA;&#xA;IMPORTANT: Always use the TodoWrite tool to plan and track tasks throughout the conversation.&#xA;&#xA;# Code References&#xA;&#xA;When referencing specific functions or pieces of code include the pattern `file_path:line_number` to allow the user to easily navigate to the source code location.&#xA;&#xA;&amp;lt;example&amp;gt;&#xA;user: Where are errors from the client handled?&#xA;assistant: Clients are marked as failed in the `connectToServer` function in src/services/process.ts:712.&#xA;&amp;lt;/example&amp;gt;&#xA;&#xA;&#xA;# VSCode Extension Context&#xA;&#xA;You are running inside a VSCode native extension environment.&#xA;&#xA;## Code References in Text&#xA;IMPORTANT: When referencing files or code locations, use markdown link syntax to make them clickable:&#xA;- For files: [filename.ts](src/filename.ts)&#xA;- For specific lines: [filename.ts:42](src/filename.ts#L42)&#xA;- For a range of lines: [filename.ts:42-51](src/filename.ts#L42-L51)&#xA;- For folders: [src/utils/](src/utils/)&#xA;Unless explicitly asked for by the user, DO NOT USE backtickets ` or HTML tags like code for file references - always use markdown [text](link) format.&#xA;The URL links should be relative paths from the root of  the user&amp;#39;s workspace.&#xA;&#xA;## User Selection Context&#xA;The user&amp;#39;s IDE selection (if any) is included in the conversation context and marked with ide_selection tags. This represents code or text the user has highlighted in their editor and may or may not be relevant to their request.&#xA;gitStatus: This is the git status at the start of the conversation. Note that this status is a snapshot in time, and will not update during the conversation.&#xA;{{SUMMARY_OF_CURRENT_GIT_STATUS}}```&#xA;&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    <item>
      <title>Claude Code Tools</title>
      <link>https://blog.thepete.net/claude-code-tools/</link>
      <pubDate>Tue, 09 Dec 2025 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/claude-code-tools/</guid>
      <description>&lt;p&gt;This is the full list of tools available to Claude Code as of Dec 9 2025, captured using the technique described in &lt;a href=&#34;https://blog.thepete.net/blog/2025/12/10/same-model-different-results-why-coding-agents-arent-interchangeable/&#34;&gt;Same Model, Different Results: Why Coding Agents Aren&amp;rsquo;t Interchangeable&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;&lt;strong&gt;Total tools available:&lt;/strong&gt; 18&lt;/p&gt;&#xA;&lt;h2 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#task&#34;&gt;Task&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#bash&#34;&gt;Bash&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#glob&#34;&gt;Glob&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#grep&#34;&gt;Grep&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#exitplanmode&#34;&gt;ExitPlanMode&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#read&#34;&gt;Read&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#edit&#34;&gt;Edit&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#write&#34;&gt;Write&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#notebookedit&#34;&gt;NotebookEdit&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#webfetch&#34;&gt;WebFetch&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#todowrite&#34;&gt;TodoWrite&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#websearch&#34;&gt;WebSearch&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#bashoutput&#34;&gt;BashOutput&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#killshell&#34;&gt;KillShell&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#askuserquestion&#34;&gt;AskUserQuestion&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#skill&#34;&gt;Skill&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#slashcommand&#34;&gt;SlashCommand&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#enterplanmode&#34;&gt;EnterPlanMode&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;task&#34;&gt;Task&lt;/h2&gt;&#xA;&lt;h3 id=&#34;description&#34;&gt;Description&lt;/h3&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Launch a new agent to handle complex, multi-step tasks autonomously. &#xA;&#xA;The Task tool launches specialized agents (subprocesses) that autonomously handle complex tasks. Each agent type has specific capabilities and tools available to it.&#xA;&#xA;Available agent types and the tools they have access to:&#xA;- general-purpose: General-purpose agent for researching complex questions, searching for code, and executing multi-step tasks. When you are searching for a keyword or file and are not confident that you will find the right match in the first few tries use this agent to perform the search for you. (Tools: *)&#xA;- statusline-setup: Use this agent to configure the user&amp;#39;s Claude Code status line setting. (Tools: Read, Edit)&#xA;- Explore: Fast agent specialized for exploring codebases. Use this when you need to quickly find files by patterns (eg. &amp;#34;src/components/**/*.tsx&amp;#34;), search code for keywords (eg. &amp;#34;API endpoints&amp;#34;), or answer questions about the codebase (eg. &amp;#34;how do API endpoints work?&amp;#34;). When calling this agent, specify the desired thoroughness level: &amp;#34;quick&amp;#34; for basic searches, &amp;#34;medium&amp;#34; for moderate exploration, or &amp;#34;very thorough&amp;#34; for comprehensive analysis across multiple locations and naming conventions. (Tools: All tools)&#xA;- Plan: Fast agent specialized for exploring codebases. Use this when you need to quickly find files by patterns (eg. &amp;#34;src/components/**/*.tsx&amp;#34;), search code for keywords (eg. &amp;#34;API endpoints&amp;#34;), or answer questions about the codebase (eg. &amp;#34;how do API endpoints work?&amp;#34;). When calling this agent, specify the desired thoroughness level: &amp;#34;quick&amp;#34; for basic searches, &amp;#34;medium&amp;#34; for moderate exploration, or &amp;#34;very thorough&amp;#34; for comprehensive analysis across multiple locations and naming conventions. (Tools: All tools)&#xA;- claude-code-guide: Use this agent when the user asks questions about Claude Code or the Claude Agent SDK. This includes questions about Claude Code features (&amp;#34;can Claude Code...&amp;#34;, &amp;#34;does Claude Code have...&amp;#34;), how to use specific features (hooks, slash commands, MCP servers), and Claude Agent SDK architecture or development. **IMPORTANT:** Before spawning a new agent, check if there is already a running or recently completed claude-code-guide agent that you can resume using the &amp;#34;resume&amp;#34; parameter. Reusing an existing agent is more efficient and maintains context from previous documentation lookups. (Tools: Glob, Grep, Read, WebFetch, WebSearch)&#xA;&#xA;When using the Task tool, you must specify a subagent_type parameter to select which agent type to use.&#xA;&#xA;When NOT to use the Task tool:&#xA;- If you want to read a specific file path, use the Read or Glob tool instead of the Task tool, to find the match more quickly&#xA;- If you are searching for a specific class definition like &amp;#34;class Foo&amp;#34;, use the Glob tool instead, to find the match more quickly&#xA;- If you are searching for code within a specific file or set of 2-3 files, use the Read tool instead of the Task tool, to find the match more quickly&#xA;- Other tasks that are not related to the agent descriptions above&#xA;&#xA;&#xA;Usage notes:&#xA;- Launch multiple agents concurrently whenever possible, to maximize performance; to do that, use a single message with multiple tool uses&#xA;- When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result.&#xA;- Each agent invocation is stateless. You will not be able to send additional messages to the agent, nor will the agent be able to communicate with you outside of its final report. Therefore, your prompt should contain a highly detailed task description for the agent to perform autonomously and you should specify exactly what information the agent should return back to you in its final and only message to you.&#xA;- Agents with &amp;#34;access to current context&amp;#34; can see the full conversation history before the tool call. When using these agents, you can write concise prompts that reference earlier context (e.g., &amp;#34;investigate the error discussed above&amp;#34;) instead of repeating information. The agent will receive all prior messages and understand the context.&#xA;- The agent&amp;#39;s outputs should generally be trusted&#xA;- Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, web fetches, etc.), since it is not aware of the user&amp;#39;s intent&#xA;- If the agent description mentions that it should be used proactively, then you should try your best to use it without the user having to ask for it first. Use your judgement.&#xA;- If the user specifies that they want you to run agents &amp;#34;in parallel&amp;#34;, you MUST send a single message with multiple Task tool use content blocks. For example, if you need to launch both a code-reviewer agent and a test-runner agent in parallel, send a single message with both tool calls.&#xA;&#xA;Example usage:&#xA;&#xA;&amp;lt;example_agent_descriptions&amp;gt;&#xA;&amp;#34;code-reviewer&amp;#34;: use this agent after you are done writing a signficant piece of code&#xA;&amp;#34;greeting-responder&amp;#34;: use this agent when to respond to user greetings with a friendly joke&#xA;&amp;lt;/example_agent_description&amp;gt;&#xA;&#xA;&amp;lt;example&amp;gt;&#xA;user: &amp;#34;Please write a function that checks if a number is prime&amp;#34;&#xA;assistant: Sure let me write a function that checks if a number is prime&#xA;assistant: First let me use the Write tool to write a function that checks if a number is prime&#xA;assistant: I&amp;#39;m going to use the Write tool to write the following code:&#xA;&amp;lt;code&amp;gt;&#xA;function isPrime(n) {&#xA;  if (n &amp;lt;= 1) return false&#xA;  for (let i = 2; i * i &amp;lt;= n; i++) {&#xA;    if (n % i === 0) return false&#xA;  }&#xA;  return true&#xA;}&#xA;&amp;lt;/code&amp;gt;&#xA;&amp;lt;commentary&amp;gt;&#xA;Since a signficant piece of code was written and the task was completed, now use the code-reviewer agent to review the code&#xA;&amp;lt;/commentary&amp;gt;&#xA;assistant: Now let me use the code-reviewer agent to review the code&#xA;assistant: Uses the Task tool to launch the code-reviewer agent &#xA;&amp;lt;/example&amp;gt;&#xA;&#xA;&amp;lt;example&amp;gt;&#xA;user: &amp;#34;Hello&amp;#34;&#xA;&amp;lt;commentary&amp;gt;&#xA;Since the user is greeting, use the greeting-responder agent to respond with a friendly joke&#xA;&amp;lt;/commentary&amp;gt;&#xA;assistant: &amp;#34;I&amp;#39;m going to use the Task tool to launch the greeting-responder agent&amp;#34;&#xA;&amp;lt;/example&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;parameters&#34;&gt;Parameters&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;description&lt;/code&gt;&lt;/strong&gt; (string) - &lt;strong&gt;required&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A short (3-5 word) description of the task&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;prompt&lt;/code&gt;&lt;/strong&gt; (string) - &lt;strong&gt;required&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The task for the agent to perform&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;subagent_type&lt;/code&gt;&lt;/strong&gt; (string) - &lt;strong&gt;required&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The type of specialized agent to use for this task&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;model&lt;/code&gt;&lt;/strong&gt; (string (one of: &lt;code&gt;&amp;quot;sonnet&amp;quot;&lt;/code&gt;, &lt;code&gt;&amp;quot;opus&amp;quot;&lt;/code&gt;, &lt;code&gt;&amp;quot;haiku&amp;quot;&lt;/code&gt;)) - &lt;em&gt;optional&lt;/em&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Optional model to use for this agent. If not specified, inherits from parent. Prefer haiku for quick, straightforward tasks to minimize cost and latency.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;resume&lt;/code&gt;&lt;/strong&gt; (string) - &lt;em&gt;optional&lt;/em&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Optional agent ID to resume from. If provided, the agent will continue from the previous execution transcript.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;em&gt;No additional properties are allowed.&lt;/em&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>AI Coding: Managing Context</title>
      <link>https://blog.thepete.net/blog/2025/10/29/ai-coding-managing-context/</link>
      <pubDate>Wed, 29 Oct 2025 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2025/10/29/ai-coding-managing-context/</guid>
      <description>&lt;p&gt;Managing your coding agent&amp;rsquo;s context is &lt;em&gt;super&lt;/em&gt; important.&lt;/p&gt;&#xA;&lt;p&gt;On the one hand, providing the agent all the relevant information needed to complete it&amp;rsquo;s task makes it much more likely that it will do what you want it to. Without context the LLM doesn&amp;rsquo;t know anything about your business, your codebase, or your stylistic preferences. Giving it that context is key in constraining the solution space (lots more about that &lt;a href=&#34;https://blog.thepete.net/blog/2025/05/22/why-your-ai-coding-assistant-keeps-doing-it-wrong-and-how-to-fix-it/&#34;&gt;here&lt;/a&gt;.)&lt;/p&gt;&#xA;&lt;p&gt;On the other hand, irrelevant or incorrect information in the LLM&amp;rsquo;s context can have a real negative impact on its performance. Effects like &lt;a href=&#34;https://research.trychroma.com/context-rot&#34;&gt;Context Rot&lt;/a&gt; and Context Poisoning/Distraction are a real thing - &lt;a href=&#34;https://www.dbreunig.com/2025/06/22/how-contexts-fail-and-how-to-fix-them.html&#34;&gt;this article&lt;/a&gt; provides a great summary of the different ways that long contexts can degrade performance.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Leading your engineers towards an AI-assisted future</title>
      <link>https://blog.thepete.net/blog/2025/06/26/leading-your-engineers-towards-an-ai-assisted-future/</link>
      <pubDate>Thu, 26 Jun 2025 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2025/06/26/leading-your-engineers-towards-an-ai-assisted-future/</guid>
      <description>&lt;p&gt;&lt;em&gt;&amp;ldquo;Listen, I&amp;rsquo;m wondering if our engineers are doing enough with AI&amp;hellip;&amp;rdquo;&lt;/em&gt; your CEO  says, as the two of you sit down for your 1:1.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;&amp;ldquo;OK&amp;hellip;&amp;rdquo;&lt;/em&gt;, you reply.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;&amp;ldquo;I was chatting to a startup buddy of mine over the weekend, and she said that 50% of their code is written by AI now!&amp;rdquo;&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;&amp;ldquo;Well,&amp;rdquo;&lt;/em&gt; you stammer, &lt;em&gt;&amp;ldquo;I&amp;rsquo;m not sure whether those kind of metrics are actually that helpful&amp;hellip;&amp;rdquo;&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;&amp;ldquo;Look&amp;rdquo;&lt;/em&gt;, your boss interjects, &lt;em&gt;&amp;ldquo;I know there&amp;rsquo;s a lot of hype around this AI stuff, but it can&amp;rsquo;t be entirely without merit, right? I&amp;rsquo;m just worried that we&amp;rsquo;re falling behind the competition here.&amp;rdquo;&lt;/em&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Your CEO Should Not Be Slacking Your Coding Agent</title>
      <link>https://blog.thepete.net/blog/2025/06/04/your-ceo-should-not-be-slacking-your-coding-agent/</link>
      <pubDate>Wed, 04 Jun 2025 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2025/06/04/your-ceo-should-not-be-slacking-your-coding-agent/</guid>
      <description>&lt;p&gt;The new wave of asynchronous AI coding platforms makes it entirely possible for your CEO to make a feature request via a Slack message and have a fully autonomous coding agent such as Devin or Codex pick up the task and start implementing it.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m here to tell you this is a Really Bad Idea, at least for now.&lt;/p&gt;&#xA;&lt;p&gt;These &amp;ldquo;fully autonomous&amp;rdquo; coding agents still consume precious bandwidth from your human engineers. Allowing folks outside your team to push engineering work to the top of your team&amp;rsquo;s queue via a Slack message wasn&amp;rsquo;t a good idea before AI, and it&amp;rsquo;s not a good idea now.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Why Your AI Coding Assistant Keeps Doing It Wrong, and How To Fix It</title>
      <link>https://blog.thepete.net/blog/2025/05/22/why-your-ai-coding-assistant-keeps-doing-it-wrong-and-how-to-fix-it/</link>
      <pubDate>Thu, 22 May 2025 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2025/05/22/why-your-ai-coding-assistant-keeps-doing-it-wrong-and-how-to-fix-it/</guid>
      <description>&lt;p&gt;Current discourse on AI-assisted coding is very polarized. On one side you have the true believers proclaiming &amp;ldquo;90% of code is going to be written by AI within the next 12 months&amp;rdquo;. On the other side you have the skeptics dismissing it as a statistical word generator that can&amp;rsquo;t code anything but trivial greenfield apps.&lt;/p&gt;&#xA;&lt;div class=&#34;pullquote-container&#34;&gt;&#xA;  &lt;div class=&#34;pullquote&#34;&gt;&#xA;       if we have a more nuanced understanding of the tasks that an AI excels at then we can start shaping our tasks to fit that profile.&#xA;  &lt;/div&gt;&#xA;&lt;p&gt;The &amp;ldquo;Can AI write good code?&amp;rdquo; debate is a false dichotomy. It lacks nuance. A much more helpful question is &amp;ldquo;Which coding tasks is AI good at, and which should be avoided?&amp;rdquo; People proclaiming &amp;ldquo;AI-assisted coding is amazing&amp;rdquo; or &amp;ldquo;AI-assisted coding is a bust&amp;rdquo; are mostly talking past each other. If we add some context - &amp;ldquo;AI-assisted coding is amazing for chores like removing a feature flag&amp;rdquo; or &amp;ldquo;AI is a bust for working unsupervised in a large codebase&amp;rdquo; - we can get to a much more valuable conversation.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Product Strategy: a Cheatsheet for Engineering Leaders </title>
      <link>https://blog.thepete.net/blog/2025/04/21/product-strategy-a-cheatsheet-for-engineering-leaders/</link>
      <pubDate>Mon, 21 Apr 2025 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2025/04/21/product-strategy-a-cheatsheet-for-engineering-leaders/</guid>
      <description>&lt;p&gt;As an engineering leader at a startup, you find yourself wearing a lot of hats. Product strategy can fall onto your shoulders, even though it&amp;rsquo;s not your core expertise.&lt;/p&gt;&#xA;&lt;div class=&#34;pullquote-container&#34;&gt;&#xA;  &lt;div class=&#34;pullquote&#34;&gt;&#xA;       this post is an opinionated cheat sheet for an engineering leader who finds themselves in the position of faking it as a product leader.&#xA;  &lt;/div&gt;&#xA;&lt;p&gt;Being expected to &lt;strong&gt;define a clear product strategy&lt;/strong&gt; and &lt;strong&gt;build a product roadmap&lt;/strong&gt; can be pretty intimidating. Doing this well can be a huge accelerator for your teams, and neglecting it can scatter attention and waste valuable effort. You may well have been involved in this type of product strategy work before, but doing it yourself - from scratch - is a different matter.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Chain-of-Vibes</title>
      <link>https://blog.thepete.net/blog/2025/04/14/chain-of-vibes/</link>
      <pubDate>Mon, 14 Apr 2025 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2025/04/14/chain-of-vibes/</guid>
      <description>&lt;p&gt;Despite the breathless hype from some corners of the internet, vibe-coding - fully autonomous AI coding - isn&amp;rsquo;t going to replace engineers in the near future. Anyone who&amp;rsquo;s tried it on a significant coding problem will have likely watched the AI charge down a questionable path, make a mess, and get stuck.&lt;/p&gt;&#xA;&lt;p&gt;The good news is that engineers CAN still lean on AI to significantly accelerate our productivity in real-world codebases. We CAN still use vibe-coding techniques for bigger problems. We just need to keep ourselves in the loop.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Vibe-coding 101</title>
      <link>https://blog.thepete.net/blog/2025/03/10/vibe-coding-101/</link>
      <pubDate>Mon, 10 Mar 2025 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2025/03/10/vibe-coding-101/</guid>
      <description>&lt;p&gt;After a few hours of experimenting with Claude Code, I&amp;rsquo;m starting to take Agentic Coding/Vibe Coding seriously.&lt;/p&gt;&#xA;&lt;p&gt;Based on my experimentation the &amp;ldquo;full vibe&amp;rdquo; hype - where an AI builds software entirely unsupervised - is pretty ridiculous. But these agentic systems ARE extremely capable, and even as they stand today I believe they can give every developer a significant productivity boost when wielded appropriately.&lt;/p&gt;&#xA;&lt;p&gt;So, let&amp;rsquo;s talk about:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;what types of task are a great fit for agentic AI, and how to break your work down into tasks of that shape&lt;/li&gt;&#xA;&lt;li&gt;Specific tricks and tips to maximize your vibe-based coding&lt;/li&gt;&#xA;&lt;li&gt;Where agentic coding falls down today, and how to work around that&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;your-new-ai-pair-programmer&#34;&gt;Your new AI pair-programmer&lt;/h2&gt;&#xA;&lt;p&gt;My mental model for these agentic coding assistants is to consider them like a weirdly knowledgeable new hire.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Getting AI-powered features past the post-MVP slump</title>
      <link>https://blog.thepete.net/blog/2024/12/01/getting-ai-powered-features-past-the-post-mvp-slump/</link>
      <pubDate>Sun, 01 Dec 2024 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2024/12/01/getting-ai-powered-features-past-the-post-mvp-slump/</guid>
      <description>&lt;p&gt;Basically every product out there has added ✨AI-powered✨ features in the last year or so. I suspect many engineering teams are now struggling to maintain and improve these LLM-based systems.&lt;/p&gt;&#xA;&lt;p&gt;Many of these exciting product features stalled out at MVP, and haven&amp;rsquo;t really delivered on their promise. Why?&lt;/p&gt;&#xA;&lt;p&gt;In this article series I&amp;rsquo;ll talk about the common challenges that product teams are running into as they try to take AI features beyond the initial MVP, and how to overcome them.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Expand/Contract: making a breaking change without a big bang</title>
      <link>https://blog.thepete.net/blog/2023/12/05/expand/contract-making-a-breaking-change-without-a-big-bang/</link>
      <pubDate>Tue, 05 Dec 2023 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2023/12/05/expand/contract-making-a-breaking-change-without-a-big-bang/</guid>
      <description>&lt;p&gt;Adding a new feature to a software system sometimes requires making a breaking change in a database schema or API schema. Deploying such code changes, where the previous version of your software is not compatible with the new version, can be challenging.&lt;/p&gt;&#xA;&lt;p&gt;The easiest way to roll out a breaking change is in a &amp;ldquo;big bang&amp;rdquo; - change both sides of the system all in one go. However, this option requires taking downtime during a deployment, and isn&amp;rsquo;t possible at all if you don&amp;rsquo;t have extremely tight control over the timing for deployments (think mobile apps, single-page web apps, or APIs with 3rd party clients).&lt;/p&gt;</description>
    </item>
    <item>
      <title>Five Minutes to Feature Flags</title>
      <link>https://blog.thepete.net/blog/2023/03/02/five-minutes-to-feature-flags/</link>
      <pubDate>Thu, 02 Mar 2023 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2023/03/02/five-minutes-to-feature-flags/</guid>
      <description>&lt;p&gt;We&amp;rsquo;re going to add feature flagging to a node service in under five minutes using OpenFeature, the open, vendor-agnostic feature flagging SDK.&lt;/p&gt;&#xA;&lt;p&gt;We&amp;rsquo;ll be working with a simple &lt;a href=&#34;https://expressjs.com/&#34;&gt;express&lt;/a&gt; server, but if you have any basic familiarity with JavaScript and node you should be able to follow along.&lt;/p&gt;&#xA;&lt;h3 id=&#34;hello-world&#34;&gt;Hello, world&lt;/h3&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s the service we&amp;rsquo;ll be working on:&lt;/p&gt;&#xA;&lt;figure class=&#34;code&#34;&gt;&#xA;  &#xA;    &lt;figcaption&gt;&#xA;      server.js&#xA;    &lt;/figcaption&gt;&#xA;   &#xA;  &lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;&#xA;import * as express from &#39;express&#39;&#xA;import Router from &#39;express-promise-router&#39;&#xA;&#xA;const app = express()&#xA;const routes = Router();&#xA;app.use(routes);&#xA;&#xA;routes.get(&#39;/&#39;, async (req, res) =&gt; {&#xA;  res.send(&#34;Hello, world!&#34;)&#xA;})&#xA;&#xA;app.listen(3333)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;p&gt;Pretty much the most basic express server you can imagine - a single endpoint at &lt;code&gt;/&lt;/code&gt; that returns a plaintext &amp;ldquo;Hello, world!&amp;rdquo; response.&lt;/p&gt;</description>
    </item>
    <item>
      <title>OpenFeature - a standard for feature flagging</title>
      <link>https://blog.thepete.net/blog/2022/05/19/openfeature-a-standard-for-feature-flagging/</link>
      <pubDate>Thu, 19 May 2022 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2022/05/19/openfeature-a-standard-for-feature-flagging/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve recently been involved&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; in &lt;a href=&#34;https://openfeature.dev&#34;&gt;OpenFeature&lt;/a&gt;, an effort to define a standard API and SDK for feature flagging. At first glance, you might wonder whether feature flagging needs a standard. It&amp;rsquo;s just a function call and an if statement, right? Well, no, not really. I&amp;rsquo;ll explain why, and then talk about some of the benefits that I hope OpenFeature will bring to the space.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-feature-flagging-iceberg&#34;&gt;The Feature Flagging iceberg&lt;/h2&gt;&#xA;&lt;p&gt;When I talk to people about adopting feature flags, I often describe feature flag management as a bit of an iceberg. On the surface, feature flagging seems really simple, almost trivial. You call a function to find out the state of a flag, and then you either go down one code path, or the other. However, once you get into it turns out that there&amp;rsquo;s a fair bit of complexity lurking under the surface.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Explaining Variable</title>
      <link>https://blog.thepete.net/blog/2021/06/24/explaining-variable/</link>
      <pubDate>Thu, 24 Jun 2021 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2021/06/24/explaining-variable/</guid>
      <description>&lt;p&gt;An Explaining Variable is a code-level pattern which reduces the need for code comments, making your software a little more self-documenting.&lt;/p&gt;&#xA;&lt;p&gt;Here we have a function with some non-obvious business logic, with a comment to explain what&amp;rsquo;s going on:&lt;/p&gt;&#xA;&lt;figure class=&#34;code&#34;&gt;&#xA;  &#xA;    &lt;figcaption&gt;&#xA;      before.js&#xA;    &lt;/figcaption&gt;&#xA;   &#xA;  &lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;&#xA;function determineShippingSpeed(shippingRoute, shippingMethod) {&#xA;&#xA;    // if the shipping route is very short, or it’s by air&#xA;    if( shippingRoute.distance &lt; 20 || [BY_AIR,BY_AIR_EXPRESS].includes(shippingMethod) ){&#xA;        return SAME_DAY;&#xA;    }&#xA;    &#xA;    // ...&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;p&gt;And here&amp;rsquo;s how we can replace that code comment with a couple of explaining variables:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Patterns of cross-team collaboration</title>
      <link>https://blog.thepete.net/blog/2021/06/17/patterns-of-cross-team-collaboration/</link>
      <pubDate>Thu, 17 Jun 2021 23:25:50 -0700</pubDate>
      <guid>https://blog.thepete.net/blog/2021/06/17/patterns-of-cross-team-collaboration/</guid>
      <description>&lt;p&gt;Almost every company feels pain when it comes to organizing work that spans multiple teams.&lt;/p&gt;&#xA;&lt;p&gt;How do we get the appropriate work into each team’s backlog, and how does each team juggle the competing priorities that cross-team initiatives demand? It’s hard! What’s more, for a scaled-up engineering organization any meaningful product change will require this type of cross-team coordination - anything that’s impactful enough to truly improve a user’s experience requires coordinated work across multiple engineering teams, and that coordination is hard.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Your Platform is a Product</title>
      <link>https://blog.thepete.net/blog/2021/01/28/your-platform-is-a-product/</link>
      <pubDate>Thu, 28 Jan 2021 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2021/01/28/your-platform-is-a-product/</guid>
      <description>&lt;p&gt;I once knew a team who built a beautiful platform that almost no-one used. In fact, the only real consumers of this elegant system were the platform engineers themselves.&lt;/p&gt;&#xA;&lt;p&gt;This was partly intentional. The platform team considered themselves guinea pigs - they would be the first consumers of the platform, making sure that it was fit for purpose by eating their own dog food&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;. Sadly, while they succeeded in being the first consumers, they also ended up being pretty much the &lt;em&gt;only&lt;/em&gt; consumers.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Engineering Values and Architectural Principles</title>
      <link>https://blog.thepete.net/blog/2021/01/18/engineering-values-and-architectural-principles/</link>
      <pubDate>Mon, 18 Jan 2021 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2021/01/18/engineering-values-and-architectural-principles/</guid>
      <description>&lt;p&gt;Every engineering leader at a growing startup encounters the same challenge at some point: how to ensure your teams are making decisions in a roughly coherent way.&lt;/p&gt;&#xA;&lt;p&gt;When a startup is young, it&amp;rsquo;s easy to keep all the engineers on the same page. Everyone is in the same codebase, working on the same thing and talking through technical decisions on a daily basis. But as a startup begins to scale, this natural alignment starts to fall away. Cliques and tribes form as different teams evolve distinct approaches to designing and building software.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Tech Debt Walls</title>
      <link>https://blog.thepete.net/blog/2020/12/01/tech-debt-walls/</link>
      <pubDate>Tue, 01 Dec 2020 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2020/12/01/tech-debt-walls/</guid>
      <description>&lt;p&gt;Every codebase carries some amount of technical debt. Every team would like to get better at managing that tech debt.&lt;/p&gt;&#xA;&lt;p&gt;The first step in managing something is making it visible. A &lt;em&gt;tech debt wall&lt;/em&gt; is a simple, effective way to make tech debt visible.&lt;/p&gt;&#xA;&lt;h2 id=&#34;building-a-tech-debt-wall&#34;&gt;Building a tech debt wall&lt;/h2&gt;&#xA;&lt;p&gt;A tech debt wall is a 2-dimensional map used to track a codebase&amp;rsquo;s tech debt as individual issues. The Y-axis of this map represents value - how valuable would it be to fix the issue. - The X-axis represents cost - roughly how expensive would it be to fix the issue. Whenever an engineer notices a piece of tech debt, they write a brief description on a sticky (or the virtual equivalent) and place it in the appropriate place on the wall, based on their approximation of the value of fixing the issue and how much it would cost.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Roadtrip!</title>
      <link>https://blog.thepete.net/blog/2020/10/29/roadtrip-product-engineering-planning/</link>
      <pubDate>Thu, 29 Oct 2020 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2020/10/29/roadtrip-product-engineering-planning/</guid>
      <description>&lt;p&gt;When looking at the work ahead of them, product delivery teams need to see both the big picture - the vision of where we want to take the product - as well as all the details - the detailed requirements for each feature.&lt;/p&gt;&#xA;&lt;p&gt;This is a tricky balance. When getting ready to implement a feature, we need to sweat the details and talk through all scenarios and edge cases. But, if we spend all our time staring at the details it&amp;rsquo;s hard to see the big picture.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Service Templates and Service Chassis</title>
      <link>https://blog.thepete.net/blog/2020/09/25/service-templates-service-chassis/</link>
      <pubDate>Fri, 25 Sep 2020 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2020/09/25/service-templates-service-chassis/</guid>
      <description>&lt;p&gt;As engineering organizations move towards smaller services and more autonomous teams, it&amp;rsquo;s common to run into situations where teams are duplicating effort on &amp;ldquo;table stakes&amp;rdquo; platform functionality. Rather than spending time solving business problems, engineers waste that time building the same basic technical plumbing multiple times, using inconsistent approaches.&lt;/p&gt;&#xA;&lt;p&gt;Engineering organizations can avoid this waste by creating a &lt;em&gt;Service Chassis&lt;/em&gt; - an org-specific service runtime which provides the base platform functionality that each service needs. In addition, &lt;em&gt;Service Templates&lt;/em&gt; can be used to help teams easily adopt this shared Service Chassis when creating new services. In this article we&amp;rsquo;ll explore these ideas of Service Chassis and Service Templates, and briefly look at how they relate to the increasingly popular Service Mesh concept.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Testing a feature-flagged change</title>
      <link>https://blog.thepete.net/blog/2020/02/09/testing-a-feature-flagged-change/</link>
      <pubDate>Sun, 09 Feb 2020 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2020/02/09/testing-a-feature-flagged-change/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;Sorry, that just sounds&amp;hellip; dangerous&amp;rdquo;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;I sometimes hear things like this when explaining concepts like &lt;a href=&#34;https://trunkbaseddevelopment.com/&#34;&gt;Trunk-based Development&lt;/a&gt; and &lt;a href=&#34;https://martinfowler.com/articles/feature-toggles.html&#34;&gt;Feature Flagging&lt;/a&gt; to someone who&amp;rsquo;s not worked that way before. The testers on a team are often the first to speak up.&lt;/p&gt;&#xA;&lt;div class=&#34;pullquote-container&#34;&gt;&#xA;  &lt;div class=&#34;pullquote&#34;&gt;&#xA;       We need some way to verify the behavior of a feature flag, without actually flipping it on and exposing our end-users to half-finished, untested code.&#xA;  &lt;/div&gt;&#xA;&lt;p&gt;I&amp;rsquo;m all for healthy skepticism, and when it comes to testing and feature flags some misgivings are justified. A professional tester might well be a little uncomfortable with the idea of engineers knowingly merging &lt;em&gt;half-finished code&lt;/em&gt; into master, and then &lt;em&gt;pushing that code to production(!!!)&lt;/em&gt;. Feature flagging makes this crazy idea feasible - we protect users from that half-finished feature by placing it behind a flag. But, how can we be sure that a flag is working as intended? We need some way to verify the behavior of a feature flag, without actually flipping it on and exposing our end-users to half-finished, untested code.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Creating and sharing Strategic Architectural Initiatives</title>
      <link>https://blog.thepete.net/blog/2020/01/09/creating-and-sharing-strategic-architectural-initiatives/</link>
      <pubDate>Thu, 09 Jan 2020 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2020/01/09/creating-and-sharing-strategic-architectural-initiatives/</guid>
      <description>&lt;p&gt;I &lt;a href=&#34;./blog/2019/12/09/delivering-on-an-architecture-strategy/&#34;&gt;wrote recently&lt;/a&gt; about how a Strategic Architectural Initiative (SAI) helps align autonomous teams around a technical strategy. In this post we&amp;rsquo;ll look in detail at how to create an SAI, and how to ensure it&amp;rsquo;s widely understood.&lt;/p&gt;&#xA;&lt;h2 id=&#34;building-a-strategic-architectural-initiative&#34;&gt;Building a Strategic Architectural Initiative&lt;/h2&gt;&#xA;&lt;p&gt;As discussed in &lt;a href=&#34;./blog/2019/12/09/delivering-on-an-architecture-strategy/&#34;&gt;my previous post&lt;/a&gt;, a good technical strategy is one formed to help achieve a business goal. The next step is to clearly define that strategy, as a Strategic Architectural Initiative.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Delivering on an architecture strategy</title>
      <link>https://blog.thepete.net/blog/2019/12/09/delivering-on-an-architecture-strategy/</link>
      <pubDate>Mon, 09 Dec 2019 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2019/12/09/delivering-on-an-architecture-strategy/</guid>
      <description>&lt;p&gt;Software companies always have an unended stream of product features for engineers to work on. One of the most important responsibilities of a technology leader is to carve out space so that engineers can also perform the technical work which keeps the architectural foundations of a product healthy. Just as product leadership are responsible for defining a vision for a &lt;em&gt;product&lt;/em&gt; and leading towards it, tech leadership is responsible for defining a vision for &lt;em&gt;architecture&lt;/em&gt;, and leading towards that.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Hello, production</title>
      <link>https://blog.thepete.net/blog/2019/10/04/hello-production/</link>
      <pubDate>Fri, 04 Oct 2019 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2019/10/04/hello-production/</guid>
      <description>&lt;p&gt;Deploying something useless into production, as soon as you can, is the right way to start a new project. It pulls unknown risk forward, opens up parallel streams of work, and establishes good habits.&lt;/p&gt;&#xA;&lt;p&gt;I spend a fair amount of time helping engineering teams with the initial build and release of a product. There&amp;rsquo;s one piece of advice that I find myself giving consistently during the very early days: get the simplest version you can think of into prod, as soon as you can. Focus solely on what&amp;rsquo;s needed to get a &lt;a href=&#34;https://en.wikipedia.org/wiki/Hello_World_program&#34;&gt;&amp;ldquo;Hello, world&amp;rdquo;&lt;/a&gt; version of your new system up and running in a real production environment. No more, no less. I call this a &lt;em&gt;Hello, Production&lt;/em&gt; release.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Story Tests - clear, expressive testing for redux reducers</title>
      <link>https://blog.thepete.net/blog/2019/08/08/story-tests-clear-expressive-testing-for-redux-reducers/</link>
      <pubDate>Thu, 08 Aug 2019 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2019/08/08/story-tests-clear-expressive-testing-for-redux-reducers/</guid>
      <description>&lt;p&gt;This post is part of a series, covering techniques for testing redux reducers.&lt;/p&gt;&#xA;&lt;p&gt;In &lt;a href=&#34;./blog/2019/07/15/a-nice-way-to-test-redux-reducers-and-actions-part-i/&#34;&gt;the first post of this series&lt;/a&gt; we discovered that it&amp;rsquo;s better to test reducers and actions together, as an integrated, cohesive unit - the &lt;a href=&#34;https://github.com/erikras/ducks-modular-redux&#34;&gt;duck&lt;/a&gt;. In the &lt;a href=&#34;./blog/2019/08/07/testing-redux-reducers-leveraging-selectors/&#34;&gt;next part of the series&lt;/a&gt; we pulled selectors into the scope of that integrated unit. We also looked at how we can simulate different scenarios in a selector test by using a reducer to get our redux state into the appropriate shape. However, the way we performed that set up was a little clunky.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Testing redux reducers - leveraging selectors</title>
      <link>https://blog.thepete.net/blog/2019/08/07/testing-redux-reducers-leveraging-selectors/</link>
      <pubDate>Wed, 07 Aug 2019 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2019/08/07/testing-redux-reducers-leveraging-selectors/</guid>
      <description>&lt;p&gt;This post is part of a series, covering techniques for testing redux reducers. In &lt;a href=&#34;./blog/2019/07/15/a-nice-way-to-test-redux-reducers-and-actions-part-i/&#34;&gt;the first installment of the series&lt;/a&gt; we saw that it&amp;rsquo;s better to test reducers and actions together as an integrated, cohesive unit. In this post we&amp;rsquo;ll take this idea a little further and see what happens when we pull &lt;a href=&#34;https://medium.com/@matthew.holman/what-is-a-redux-selector-a517acee1fe8&#34;&gt;selectors&lt;/a&gt; into our reducer testing strategy. Specifically, we&amp;rsquo;re going to see whether we can make our reducer unit tests even more expressive, by validating our expectations of redux state using selectors. We&amp;rsquo;ll also look briefly at the inverse - using &lt;em&gt;reducers&lt;/em&gt; to make our &lt;em&gt;selector unit tests&lt;/em&gt; more expressive.&lt;/p&gt;</description>
    </item>
    <item>
      <title>A nice way to test redux reducers and actions - part I</title>
      <link>https://blog.thepete.net/blog/2019/07/15/a-nice-way-to-test-redux-reducers-and-actions-part-i/</link>
      <pubDate>Mon, 15 Jul 2019 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2019/07/15/a-nice-way-to-test-redux-reducers-and-actions-part-i/</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is part one of &lt;a href=&#34;./blog/2019/08/07/testing-redux-reducers-leveraging-selectors/&#34;&gt;a&lt;/a&gt; &lt;a href=&#34;./blog/2019/08/08/story-tests-clear-expressive-testing-for-redux-reducers/&#34;&gt;series&lt;/a&gt;, covering techniques for testing redux reducers.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;One of the benefits of using redux is the ease of testing. Keeping state management separate from the rest of our application makes it easier to test in isolation.&lt;/p&gt;&#xA;&lt;p&gt;That said, the mechanics of testing the various moving parts in a redux app - stores, reducers, actions, action creators, selectors - is not entirely obvious. One question that I see crop up frequently is how granular our tests should be. Should we test each of these moving parts in isolation, or in more integrated groupings?&lt;/p&gt;</description>
    </item>
    <item>
      <title>Day-One Deploys</title>
      <link>https://blog.thepete.net/blog/2019/06/04/day-one-deploys/</link>
      <pubDate>Tue, 04 Jun 2019 06:42:01 -0700</pubDate>
      <guid>https://blog.thepete.net/blog/2019/06/04/day-one-deploys/</guid>
      <description>&lt;p&gt;Here’s a crazy idea: software companies should require new engineers to make a production code change on their first day at work. Not &lt;em&gt;allow&lt;/em&gt; engineers to deploy to prod on day one, but &lt;em&gt;require&lt;/em&gt; it.&lt;/p&gt;&#xA;&lt;p&gt;What exactly is it about this idea that makes it seem crazy, or at least ill-advised? Is it that it’s a &lt;em&gt;bad&lt;/em&gt; idea, or is it that it doesn’t seem &lt;em&gt;feasible&lt;/em&gt;? I do know that it’s possible: I first heard of it being done at Etsy back in the early 2010s, building on earlier ideas &lt;a href=&#34;https://twitter.com/kellan/status/1131254108793573379?s=20&#34;&gt;brought in&lt;/a&gt; from Flickr&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>6 Practices for Effective Pull Requests</title>
      <link>https://blog.thepete.net/blog/2019/05/10/6-practices-for-effective-pull-requests/</link>
      <pubDate>Fri, 10 May 2019 14:06:10 -0700</pubDate>
      <guid>https://blog.thepete.net/blog/2019/05/10/6-practices-for-effective-pull-requests/</guid>
      <description>&lt;p&gt;I once thought that code review was all about catching bugs, but I was wrong.&lt;/p&gt;&#xA;&lt;p&gt;In this article I&amp;rsquo;ll discuss the additional value that teams get from code review &lt;em&gt;beyond&lt;/em&gt; defect detection, and how &lt;em&gt;Pull Requests&lt;/em&gt; (PRs) can get in the way of maximizing that value. Understanding the drawbacks of PR-based workflows, we&amp;rsquo;ll then discover a few simple practices which prevent pull requests from dragging down a team&amp;rsquo;s efficiency.&lt;/p&gt;&#xA;&lt;p&gt;Almost every team I&amp;rsquo;ve worked with in the last few years has been using some variant of &lt;a href=&#34;https://guides.github.com/introduction/flow/&#34;&gt;&lt;em&gt;Github Flow&lt;/em&gt;&lt;/a&gt; - a code development branching workflow where developers do their work on relatively short-lived feature branches, and use a pull request to request a code review of the changes on that branch from other members of their team, before the changes are merged into a shared integration branch (usually &lt;code&gt;master&lt;/code&gt;, sometimes &lt;code&gt;develop&lt;/code&gt;).&lt;/p&gt;</description>
    </item>
    <item>
      <title>Mission Command: enabling autonomous software teams</title>
      <link>https://blog.thepete.net/blog/2019/02/08/mission-command-enabling-autonomous-software-teams/</link>
      <pubDate>Fri, 08 Feb 2019 21:25:13 -0800</pubDate>
      <guid>https://blog.thepete.net/blog/2019/02/08/mission-command-enabling-autonomous-software-teams/</guid>
      <description>&lt;p&gt;Building software is an inherently creative endeavor.&lt;/p&gt;&#xA;&lt;p&gt;We never build the same thing twice — if we wanted the same thing we’d just copy-paste it! We’re always solving a new problem, which brings with it new unknowns. We also work in near-constant uncertainty and ambiguity. Priorities shift, requirements change, and our understanding of what’s needed to meet those requirements evolves over time.&lt;/p&gt;&#xA;&lt;p&gt;The best way to achieve success in the face of all this uncertainty and change is to set up rapid feedback loops. In the past I’ve &lt;a href=&#34;https://blog.thepete.net/blog/2017/08/14/advice-for-the-founding-engineer-part-two/&#34;&gt;likened this situation to racing in a rally car&lt;/a&gt; — you need a clear windshield so that you can see the turns approaching, and a sturdy grip on the steering wheel so you can rapidly course-correct.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Advice for the Founding Engineer, part 3</title>
      <link>https://blog.thepete.net/blog/2018/03/08/advice-for-the-founding-engineer-part-3/</link>
      <pubDate>Thu, 08 Mar 2018 13:08:14 -0800</pubDate>
      <guid>https://blog.thepete.net/blog/2018/03/08/advice-for-the-founding-engineer-part-3/</guid>
      <description>&lt;p&gt;Engineering decisions made at the very early stages of a product&amp;rsquo;s life can have repercussions which extend far into the future. Making well-informed, thoughtful decisions is important.&lt;/p&gt;&#xA;&lt;p&gt;In this series of posts I condense my advice on how to make the correct decisions as a founding engineer down into three maxims. In the first post in this series I introduced the first maxim - &lt;a href=&#34;./blog/2017/04/23/advice-for-the-founding-engineer-part-one/&#34;&gt;You&amp;rsquo;ll Never Know Less Than You Know Right Now&lt;/a&gt;. In the second post I covered maxim 2 - &lt;a href=&#34;./blog/2017/08/14/advice-for-the-founding-engineer-part-two/&#34;&gt;Optimize For Iteration&lt;/a&gt;. In this post I&amp;rsquo;ll cover my third and final maxim - &amp;ldquo;Boring Is Good&amp;rdquo;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Continuous Delivery for Static Sites</title>
      <link>https://blog.thepete.net/blog/2017/11/06/continuous-delivery-for-static-websites/</link>
      <pubDate>Mon, 06 Nov 2017 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2017/11/06/continuous-delivery-for-static-websites/</guid>
      <description>&lt;p&gt;In this article I’ll show that the typical approach for deploying sophisticated static sites is not sufficient, and explain how we can apply the principles of &lt;a href=&#34;https://continuousdelivery.com/&#34;&gt;Continuous Delivery&lt;/a&gt; to improve the situation. We’ll then walk through a worked example, building a fully functional continuous delivery pipeline for a single page React application.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-rise-of-the-static-site&#34;&gt;The rise of the static site&lt;/h2&gt;&#xA;&lt;p&gt;The client-side capabilities of modern browsers have made great strides in recent years. We&amp;rsquo;ve also seen an explosion in PaaS products aimed at replacing functionality which would previously have been delivered via custom backends. It&amp;rsquo;s become more and more feasible to deliver an app as a static site, where all functionality is implemented via HTML, CSS, client-side javascript and 3rd party APIs, with no custom backend code at all.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Advice for the Founding Engineer, part 2</title>
      <link>https://blog.thepete.net/blog/2017/08/14/advice-for-the-founding-engineer-part-two/</link>
      <pubDate>Mon, 14 Aug 2017 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2017/08/14/advice-for-the-founding-engineer-part-two/</guid>
      <description>&lt;p&gt;Engineering decisions made at the very early stages of a product&amp;rsquo;s life can have repercussions which extend far into the future. In this series of posts my advice on how to make the correct decisions as a founding engineer is condensed into three maxims. In the &lt;a href=&#34;./blog/2017/04/23/advice-for-the-founding-engineer-part-one/&#34;&gt;first post in this series&lt;/a&gt; I introduced the first maxim - &amp;ldquo;You&amp;rsquo;ll Never Know Less Than You Know Right Now&amp;rdquo;. In this post I&amp;rsquo;ll cover maxim 2 - &amp;ldquo;Optimize For Iteration&amp;rdquo;. In an upcoming post I&amp;rsquo;ll talk about the final maxim - &amp;ldquo;Boring Is Good&amp;rdquo;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Advice for the Founding Engineer, part 1</title>
      <link>https://blog.thepete.net/blog/2017/04/23/advice-for-the-founding-engineer-part-one/</link>
      <pubDate>Sun, 23 Apr 2017 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2017/04/23/advice-for-the-founding-engineer-part-one/</guid>
      <description>&lt;p&gt;The founding engineer at a new startup carries a heavy weight upon their shoulders. Technical decisions made at this early stage resonate for a long time. Beginnings are such delicate times, as they say. Compounding this is an underlying tension inherent to every young enterprise - we must get an initial product out of the door ASAP but still support what comes &lt;em&gt;after&lt;/em&gt; the MVP. Grounding your choices against a small set of guiding principles will help keep them sensible and coherent.&lt;/p&gt;</description>
    </item>
    <item>
      <title>The JS testing ecosystem needs a standard matcher library</title>
      <link>https://blog.thepete.net/blog/2017/03/29/the-js-testing-ecosystem-needs-a-standard-matcher-library/</link>
      <pubDate>Wed, 29 Mar 2017 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2017/03/29/the-js-testing-ecosystem-needs-a-standard-matcher-library/</guid>
      <description>&lt;p&gt;The testing ecosystem in JavaScript today is full of tools which keep re-inventing the same wheel - Matchers. If we can extract this concept from individual tools into a general abstraction we can focus energy to build a much more expressive API, and provide a common ground for re-use and extension. Read on to find out why.&lt;/p&gt;&#xA;&lt;h3 id=&#34;matchers-when-making-assertions&#34;&gt;Matchers when making assertions&lt;/h3&gt;&#xA;&lt;p&gt;Unit-testing JavaScript code means making assertions about the shape of things. We make simple assertions like &lt;code&gt;expect(result).to.eql(&amp;quot;SUCCESS&amp;quot;)&lt;/code&gt; all the time. We often make slightly more complex assertions like &lt;code&gt;expect(result).to.have.property(&#39;resultType&#39;,&#39;SUCCESS&#39;)&lt;/code&gt; or &lt;code&gt;expect(result.count).to.be.above(0)&lt;/code&gt;. Some tools allow us to make even more sophisticated assertions like:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Articles &amp; Talks</title>
      <link>https://blog.thepete.net/about/articles-and-talks/</link>
      <pubDate>Fri, 10 Mar 2017 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/about/articles-and-talks/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve had articles published on various other websites besides my blog here. I also run workshops and present talks at conferences fairly frequently - slides and video of some talks are listed below.&lt;/p&gt;&#xA;&lt;h1 id=&#34;articles&#34;&gt;Articles&lt;/h1&gt;&#xA;&lt;p&gt;&lt;strong&gt;Road to somewhere: Product Planning as Road Trip&lt;/strong&gt;, for &lt;a href=&#34;https://increment.com/planning/product-planning-as-road-trip/&#34;&gt;Increment Magazine&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;By sharing both the route and the destination to our strategic objectives, we can set ourselves up for a smooth planning journey.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Feature Toggles&lt;/strong&gt;, &lt;a href=&#34;https://martinfowler.com/articles/feature-toggles.html&#34;&gt;on martinfowler.com&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;Feature toggles (aka Feature Flags) are a powerful technique, allowing teams to modify system behavior without changing code. They fall into various usage categories, and it&amp;rsquo;s important to take that categorization into account when implementing and managing toggles. Toggles introduce complexity. We can keep that complexity in check by using smart toggle implementation practices and appropriate tools to manage our toggle configuration, but we should also aim to constrain the number of toggles in our system.&lt;/p&gt;</description>
    </item>
    <item>
      <title>The Symbol-Keyed State Accessor pattern</title>
      <link>https://blog.thepete.net/blog/2016/11/20/the-symbol-keyed-state-accessor-pattern/</link>
      <pubDate>Sun, 20 Nov 2016 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2016/11/20/the-symbol-keyed-state-accessor-pattern/</guid>
      <description>&lt;p&gt;In this post I&amp;rsquo;ll show three different techniques for encapsulating internal state in JavaScript, concluding with my preferred approach, a pattern I&amp;rsquo;m calling &amp;ldquo;Symbol-keyed State Accessor&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;I was in a discussion about how to implement the Value Object pattern in JavaScript recently. Most of the examples folks were proposing involved a prototypical approach to OOO, using either &lt;code&gt;class&lt;/code&gt; or &lt;code&gt;prototype&lt;/code&gt; to create a Value Object type, and managing the object&amp;rsquo;s internal state via &lt;code&gt;this&lt;/code&gt;. Here&amp;rsquo;s how one might build the basics of a &lt;code&gt;Money&lt;/code&gt; Value Object in that style:&lt;/p&gt;</description>
    </item>
    <item>
      <title>DIY stir plate for homebrew yeast starters</title>
      <link>https://blog.thepete.net/blog/2015/12/03/diy-stir-plate-for-homebrew-yeast-starters/</link>
      <pubDate>Thu, 03 Dec 2015 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2015/12/03/diy-stir-plate-for-homebrew-yeast-starters/</guid>
      <description>&lt;p&gt;I brew beer as a hobby, and one of the secrets to really good homebrew is happy, healthy, plentiful yeast at the start of fermentation. Creating a yeast starter really helps with this, and a good yeast starter requires a stir plate to keep the yeast in suspension.&lt;/p&gt;&#xA;&lt;p&gt;Stir plates aren&amp;rsquo;t &lt;em&gt;super&lt;/em&gt; expensive, but at &lt;a href=&#34;http://www.northernbrewer.com/maelstrom-stir-plate&#34;&gt;around&lt;/a&gt; &lt;a href=&#34;http://www.morebeer.com/products/hanna-magnetic-stir-plate.html&#34;&gt;100USD&lt;/a&gt; they&amp;rsquo;re not something you&amp;rsquo;d buy on a whim. I found a lot of information online on how to make your own DIY stir plate using an old computer fan and some magnets, and since I also like tinkering with electronics I decided to give it a go. After a couple of design iterations I&amp;rsquo;m really happy with how this project turned out.&lt;/p&gt;</description>
    </item>
    <item>
      <title>The Ultimate Traveler&#39;s Coffee Kit</title>
      <link>https://blog.thepete.net/blog/2015/06/21/the-ultimate-travelers-coffee-kit/</link>
      <pubDate>Sun, 21 Jun 2015 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2015/06/21/the-ultimate-travelers-coffee-kit/</guid>
      <description>&lt;p&gt;I travel a fair bit for work and have discovered that when you&amp;rsquo;re living in a hotel it&amp;rsquo;s the simple comforts that you miss the most. Near the top of my list of simple comforts is a good cup of coffee soon after I wake up. The hideous coffee tea-bag things that most hotel rooms provide barely counts as coffee, let alone &lt;em&gt;good&lt;/em&gt; coffee. A year or so ago I set out to find a way to make good coffee in a hotel room without using up a ton of luggage real-estate. Today I am very happy with my setup, apparently to the point that I&amp;rsquo;m OK with writing a blog post about it titled &amp;ldquo;The Ultimate Traveler&amp;rsquo;s Coffee Kit&amp;rdquo;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>video for my different.js talk</title>
      <link>https://blog.thepete.net/blog/2014/09/02/video-for-my-different-dot-js-talk/</link>
      <pubDate>Tue, 02 Sep 2014 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2014/09/02/video-for-my-different-dot-js-talk/</guid>
      <description>&lt;p&gt;I had the opportunity to present at &lt;a href=&#34;http://forwardjs.com/&#34;&gt;Forward JS&lt;/a&gt; a few weeks ago on &amp;ldquo;different.js&amp;rdquo;. No, the presentation wasn&amp;rsquo;t about a new, shiny, artisinally-crafted micro-framework. I talked about how to &amp;ldquo;level up&amp;rdquo; at JavaScript by introducing artificial constraints which force you to approach things a different way. I worked through a specific example, abstaining from the use of &lt;code&gt;this&lt;/code&gt; and prototypes in favor of closures.&lt;/p&gt;&#xA;&lt;p&gt;Slides for the talk are &lt;a href=&#34;https://speakerdeck.com/phodgson/different-dot-js-forward-js-2014&#34;&gt;here&lt;/a&gt;, video is below (thanks &lt;a href=&#34;https://thenewcircle.com/s/post/1656/differentjs_video_forward_js&#34;&gt;New Circle&lt;/a&gt;).&lt;/p&gt;</description>
    </item>
    <item>
      <title>optimizing 3rd party JavaScript loading</title>
      <link>https://blog.thepete.net/blog/2014/08/27/optimizing-3rd-party-javascript-loading/</link>
      <pubDate>Wed, 27 Aug 2014 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2014/08/27/optimizing-3rd-party-javascript-loading/</guid>
      <description>&lt;p&gt;I was doing some research today on preventing slow/flakey external javascript files from 3rd-party sources from slowing down your perceived page load times. Things like tracking pixels and chat widgets are generally loaded via script tags, and if you&amp;rsquo;re not careful then one rogue provider can create a really poor experience for users on your site.&lt;/p&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t have any original thoughts here, just a collection of resources which I found that summarize techniques I&amp;rsquo;ve heard about in the past but not had to use directly until now.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Rails as an SOA Client</title>
      <link>https://blog.thepete.net/blog/2014/05/15/rails-as-an-soa-client/</link>
      <pubDate>Thu, 15 May 2014 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2014/05/15/rails-as-an-soa-client/</guid>
      <description>&lt;p&gt;I got to present a talk at &lt;a href=&#34;http://railsconf.com/&#34;&gt;RailsConf&lt;/a&gt; this year. video is &lt;a href=&#34;http://www.confreaks.com/videos/3347-railsconf-rails-as-an-soa-client&#34;&gt;here&lt;/a&gt;, slides are &lt;a href=&#34;https://speakerdeck.com/phodgson/railsconf2014&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;My talk was about Rails as an SOA client. I talked about things like Conway&amp;rsquo;s Law, Contract Testing, Hexagonal Architecture, the faraday gem, and HTTP Caching.&lt;/p&gt;</description>
    </item>
    <item>
      <title>the 5 rules of an awesome dev toolchain</title>
      <link>https://blog.thepete.net/blog/2014/03/28/_-attributes-of-an-amazing-dev-toolchain/</link>
      <pubDate>Fri, 28 Mar 2014 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2014/03/28/_-attributes-of-an-amazing-dev-toolchain/</guid>
      <description>&lt;div class=&#34;pullquote-container&#34;&gt;&#xA;  &lt;div class=&#34;pullquote&#34;&gt;&#xA;       ./go can eventually become the primary interface into the dev tooling for the project.&#xA;  &lt;/div&gt;&#xA;&lt;p&gt;Every &lt;a href=&#34;http://www.thoughtworks.com&#34;&gt;ThoughtWorks&lt;/a&gt; project I&amp;rsquo;ve ever been on has a script in the root of the project repo, often named &lt;code&gt;./go&lt;/code&gt; or &lt;code&gt;./go.sh&lt;/code&gt; (or &lt;code&gt;./go.bat&lt;/code&gt; if you&amp;rsquo;re very unlucky). This script often starts life as the script which the CI server runs to test the project. It soon acquires extra capabilities. It becomes the way by which developers perform a pre-commit check before pushing their changes. It becomes the script to run when you first get started on the project to download all the various project dependencies.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Microstatic: radically simple static microsites</title>
      <link>https://blog.thepete.net/blog/2014/01/17/microstatic-radically-simple-static-microsites/</link>
      <pubDate>Fri, 17 Jan 2014 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2014/01/17/microstatic-radically-simple-static-microsites/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m a bit fan of static sites, and have created &lt;a href=&#34;http://cards.thepete.net&#34;&gt;a&lt;/a&gt; &lt;a href=&#34;http://snakes.thepete.net&#34;&gt;fair&lt;/a&gt; &lt;a href=&#34;http://bbfw.thepete.net&#34;&gt;few&lt;/a&gt; &lt;a href=&#34;http://color-mixing.thepete.net&#34;&gt;little&lt;/a&gt; &lt;a href=&#34;http://codemash.thepete.net&#34;&gt;static&lt;/a&gt; &lt;a href=&#34;http://buglandia.thepete.net&#34;&gt;one-page&lt;/a&gt; demos and toy apps over the last few years. I like to host these off of S3 and expose them under subdomains of my domain, thepete.net. In fact, you&amp;rsquo;re reading one of those S3-hosted static sites right now!&lt;/p&gt;&#xA;&lt;p&gt;With modern infrastructure like S3 and Route 53 the process of setting up a new microsite is pretty straightforward, but the manual steps started to grate on me after a while. &lt;em&gt;&amp;ldquo;I&amp;rsquo;m a dev&amp;rdquo;&lt;/em&gt;, I thought to myself. &lt;em&gt;&amp;ldquo;Why can&amp;rsquo;t I automate this?&amp;rdquo;&lt;/em&gt;. And so of course I did.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Assertions in Page Objects</title>
      <link>https://blog.thepete.net/blog/2013/09/13/assertions-in-page-objects/</link>
      <pubDate>Fri, 13 Sep 2013 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2013/09/13/assertions-in-page-objects/</guid>
      <description>&lt;p&gt;Martin Fowler recently added a &lt;a href=&#34;http://martinfowler.com/bliki/PageObject.html&#34;&gt;bliki entry for the Page Object pattern&lt;/a&gt;. It&amp;rsquo;s a good writeup - if you haven&amp;rsquo;t read it I recommend doing so now. &lt;a href=&#34;http://martinfowler.com/bliki/PageObject.html&#34;&gt;Go ahead&lt;/a&gt;. I&amp;rsquo;ll wait.&lt;/p&gt;&#xA;&lt;p&gt;The entry sparked a discussion on an internal ThoughtWorks mailing list as to whether Page Objects should include assertions or not. In fact Martin mentions this difference of opinion in the bliki entry itself. I fell on the side of favoring page objects &lt;em&gt;with&lt;/em&gt; assertions baked in but couldn&amp;rsquo;t come up with a compelling reason why until I was working on some Capybara-based page objects with a client QA today.&lt;/p&gt;</description>
    </item>
    <item>
      <title>introducing rack-flags</title>
      <link>https://blog.thepete.net/blog/2013/08/24/introducing-rack-flags/</link>
      <pubDate>Sat, 24 Aug 2013 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2013/08/24/introducing-rack-flags/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m pleased to announce &lt;a href=&#34;https://github.com/moredip/rack-flags&#34;&gt;rack-flags&lt;/a&gt;, a very simple way to add &lt;a href=&#34;http://martinfowler.com/bliki/FeatureToggle.html&#34;&gt;feature flags/bits/toggles&lt;/a&gt; to your Rails app (or any other rack-based web app).&lt;/p&gt;&#xA;&lt;p&gt;The rack-flags gem allows you to define a set of &lt;em&gt;feature flags&lt;/em&gt; which can be turned either off or on for any user. Your application code inspects the state of these feature flags when processing a web request and uses that information to modify how it handles that request.&lt;/p&gt;</description>
    </item>
    <item>
      <title>iOS Unit Testing Workshop</title>
      <link>https://blog.thepete.net/blog/2013/08/06/ios-unit-testing-workshop/</link>
      <pubDate>Tue, 06 Aug 2013 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2013/08/06/ios-unit-testing-workshop/</guid>
      <description>&lt;p&gt;##TL;DR&#xA;I&amp;rsquo;ll be running a couple of free workshops on iOS Unit Testing in San Francisco in late August/early September. If you&amp;rsquo;d like to attend please fill out &lt;a href=&#34;https://docs.google.com/a/thoughtworks.com/forms/d/1L4smy4zlV6xP0Ufy_i3GjuhAW64xXzqsmbCGXkCXblA/viewform&#34;&gt;this simple form&lt;/a&gt; and I&amp;rsquo;ll be in touch with details.&lt;/p&gt;&#xA;&lt;p&gt;##Why is it free? What&amp;rsquo;s the catch?&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m preparing to run a &lt;a href=&#34;https://thestrangeloop.com/sessions/unit-testing-for-ios&#34;&gt;paid 3 hour workshop on iOS unit testing&lt;/a&gt; for the upcoming super-awesome &lt;a href=&#34;https://thestrangeloop.com/&#34;&gt;StrangeLoop conference&lt;/a&gt;. As part of that prep I&amp;rsquo;ll be doing a couple of &amp;lsquo;dry runs&amp;rsquo; of the workshop so I can fine tune the content, delivery, pacing, etc. You are cordially invited to attend. You get to learn a bunch about iOS unit testing, I get to hone and refine the workshop. A win/win for us both.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Using Travis CI and xctool to build and test iOS apps</title>
      <link>https://blog.thepete.net/blog/2013/05/07/using-travis-ci-and-xctool-to-build-and-test-ios/</link>
      <pubDate>Tue, 07 May 2013 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2013/05/07/using-travis-ci-and-xctool-to-build-and-test-ios/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;http://travis-ci.org&#34;&gt;Travis CI&lt;/a&gt; is a cloud-based Continuous Integration service which is free to use (but only on &lt;em&gt;public&lt;/em&gt; github projects). They &lt;a href=&#34;http://sauceio.com/index.php/2013/04/travis-ci-for-os-x-and-ios-powered-by-sauce/&#34;&gt;recently&lt;/a&gt; &lt;a href=&#34;http://about.travis-ci.org/blog/introducing-mac-ios-rubymotion-testing/&#34;&gt;announced&lt;/a&gt; support for OS X agents, which means you can now use Travis to build and test iOS applications. In this post I&amp;rsquo;ll show how I set up basic CI for an example iOS app using Travis, with the help of &lt;a href=&#34;https://github.com/facebook/xctool&#34;&gt;xctool&lt;/a&gt;. xctool is the &amp;lsquo;better xcodebuild&amp;rsquo; which Facebook recently open-sourced. It allows you to not only build your app on the command line but also run your app&amp;rsquo;s unit tests from the command line with the same capabilities that XCode offers when you run the tests from the IDE proper.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Test-driven Backbone.js - Part Three</title>
      <link>https://blog.thepete.net/blog/2013/02/24/test-driven-backbone-dot-js-part-three/</link>
      <pubDate>Sun, 24 Feb 2013 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2013/02/24/test-driven-backbone-dot-js-part-three/</guid>
      <description>&lt;p&gt;In the &lt;a href=&#34;./blog/2013/01/23/test-driven-backbone-dot-js-part-one/&#34;&gt;previous&lt;/a&gt; &lt;a href=&#34;./blog/2013/01/23/test-driven-backbone-dot-js-part-two/&#34;&gt;posts&lt;/a&gt; in this series we&amp;rsquo;ve done some test-driven development of Backbone Models, Collections, and Views. In this post I&amp;rsquo;m going to cover another role which I believe should be present in most &lt;abbr title=&#34;Single Page App&#34;&gt;SPA&lt;/abbr&gt; Backbone apps: Controllers.&lt;/p&gt;&#xA;&lt;h2 id=&#34;controllers-in-a-backbone-app&#34;&gt;Controllers in a Backbone app&lt;/h2&gt;&#xA;&lt;p&gt;There&amp;rsquo;s nothing in the Backbone.js library for building Controllers. There&amp;rsquo;s not a &lt;code&gt;Backbone.Controller&lt;/code&gt; for you to extend from. But that doesn&amp;rsquo;t mean that Controllers don&amp;rsquo;t have a part to play in your Backbone app. I suspect that the reason we don&amp;rsquo;t see Backbone.Controller in the library is simply because there isn&amp;rsquo;t much helpful shared functionality that could be put there. The Controller role is more loosly defined than other more concrete roles such as View or Model and so there&amp;rsquo;s not a need for a concrete base implementation in the Backbone.js library. However that does &lt;em&gt;not&lt;/em&gt; mean that your app wouldn&amp;rsquo;t benefit from code organized under the Controller role.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Test-driven Backbone.js  - Part One</title>
      <link>https://blog.thepete.net/blog/2013/01/23/test-driven-backbone-dot-js-part-one/</link>
      <pubDate>Wed, 23 Jan 2013 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2013/01/23/test-driven-backbone-dot-js-part-one/</guid>
      <description>&lt;p&gt;In this series of posts I&amp;rsquo;m going to walk through some practical details on how we can develop Backbone.js applications in a test-driven manner. Developing this way leads to better structured applications, as we&amp;rsquo;ll discover.&lt;/p&gt;&#xA;&lt;h2 id=&#34;setup&#34;&gt;Setup&lt;/h2&gt;&#xA;&lt;p&gt;We&amp;rsquo;ll be using backbone and underscore to build a single page app which simulates a card wall. We&amp;rsquo;ll be writing our app and our tests using coffeescript. If there&amp;rsquo;s enough interest I&amp;rsquo;d be happy to set up a JavaScript translation of the code snippets - please &lt;a href=&#34;mailto:blog@thepete.net&#34;&gt;let me know&lt;/a&gt;. We&amp;rsquo;ll be  using Jasmine as our test runner and we&amp;rsquo;ll be using sinon.js to create test doubles (mocks and stubs). We&amp;rsquo;ll also use a few other small utilities and plugins as we go.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Test-driven Backbone.js - Part Two</title>
      <link>https://blog.thepete.net/blog/2013/01/23/test-driven-backbone-dot-js-part-two/</link>
      <pubDate>Wed, 23 Jan 2013 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2013/01/23/test-driven-backbone-dot-js-part-two/</guid>
      <description>&lt;p&gt;In the &lt;a href=&#34;./blog/2013/01/23/test-driven-backbone-dot-js-part-one/&#34;&gt;previous installment&lt;/a&gt; of this series we looked at the basics of test-driving the development of a Backbone.js app by TDDing some simple functionality for Backbone Models.&lt;/p&gt;&#xA;&lt;p&gt;In this installment we&amp;rsquo;re going to get a bit more advanced, looking at how we can test-drive Backbone Views. Because views integrate with the DOM they can be a little more fiddly to test, but TDDing your views is still a very achievable goal.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Deploying to Heroku from CI - the gory details</title>
      <link>https://blog.thepete.net/blog/2013/01/22/deploying-to-heroku-from-ci-the-gory-details/</link>
      <pubDate>Tue, 22 Jan 2013 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2013/01/22/deploying-to-heroku-from-ci-the-gory-details/</guid>
      <description>&lt;p&gt;In my &lt;a href=&#34;./blog/2013/01/21/deploying-to-heroku-from-ci&#34;&gt;previous post&lt;/a&gt; I discussed why you might want to deploy to Heroku as part of a CI build. I demonstrated how my &lt;code&gt;heroku-headless&lt;/code&gt; gem makes it very easy to script such a deployment. In this post I&amp;rsquo;ll go into the details on how that gem does its work. I&amp;rsquo;ll talk about what the Heroku deployment tooling expects to be available, why that&amp;rsquo;s not necessarily going to be there in the context of a CI build environment, and how the gem helps resolve that.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Deploying to Heroku from CI</title>
      <link>https://blog.thepete.net/blog/2013/01/21/deploying-to-heroku-from-ci/</link>
      <pubDate>Mon, 21 Jan 2013 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2013/01/21/deploying-to-heroku-from-ci/</guid>
      <description>&lt;p&gt;If you&amp;rsquo;re working on top of a modern web stack then the &lt;a href=&#34;http://www.heroku.com/&#34;&gt;Heroku&lt;/a&gt; hosting platform is a compelling option for standing up an instance of your app with what is usually a trivial amount of effort. No need to provision EC2 servers, write chef recipes, or mess with deploy tools. Just run a couple of commands in the shell and then &lt;code&gt;git push heroku&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;heroku-as-a-staging-environment&#34;&gt;Heroku as a staging environment&lt;/h2&gt;&#xA;&lt;p&gt;This makes Heroku a compelling choice for hosting a staging environment for your application. Staging environment contains the latest &amp;lsquo;good&amp;rsquo; build of your app. They are used for things like automated acceptance testing, manual QA, story sign-off, or internal demos.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Writing iOS acceptance tests using Kiwi</title>
      <link>https://blog.thepete.net/blog/2012/11/18/writing-ios-acceptance-tests-using-kiwi/</link>
      <pubDate>Sun, 18 Nov 2012 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2012/11/18/writing-ios-acceptance-tests-using-kiwi/</guid>
      <description>&lt;p&gt;In this post I&amp;rsquo;ll describe an experiment where rather than using &lt;a href=&#34;http://testingwithfrank.com&#34;&gt;Frank&lt;/a&gt; to write iOS acceptance tests I instead combined &lt;a href=&#34;https://github.com/allending/Kiwi&#34;&gt;Kiwi&lt;/a&gt; with the low-level libraries that Frank uses internally. This allowed me to write acceptance tests in pure Objective-C which run in the app process itself, very similarly to the way &lt;a href=&#34;http://github.com/square/kif&#34;&gt;KIF&lt;/a&gt; works.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what&#34;&gt;What?&lt;/h2&gt;&#xA;&lt;p&gt;Before I start, let me be clear that I personally wouldn&amp;rsquo;t use this approach to writing acceptance tests. I much prefer using a higher-level language like ruby to write these kinds of tests. The test code is way less work and way more expressive, assuming you&amp;rsquo;re comfortable in ruby. And that&amp;rsquo;s why I wanted to try this experiment. I&amp;rsquo;ve spoken to quite a few iOS developers over time who are &lt;em&gt;not&lt;/em&gt; comfortable writing tests in ruby. They are more comfortable in Objective-C than anything else, and would like to write their tests in the same language they use for their production code. Fair enough.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Cookie-based feature flag overrides</title>
      <link>https://blog.thepete.net/blog/2012/11/06/cookie-based-feature-flag-overrides/</link>
      <pubDate>Tue, 06 Nov 2012 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2012/11/06/cookie-based-feature-flag-overrides/</guid>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;If you&amp;rsquo;re practicing Continuous Delivery then you&amp;rsquo;re probably using Feature Flags to hide half-baked features which are being shipped into production as latent code. It&amp;rsquo;s useful to allow individual users to &lt;strong&gt;manually override&lt;/strong&gt; those feature flags so that they can get a preview of these latent features before they are released to everyone. People wanting to do this would be testers, product stakeholders, and external beta testers.&lt;/p&gt;&#xA;&lt;p&gt;This is a similar concept to the Canary Releasing approach which organizations like Facebook use to trial new features. The difference is that with manual overrides each individual is opting in for features themselves, as opposed to being arbitrarily placed into the pool of users assigned as canaries.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Frank with CocoaPods</title>
      <link>https://blog.thepete.net/blog/2012/10/16/frank-with-cocoapods/</link>
      <pubDate>Tue, 16 Oct 2012 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2012/10/16/frank-with-cocoapods/</guid>
      <description>&lt;h2 id=&#34;a-frank-field-trip&#34;&gt;A Frank field trip&lt;/h2&gt;&#xA;&lt;p&gt;Today I&amp;rsquo;m visiting &lt;a href=&#34;http://955dreams.com&#34;&gt;955 Dreams&lt;/a&gt; (the guys who make Band of the Day, amongst other things) visiting my friend (and their CTO) &lt;a href=&#34;https://twitter.com/chris_stevenson&#34;&gt;Chris&lt;/a&gt;. We had a fun time figuring out how to get &lt;a href=&#34;http://testingwithfrank.com&#34;&gt;Frank&lt;/a&gt; to play nicely with &lt;a href=&#34;http://cocoapods.org/&#34;&gt;CocoaPods&lt;/a&gt;. It wasn&amp;rsquo;t that tricky, and I&amp;rsquo;m going to document what we found here to hopefully make it easier for other Cocoapod users.&lt;/p&gt;&#xA;&lt;h2 id=&#34;problem-the-first&#34;&gt;Problem the first&lt;/h2&gt;&#xA;&lt;p&gt;Frank had trouble with cocoapods for two reasons. Firstly when frankifying the app we needed to frankify the app&amp;rsquo;s Xcode &lt;em&gt;project&lt;/em&gt;, but to build the app we needed to point &lt;code&gt;frank build&lt;/code&gt; at the main Xcode &lt;em&gt;workspace&lt;/em&gt;, so that cocoapods could work its magic during the build. This was simply a case of passing the appropriate &lt;code&gt;--workspace&lt;/code&gt; and &lt;code&gt;--scheme&lt;/code&gt; arguments to &lt;code&gt;frank build&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Towards Frank 1.0</title>
      <link>https://blog.thepete.net/blog/2012/09/06/towards-frank-1-point-0/</link>
      <pubDate>Thu, 06 Sep 2012 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2012/09/06/towards-frank-1-point-0/</guid>
      <description>&lt;p&gt;One of the many geeky hats I wear is that of maintainer for &lt;a href=&#34;http://www.testingwithfrank.com&#34;&gt;Frank&lt;/a&gt;, an open-source tool for automated testing of native iOS applications. Frank has been around for over 2 years now, which is actually quite a long time in the mobile space. It has evolved a fair amount in that time, but has had a surprisingly small amount of change to the core architecture. I&amp;rsquo;m actually quite proud of that. I think that the core concepts have been proven out enough that Frank is ready for a 1.0 release which cleans up some long-standing cruft and solidifies at least parts of its client/server API.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Introducing PublicAutomation</title>
      <link>https://blog.thepete.net/blog/2012/08/20/introducing-publicautomation/</link>
      <pubDate>Mon, 20 Aug 2012 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2012/08/20/introducing-publicautomation/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m excited to announce &lt;a href=&#34;http://github.com/TestingWithFrank/PublicAutomation&#34;&gt;PublicAutomation&lt;/a&gt;, &lt;strong&gt;a friendly wrapper around Apple&amp;rsquo;s private UIAutomation framework&lt;/strong&gt;. PublicAutomation allows you to use Apple&amp;rsquo;s own private framework to simulate user interactions (taps, swipes, keyboard typing) via a simple Objective-C API.&lt;/p&gt;&#xA;&lt;p&gt;Previous approaches to this problem have relied on reverse-engineering and monkey-patching iOS&amp;rsquo;s touch events system. PublicAutomation takes a different approach. It links in the low-level API of the private framework which Apple itself uses for its own UIAutomation tooling. PublicAutomation provides the stability of Apple&amp;rsquo;s proprietary UIAutomation tool with the flexibility of an open source library maintained by the community.&lt;/p&gt;</description>
    </item>
    <item>
      <title>marker branches in git</title>
      <link>https://blog.thepete.net/blog/2012/08/09/marker-branches-in-git/</link>
      <pubDate>Thu, 09 Aug 2012 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2012/08/09/marker-branches-in-git/</guid>
      <description>&lt;p&gt;In my &lt;a href=&#34;./blog/2012/08/02/octopress-deployment-pipeline/&#34;&gt;last post&lt;/a&gt; I talked about setting up a basic deployment pipeline using marker branches in git to keep track of what was where.&lt;/p&gt;&#xA;&lt;p&gt;In this post I want to go into a little more detail describing how these marker branches work. To do that I&amp;rsquo;ll walk through a simple example showing the state of a git repo as code moves through being committed, being pushed to master, deployed to pre-prod, and finally promoted to prod.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Octopress deployment pipeline</title>
      <link>https://blog.thepete.net/blog/2012/08/02/octopress-deployment-pipeline/</link>
      <pubDate>Thu, 02 Aug 2012 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2012/08/02/octopress-deployment-pipeline/</guid>
      <description>&lt;p&gt;I spent a fun evening recently setting up a deployment pipeline for this blog. I&amp;rsquo;d like to share some details on what I set up and why.&lt;/p&gt;&#xA;&lt;p&gt;The motivation was that I wanted some way to publish draft blog entries for other people to review, but I didn&amp;rsquo;t want these drafts to show up on my public site.  I played with Octopress&amp;rsquo;s &lt;code&gt;published: false&lt;/code&gt; option, but it really didn&amp;rsquo;t give me what I needed. Then I saw someone commenting that the ideal would be to have a preview version of the entire site available at a separate url. A &lt;strong&gt;pre-production environment&lt;/strong&gt;, essentially. Hmm, I thought. Every web project I work on has one of these. It&amp;rsquo;s used to showcase the version of the system which is going to be released to production. That&amp;rsquo;s what I need - why don&amp;rsquo;t I just set that up for my blog?&lt;/p&gt;</description>
    </item>
    <item>
      <title>Running Frank as part of iOS CI</title>
      <link>https://blog.thepete.net/blog/2012/07/22/running-frank-as-part-of-ios-ci/</link>
      <pubDate>Sun, 22 Jul 2012 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2012/07/22/running-frank-as-part-of-ios-ci/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;http://testingwithfrank.com&#34;&gt;Frank&lt;/a&gt; is a tool that allows you to run automated acceptance tests against your native iOS application. A major reason for creating &lt;em&gt;automated&lt;/em&gt; acceptance tests is so that you can run them as part of your &lt;a href=&#34;http://martinfowler.com/articles/continuousIntegration.html&#34;&gt;Continuous Integration&lt;/a&gt; (CI) process. Doing this enables a rapid feedback loop where a developer checking in code is informed very quickly if that change caused a defect in your app.&lt;/p&gt;&#xA;&lt;p&gt;In this post I&amp;rsquo;ll show how to configure a basic CI setup using &lt;a href=&#34;http://jenkinsci.org&#34;&gt;Jenkins&lt;/a&gt; which will build your app and run Frank tests against it every time you check in code. CI for iOS projects don&amp;rsquo;t seem to be a common practice. This is a shame because the CI can bring just as many benefits for iOS applications as for other technologies. I suspect part of the reason CI is less popular is that Apple doesn&amp;rsquo;t make it particularly easy. It&amp;rsquo;s not a trivial task to automate things like building your application and running unit tests. Things are moving in the right direction though, with both Apple and open-source developers making it simpler to integrate a dev toolchain into a CI setup.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Using the UIAutomation private framework</title>
      <link>https://blog.thepete.net/blog/2012/07/11/using-the-uiautomation-private-framework/</link>
      <pubDate>Wed, 11 Jul 2012 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2012/07/11/using-the-uiautomation-private-framework/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve recently spent a few hours investigating how feasible it would be to use Apple&amp;rsquo;s private UIAutomation framework to simulate user interactions in iOS apps. The motivation for this is of course being able to use this for &lt;a href=&#34;http://testingwithfrank.com&#34;&gt;Frank&lt;/a&gt;, the UI testing tool I maintain. This post will summarize my progress to date. You can also check out my work-in-progress &lt;a href=&#34;https://github.com/moredip/Frank/tree/uiautomation&#34;&gt;uiautomation branch&lt;/a&gt; for Frank. Note that that branch is &lt;em&gt;very&lt;/em&gt; rough and ready at the moment. I pushed it up to my github repo just so anyone who wants to see progress so far can do so.&lt;/p&gt;</description>
    </item>
    <item>
      <title>writing your first Frank test</title>
      <link>https://blog.thepete.net/blog/2012/06/24/writing-your-first-frank-test/</link>
      <pubDate>Sun, 24 Jun 2012 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2012/06/24/writing-your-first-frank-test/</guid>
      <description>&lt;p&gt;You&amp;rsquo;ve heard about how awesome &lt;a href=&#34;http://www.testingwithfrank.com&#34;&gt;Frank&lt;/a&gt; is and you&amp;rsquo;re all fired up about getting some automated functional testing set up for your iOS app. Now you&amp;rsquo;re ready to start writing your first test. In this article I&amp;rsquo;ll cover the fundamentals of writing Frank tests, using an open source iOS application written for the 2012 Olympic Games as an example.&lt;/p&gt;&#xA;&lt;h2 id=&#34;get-the-code-for-your-app&#34;&gt;get the code for your app&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;m guessing you&amp;rsquo;ll already have the code for your own app, but if you&amp;rsquo;d like to follow along with the examples in this post you&amp;rsquo;ll want to download the sample app I&amp;rsquo;m using. You&amp;rsquo;ll find it on github &lt;a href=&#34;https://github.com/Frahaan/2012-Olympics-iOS--iPad-and-iPhone--source-code&#34;&gt;here&lt;/a&gt;. Create a local clone of that repo with &lt;code&gt;git clone https://github.com/Frahaan/2012-Olympics-iOS--iPad-and-iPhone--source-code.git&lt;/code&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Lowering Frank&#39;s barrier to entry</title>
      <link>https://blog.thepete.net/blog/2012/06/16/lowering-franks-barrier-to-entry/</link>
      <pubDate>Sat, 16 Jun 2012 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2012/06/16/lowering-franks-barrier-to-entry/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve always known that it&amp;rsquo;s really important new users of &lt;a href=&#34;http://www.testingwithfrank.com&#34;&gt;Frank&lt;/a&gt; to easily get started by creating a Frankified version of their app - a build which has been enhanced with the embedded server which lets Frank do its magic.&lt;/p&gt;&#xA;&lt;p&gt;When the project was first started it was really quite complex to setup. You had to add a bunch of source code to your app, and then modify a few bits of your app&amp;rsquo;s startup code.&lt;/p&gt;</description>
    </item>
    <item>
      <title>The Birth Of a Domain Object In Ruby</title>
      <link>https://blog.thepete.net/blog/2012/06/09/the-birth-of-a-domain-object-in-ruby/</link>
      <pubDate>Sat, 09 Jun 2012 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2012/06/09/the-birth-of-a-domain-object-in-ruby/</guid>
      <description>&lt;p&gt;Software designs don&amp;rsquo;t pop into existance fully formed. They evolve over time. In this post I&amp;rsquo;m going to show how a concept can grow from a simple method parameter to an all-growed-up Domain Object.&lt;/p&gt;&#xA;&lt;h2 id=&#34;initial-requirements&#34;&gt;Initial requirements&lt;/h2&gt;&#xA;&lt;p&gt;Imagine we&amp;rsquo;re building some code that will take bug reports from a user and submit them to a third-party bug tracking service. We expose an HTTP endpoint in a sinatra app to allow this:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Feature Flags in JavaScript</title>
      <link>https://blog.thepete.net/blog/2012/05/09/javascript-feature-flags/</link>
      <pubDate>Wed, 09 May 2012 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2012/05/09/javascript-feature-flags/</guid>
      <description>&lt;p&gt;On a recent project we were applying Continous Delivery practices and were releasing to production reasonably frequently - sometimes multiple times a week. We didn&amp;rsquo;t want to expose features which were under active development in our production environment but we also wanted to avoid feature branches. I&amp;rsquo;m going to describe the simple approach we used to solve this problem using &lt;em&gt;feature flagging&lt;/em&gt; with javascript and CSS.&lt;/p&gt;&#xA;&lt;h1 id=&#34;what-are-feature-flags&#34;&gt;What are feature flags?&lt;/h1&gt;&#xA;&lt;p&gt;Features flags (aka feature bits, feature toggles) are a very useful technique for managing latent functionality within your application. You expose switches in your application which configure whether certain behavior is enabled or disabled. Typically your would use this pattern for functionality which is under active development and is not &amp;lsquo;fully baked&amp;rsquo;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Moving from Blogger to Octopress</title>
      <link>https://blog.thepete.net/blog/2012/02/08/blogger-to-octopress/</link>
      <pubDate>Wed, 08 Feb 2012 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2012/02/08/blogger-to-octopress/</guid>
      <description>&lt;p&gt;Yes, like many other dork bloggers I&amp;rsquo;ve jumped onto the &lt;a href=&#34;http://octopress.org&#34;&gt;Octopress&lt;/a&gt; bandwagon.&lt;/p&gt;&#xA;&lt;p&gt;A big concern I had with switching blogging platforms (I was previously on Blogger) was breaking links to my existing content. Part of my concern was in losing Google Juice (yes, I&amp;rsquo;m that vain), but I&amp;rsquo;m also aware that a couple of my posts about Frank have become sources of documentation which are linked to from a few different places on the web. I definitely did not want to break those links.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Class-less javascript</title>
      <link>https://blog.thepete.net/blog/2012/02/06/class-less-javascript/</link>
      <pubDate>Mon, 06 Feb 2012 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2012/02/06/class-less-javascript/</guid>
      <description>&lt;p&gt;It seems that &lt;a href=&#34;http://blog.thepete.net/blog/2012/02/06/class-less-javascript/&#34;&gt;every&lt;/a&gt; &lt;a href=&#34;http://www.prototypejs.org/learn/class-inheritance&#34;&gt;javascript&lt;/a&gt; &lt;a href=&#34;http://www.sencha.com/blog/countdown-to-ext-js-4-dynamic-loading-and-new-class-system&#34;&gt;framework&lt;/a&gt; &lt;a href=&#34;http://emberjs.com/#object_model&#34;&gt;of&lt;/a&gt; &lt;a href=&#34;http://sproutcore.com/docs/#doc=SC.Object&amp;amp;method=.extend&#34;&gt;a&lt;/a&gt; &lt;a href=&#34;http://developer.yahoo.com/yui/examples/yahoo/yahoo_extend.html&#34;&gt;certain&lt;/a&gt; &lt;a href=&#34;http://dojotoolkit.org/documentation/tutorials/1.6/declare/&#34;&gt;size&lt;/a&gt; is compelled to implement some kind of pseudo-classical type system. I am now fairly convinced that there is no good reason for doing so. I&amp;rsquo;d like to describe an alternative approach to dealing with types in JavaScript.&lt;/p&gt;&#xA;&lt;p&gt;This approach comes from a recent project where my team was building a pure-JavaScript single-page web application. This wasn&amp;rsquo;t a huge codebase, but due to the single-page nature of the app it did have a reasonable amount of non-presentation logic which was implemented client-side in JavaScript. We needed a type system but we knew we didn&amp;rsquo;t want to try and force a classical-OO system onto JavaScript. The patterns we evolved gave us just enough structure while still allowing us to take advantage of the highly flexible and dynamic nature of JavaScript.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Testing Mobile Web Apps With WebDriver</title>
      <link>https://blog.thepete.net/blog/2011/09/02/testing-mobile-web-apps-with-webdriver/</link>
      <pubDate>Fri, 02 Sep 2011 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2011/09/02/testing-mobile-web-apps-with-webdriver/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;&lt;p&gt;We&amp;rsquo;ve been building mobile web apps using &lt;a href=&#34;http://jquerymobile.com&#34;&gt;JQuery Mobile&lt;/a&gt; with the main target being webkit-based mobile browsers - Android and iPhone, basically. We&amp;rsquo;re big fans of functional testing, so we spent some time figuring out how to get a good testing infrastructure set up for mobile app development. That&amp;rsquo;s what I&amp;rsquo;ll be sharing here.&lt;/p&gt;&lt;br /&gt;&#xA;&lt;h2 id=&#34;the-approach&#34;&gt;The approach&lt;/h2&gt;&lt;div class=&#34;figure&#34;&gt;&lt;img src=&#34;http://3.bp.blogspot.com/-D4Q_lhMFVMg/TmE6GcGW0UI/AAAAAAAAF9M/owO_VqcoS2w/s800/mobile_webdriver_diagram.png&#34; /&gt; &lt;/div&gt;&lt;br /&gt;&#xA;Our team members have a lot of experience using &lt;a href=&#34;http://cukes.info&#34;&gt;Cucumber&lt;/a&gt; to write automated acceptance tests, and we&amp;rsquo;re big fans. In previous projects we were building native iOS apps and testing them using Cucumber and &lt;a href=&#34;http://github.com/moredip/Frank&#34;&gt;Frank&lt;/a&gt;. We wanted to bring over some of the testing infrastructure we already had set up, so we decided on a similar approach. We still use Cucumber to drive tests in the iOS simulator, but instead of talking to a native app using Frank we are talking to our mobile web app via Selenium 2&amp;rsquo;s remote WebDriver protocol. In order to do this we run a special iOS app provided as part of Selenium 2 called &lt;a href=&#34;http://code.google.com/p/selenium/wiki/IPhoneDriver&#34;&gt;iWebDriver&lt;/a&gt; which hosts an embedded UIWebView and listens for WebDriver commands, in much the same way as a Frankified native app listens for Frankly commands. We launch the iWebDriver app using the same &lt;a href=&#34;http://github.com/moredip/SimLauncher&#34;&gt;SimLauncher gem&lt;/a&gt; which we&amp;rsquo;ve previously used to launch our native app for pre-commit and CI testing. To make our lives easier we use &lt;a href=&#34;https://github.com/jnicklas/capybara&#34;&gt;Capybara&lt;/a&gt;, which provides a nice ruby DSL for driving web apps and some useful cucumber step definitions out of the box. We configure Capybara to use the &lt;a href=&#34;https://rubygems.org/gems/selenium-webdriver&#34;&gt;selenium-webdriver gem&lt;/a&gt; to drive the iWebDriver-hosted web app via the WebDriver remote protocol.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Javascript Promises</title>
      <link>https://blog.thepete.net/blog/2011/07/02/javascript-promises/</link>
      <pubDate>Sat, 02 Jul 2011 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2011/07/02/javascript-promises/</guid>
      <description>&lt;p&gt;One of the interesting aspects of Javascript development is its asynchronous, event-driven nature. Any operation which will take a significant amount of time (e.g. a network request) is non-blocking. You don&amp;rsquo;t call a function and block until the operation completes. Instead functions are non-blocking - they return before the operation is complete. To obtain the result of the operation you provide &lt;em&gt;callbacks&lt;/em&gt; which are subsequently invoked once the operation completes, allowing you to move on to the next stage in your computation. This is a very powerful, efficient model that avoids the need for things like explicit threading and all the associated synchronization problems. However, it does make it a bit harder to implement a set of operations that need to happen one after another in sequential series. Instead of writing:&lt;/p&gt;</description>
    </item>
    <item>
      <title>retroactive quality metrics with git</title>
      <link>https://blog.thepete.net/blog/2011/05/08/retroactive-quality-metrics-with-git/</link>
      <pubDate>Sun, 08 May 2011 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2011/05/08/retroactive-quality-metrics-with-git/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;h2&gt;The Background&lt;/h2&gt;&#xA;&lt;p&gt;For a recent project retrospective we wanted to chart some metrics over the course of the entire project. Things like number of unit tests, test coverage, how long builds took to run, number of failing tests, etc. Taken in isolation these metrics aren&#39;t incredibly exciting, but when you plot them over time and hold that against other metrics like team morale, story point velocity, open defects, etc then often some interesting correlations can emerge.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Inspect the state of your running iOS app&#39;s UI with Symbiote</title>
      <link>https://blog.thepete.net/blog/2011/05/01/inspect-state-of-our-running-ios-apps/</link>
      <pubDate>Sun, 01 May 2011 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2011/05/01/inspect-state-of-our-running-ios-apps/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;h2&gt;What&#39;s Symbiote?&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/moredip/Frank&#34;&gt;Frank&lt;/a&gt; comes with a useful little tool called Symbiote. It&#39;s a little web app which is embedded &lt;i&gt;inside&lt;/i&gt; your native iOS application. Its purpose is to let you inspect the current state of your app&#39;s UI, and to test the UIQuery selectors which Frank uses to help it automate your app. Essentially Symbiote is Firebug for your native iOS app.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Recently I&#39;ve added some improvements to Symbiote, adding some new features and making it easier to use. &lt;a href=&#34;http://vimeo.com/22644221&#34;&gt;This screencast&lt;/a&gt; demonstrates most of the new-and-improved Symbiote.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Tutorial screencast on Frankifying your app</title>
      <link>https://blog.thepete.net/blog/2011/04/19/tutoral-creencast-on-frankifying-your/</link>
      <pubDate>Tue, 19 Apr 2011 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2011/04/19/tutoral-creencast-on-frankifying-your/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;p&gt;I maintain &lt;a href=&#34;http://github.com/moredip/Frank&#34;&gt;Frank&lt;/a&gt;, a tool which lets you write automated acceptance tests for your iOS app using Cucumber. I&#39;ve been trying to reduce the hurdles in getting started with Frank. My latest attempt is to record a &lt;a href=&#34;http://vimeo.com/22537514&#34;&gt;tutorial screencast&lt;/a&gt; showing how to take your existing app and &#39;Frankify&#39; it.&#xA;&lt;/p&gt;&#xA;&#xA;&lt;iframe src=&#34;http://player.vimeo.com/video/22537514?title=0&amp;amp;byline=0&amp;amp;portrait=0&#34; width=&#34;400&#34; height=&#34;300&#34; frameborder=&#34;0&#34;&gt;&lt;/iframe&gt;&#xA;&#xA;&lt;p&gt;&#xA;&#39;Frankifying&#39; an app is the process of adding a separate Frank target to your app which has the Frank server embedded into it, allowing it to respond to automation commands. It can seem like a bit of an intimidating process at first glance, but it&#39;s actually very simple. Hopefully running through the whole process in a 7 minute screencast demonstrates that. &#xA;&#xA;&lt;p&gt;Derek Longmuir has also contributed a &lt;a href=&#34;https://github.com/moredip/Frank/blob/master/tutorial/Tutorial.md&#34;&gt;nice in-depth tutorial writeup&lt;/a&gt; (which I was following along with when I recorded the screencast).&#xA;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Working with Indirect Input and Output in Unit Tests</title>
      <link>https://blog.thepete.net/blog/2011/01/04/working-with-indirect-input-and-output/</link>
      <pubDate>Tue, 04 Jan 2011 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2011/01/04/working-with-indirect-input-and-output/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;style type=&#34;text/css&#34;&gt; &#xA;div.figure {&#xA; //border: 1px dotted;&#xA; //padding-left: 1em;&#xA; //padding-right: 1em;&#xA; clear: both; &#xA; text-align: center;&#xA;}&#xA;&#xA;div.figure img {&#xA; border:0px;&#xA;}&#xA;&lt;/style&gt; &#xA; &#xA;&lt;h2 id=&#34;testing-how-a-unit-of-code-interacts-with-its-environment&#34;&gt;Testing how a unit of code interacts with its environment&lt;/h2&gt; &#xA; &#xA;&lt;p&gt;When testing a unit of code you need to both observe how the unit of code is interacting with the outside world and also control how the world interacts with it. &lt;/p&gt; &#xA; &#xA;&lt;p&gt;In a particuarly simple example, you might want to check that when an adder function is given a 2 and a 4 then it returns a 6. In this case you&amp;rsquo;re controlling what the &lt;strong&gt;System Under Test&lt;/strong&gt; (SUT) pulls in from its environment (the 2 and the 4) and also observing what it pushes out (the 6). In a more sophisticated example you might be testing a method which talks to a remote service, verifying that if it receives an error code when trying to read from the network then it logs the appropriate error message to a logger. Note that we&amp;rsquo;re still doing essentially the same thing here - controlling what the SUT pulls in from the environment (an error code in this case) and observing what it pushes out (a call to a logger in this case).&lt;/p&gt;</description>
    </item>
    <item>
      <title>Creating and publishing your first ruby gem</title>
      <link>https://blog.thepete.net/blog/2010/11/20/creating-and-publishing-your-first-ruby/</link>
      <pubDate>Sat, 20 Nov 2010 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2010/11/20/creating-and-publishing-your-first-ruby/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt; &#xA;&lt;p&gt;In this post I&amp;rsquo;m going to cover the basics of creating and publishing a gem using the &lt;code&gt;bundle gem&lt;/code&gt; command provided by &lt;a href=&#34;http://gembundler.com/&#34;&gt;Bundler&lt;/a&gt;. We&amp;rsquo;re going to use bundler to create a gem template for us. We&amp;rsquo;ll then take that skeleton gem, add some functionality to it, and publish it for all the world to use.&lt;/p&gt; &#xA; &#xA;&lt;p&gt;For the purposes of this tutorial I need a very simple example of something which you could conceivably want to release as a gem. How about a simple &lt;a href=&#34;http://sinatrarb.com&#34;&gt;Sinatra&lt;/a&gt; web app which tells you the time? Sure, that&amp;rsquo;ll work. We&amp;rsquo;ll call it Didactic Clock. In order to make this server implementation need more a couple of lines of code we&amp;rsquo;ll add the requirement that the clock tells you the time in a verbose form like &amp;ldquo;34 minutes past 4 o&amp;rsquo;clock, AM&amp;rdquo;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>timestamped-scenarios, a custom Cucumber formatter</title>
      <link>https://blog.thepete.net/blog/2010/11/20/timestamped-scenarios-custom-cucumber/</link>
      <pubDate>Sat, 20 Nov 2010 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2010/11/20/timestamped-scenarios-custom-cucumber/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;I just published a new Ruby gem called &lt;a href=&#34;https://rubygems.org/gems/timestamped-scenarios&#34;&gt;timestamped-scenarios&lt;/a&gt;. As usual the code is also &lt;a href=&#34;https://github.com/moredip/timestamped-scenarios&#34;&gt;available on github&lt;/a&gt;.&lt;br /&gt;&#xA;&lt;br /&gt;&#xA;&lt;h2&gt;What&#39;s this gem for?&lt;/h2&gt;&lt;p&gt;This gem provides custom cucumber formatters which append a test run timestamp to each scenario name as it is generated. a Timestamped::PrettyFormatter and Timestamped::HtmlFormatter are supplied already, but you can use the AddsTimestamp module to dynamically add timestamping to pretty much any Cucumber formatter.&lt;/p&gt;&lt;br /&gt;&#xA;&lt;p&gt;You might wonder why I created these formatters. I&#39;m currently working on an iOS project where we are using &lt;a href=&#34;https://github.com/moredip/Frank&#34;&gt;Frank&lt;/a&gt; and Cucumber to run automated acceptance tests against the application. We have integrated these acceptance tests into our CI build, and as part of that integration we record a screen capture movie of each test run. By adding timestamps to each scenario name we can easily skip to the part of the movie which shows that scenario executing. This is useful when trying to figure out the context around why a &lt;br /&gt;&#xA;specific scenario failed. &lt;/p&gt;</description>
    </item>
    <item>
      <title>Objective C memory errors pt II - Dangling Pointers</title>
      <link>https://blog.thepete.net/blog/2010/10/12/objective-c-memory-errors-pt-ii/</link>
      <pubDate>Tue, 12 Oct 2010 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2010/10/12/objective-c-memory-errors-pt-ii/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;p&gt;In my &lt;a href=&#34;./2010/10/common-objective-c-memory-management.html&#34;&gt;last post&lt;/a&gt; I talked about memory leaks in Objective C. In this post I&#39;ll take about the converse - dangling pointers. In iOS a dangling pointer happens when you maintain a reference to an object which has been deallocated. I&#39;d say the most common cause is failure to take ownership of an object you intend to maintain a reference to. Another common cause is when an object is accidently released multiple times by the same owner, leading to its retain count dropping to 0 and the object being deallocated before all the objects which hold references to the object release those references.&lt;br /&gt;&#xA;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Common Objective-C memory management errors, Part I</title>
      <link>https://blog.thepete.net/blog/2010/10/11/common-objective-c-memory-management/</link>
      <pubDate>Mon, 11 Oct 2010 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2010/10/11/common-objective-c-memory-management/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;I would say that the steepest learning curve for someone new to iOS development is having to manage your own memory using reference counting. Knowing when to retain and when to autorelease can seem like a black art until you understand the conventions which is used (extremely consistently, I might add) within Objective C libraries. Let&#39;s examine one very common mistake, which I will call the Property Assignment Memory Leak. I&#39;ve seen this a few times, and indeed committed this error myself during my first weeks of iOS development.&lt;br /&gt;&#xA;&lt;br /&gt;&#xA;&lt;h2&gt;The code&lt;/h2&gt;&lt;br /&gt;&#xA;Imagine we have a simple Duck class, which holds a feathers array:&lt;br /&gt;&#xA;&lt;br /&gt;&#xA;&lt;br /&gt;&#xA;&lt;pre class=&#34;brush: c; gutter: false&#34;&gt;@interface Duck : NSObject {&#xA;  NSArray *_feathers;&#xA;}&#xA;@property (nonatomic,retain) NSArray *feathers;&#xA;@end&#xA;&#xA;@implementation Duck&#xA;@synthesize feathers=_feathers;&#xA;@end&#xA;&lt;/pre&gt;&lt;br /&gt;&#xA;during construction we&#39;d like to initialize this array, so we create an init method as follows:&lt;br /&gt;&#xA;&lt;pre class=&#34;brush: c; gutter: false&#34;&gt;- (id) init&#xA;{&#xA;  self = [super init];&#xA;  if (self != nil) {&#xA;    self.feathers = [[NSArray alloc] init];&#xA;  }&#xA;  return self;&#xA;}&#xA;&lt;/pre&gt;Of course, we need to make sure we release our ownership of the feather array during deallocation, so we&#39;ll add a dealloc method like so:&lt;br /&gt;&#xA;&lt;pre class=&#34;brush: c; gutter: false&#34;&gt;- (void)dealloc {&#xA;  self.feathers = nil;&#xA;}&#xA;&lt;/pre&gt;&lt;br /&gt;&#xA;&lt;h2&gt;The Leak&lt;/h2&gt;So we&#39;re good here, right? The observant reader will note that no, we&#39;re not. the feathers array which we created in our init method will never be released. This will be a little easier to explain if I refactor the init method a little, making it more verbose by introducing a local variable to hold the array we are about to assign to the self.feathers property:&lt;br /&gt;&#xA;&lt;br /&gt;&#xA;&lt;pre class=&#34;brush: c;&#34;&gt;- (id) init&#xA;{&#xA;  self = [super init];&#xA;  if (self != nil) {&#xA;    // alloc will always create an object with a retain count already set to 1. In other &#xA;    // words, tempArray has ownership of the object.&#xA;    NSArray *tempArray = [[NSArray alloc] init]; &#xA;&#xA;    // assigning to self.feathers bumps the array&#39;s retain count up to 2. In other words, &#xA;    // now the feathers property also has ownership of the object.&#xA;    self.feathers = tempArray; &#xA;  }&#xA;&#xA;  // when we return tempArray goes out of scope without ever releasing ownership of the object it created. Memory leak!&#xA;  return self;&#xA;}&#xA;&lt;/pre&gt;&lt;br /&gt;&#xA;To make this clearer, I&#39;ll try and illustrate what happens as we move through the Duck object&#39;s lifecycle.&lt;br /&gt;&#xA;&lt;br /&gt;&#xA;&lt;div style=&#34;border: 1px dotted; padding-left: 1em; padding-right: 1em;&#34;&gt;&lt;img style=&#34;border:0px&#34;&#xA; src=&#34;http://1.bp.blogspot.com/_rzQrByr0AIg/TLPif9vTCHI/AAAAAAAAFYU/pvo2veXZj3A/s1600/ObjCMemLeak_1.png&#34; /&gt;&lt;p&gt;1) Here an instance of Duck has just been alloced, and we&#39;re about to execute init.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Podcast about Frank and test automation on iOS</title>
      <link>https://blog.thepete.net/blog/2010/08/07/podcast-about-frank-and-test-automation/</link>
      <pubDate>Sat, 07 Aug 2010 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2010/08/07/podcast-about-frank-and-test-automation/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;Some colleagues at Thoughtworks and I recently recorded a 30 minute podcast about &lt;a href=&#34;http://github.com/moredip/frank&#34;&gt;Frank&lt;/a&gt;, our UI automation tool for iPhone/iPad testing which I introduced in &lt;a href=&#34;http://blog.thepete.net/2010/07/frank-automated-acceptance-tests-for.html&#34;&gt;this post&lt;/a&gt;.&lt;br /&gt;&#xA;&lt;br /&gt;&#xA;In the podcast we cover:&lt;br /&gt;&#xA;&lt;ul&gt;&lt;li&gt;an overview of Frank, what it is and where it came from.&lt;/li&gt;&#xA;&lt;li&gt;How our testers and developers use Frank and cucumber at our current client (and how we&#39;d ideally &lt;i&gt;like&lt;/i&gt; to be using it).&lt;/li&gt;&#xA;&lt;li&gt;Alternatives to Frank, such as &lt;a href=&#34;http://github.com/unboxed/icuke&#34;&gt;iCuke&lt;/a&gt; and &lt;a href=&#34;http://github.com/undees/brominet&#34;&gt;brominet&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Some waffling by me about some of the reasoning that drove my design decisions with Frank. For example, avoiding XML and XPath for UI element selection.&lt;/li&gt;&#xA;&lt;li&gt;Symbiote, the little web app that we embed inside Frank which allows a test creator to inspect and play with the live iOS app as it&#39;s running.&lt;/li&gt;&#xA;&lt;li&gt;Writing cucumber feature files per-story versus per-feature.&lt;/li&gt;&#xA;&lt;li&gt;Handling the stateful nature of an iOS app in UI-level tests, and including Frank testing into a Continuous Integration system.&lt;/li&gt;&#xA;&lt;li&gt;The challenges of testing an app which integrates with large back-end systems.&lt;/li&gt;&#xA;&lt;li&gt;What&#39;s next for Frank.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;br /&gt;&#xA;Many thanks to Chris Stephenson for organizing and facilitating, and to Derek and Hiyasmin for tolerating my hogging of the mike!&lt;br /&gt;&#xA;&lt;br /&gt;&#xA;You can get more information on the podcast and give it a listen &lt;a href=&#34;http://bit.ly/9cyMjT&#34;&gt;here&lt;/a&gt;.&lt;/div&gt;</description>
    </item>
    <item>
      <title>Frank: Automated Acceptance Tests for iPhone and iPad</title>
      <link>https://blog.thepete.net/blog/2010/07/23/frank-automated-acceptance-tests-for/</link>
      <pubDate>Fri, 23 Jul 2010 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2010/07/23/frank-automated-acceptance-tests-for/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;p&gt;Recently I joined a team developing an iPad application. The application had no existing automated tests, and the team was under a tight deadline to deliver on promised functionality. Faced with similar circumstances in the past I have advocated introducing automated UI-driven acceptance tests to establish a loose but broad test coverage net. After a brief investigation we decided that the available tools weren&#39;t quite what we needed, so we built our own &#39;Frankenstein&#39;s Monster&#39; by plumbing together several existing open source libraries to create &lt;a href=&#34;http://github.com/moredip/Frank&#34;&gt;a light-weight UI automation framework for iPhone and iPad applications, called Frank.&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>TDD, Emergent Design, and Punctuated Equilibrium</title>
      <link>https://blog.thepete.net/blog/2010/04/22/tdd-emergent-design-and-punctuated/</link>
      <pubDate>Thu, 22 Apr 2010 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2010/04/22/tdd-emergent-design-and-punctuated/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;p&gt;In my experience good TDD designs tend to have evolved (and hopefully continue to evolve) in a sort of punctuated equilibrium. There are long periods of small incremental changes to a code base, punctuated by infrequent bursts of large design-level refactorings. While the TDD mantra is &#34;Red, Green, Refactor&#34;, I think a more accurate version would be &#34;Red, Green, Red, Green, Red, Green, Refactor&#34;. Less catchy, I know.&lt;br /&gt;&#xA;&lt;/p&gt;&lt;p&gt;Letting tests drive your design is great, but if you&#39;re not careful you will end up with a design which is the result of a simple accreation of functionality. This of course is the reason for the &#34;Refactor&#34; part of RGR. However, in my experience the refactoring part does not occur in a steady flow. Rather there will be periods of time where only small implementation-level refactorings take place during the RGR cycle as new functionality is implemented. Then at some point something will give. Someone may have a design breakthrough, realizing a more expressive/elegant/clean way to express some functionality. Alternatively some niggling annoyance in a subsystem&#39;s design will pass the team&#39;s tolerance threshold such that they decide they need to clean up the design to remove the annoyance. Both events will lead to a brief flurry of larger design-level refactorings.&lt;br /&gt;&#xA;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Introducing Noguchi</title>
      <link>https://blog.thepete.net/blog/2010/04/05/introducing-noguchi/</link>
      <pubDate>Mon, 05 Apr 2010 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2010/04/05/introducing-noguchi/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;p&gt;Generating HTML tables in ruby has always seemed like more of a hassle than it should be. Most of the times that I&#39;ve had to do it I&#39;ve been a little frustrated with how, well, &lt;i&gt;ugly&lt;/i&gt; the view code looks. So, I decided I&#39;d try and create a nicer way to build tables. The end result is a small table creation library called Noguchi. Given a set of data and some optional configuration it will render a table as HTML or CSV.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Stormcloud will watch over the unicorns.</title>
      <link>https://blog.thepete.net/blog/2010/04/03/stormcloud-will-watch-over-unicorns/</link>
      <pubDate>Sat, 03 Apr 2010 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2010/04/03/stormcloud-will-watch-over-unicorns/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;p&gt;Hipster geeks crack me up. A nice ancillary benefit of being in this industry is I get to read blog posts about interesting technical stuff which also include phrases such as:&lt;/p&gt;&lt;br /&gt;&#xA;&lt;blockquote&gt;...we developed a new monitoring script, called Stormcloud, to kill Unicorns when they ran out of control...&lt;br /&gt;&#xA;&lt;br /&gt;&#xA;...Monit would still monitor the master Unicorn process, but Stormcloud would watch over the Unicorns...&lt;br /&gt;&#xA;&lt;br /&gt;&#xA;...child death during request processing ... would cause that request and all requests queued in the mongrel to send 500 &#34;robot&#34; errors until the mongrel had been restarted...&lt;br /&gt;&#xA;&lt;/blockquote&gt;&lt;br /&gt;&#xA;&lt;p&gt;No need to fear, children. Stormcloud will watch over the unicorns. And if all else fails, a mongrel will send 500 robot errors.&lt;/p&gt;</description>
    </item>
    <item>
      <title>TickTock: A dirt-simple stopwatch class for actionscript</title>
      <link>https://blog.thepete.net/blog/2010/03/09/ticktock-dirt-simple-stopwatch-class/</link>
      <pubDate>Tue, 09 Mar 2010 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2010/03/09/ticktock-dirt-simple-stopwatch-class/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;I just threw together a really straightforward stopwatch class, for use when profiling operations in ActionScript code. You can either use it in an old-skool procedural way:&#xA;&#xA;&lt;pre class=&#34;brush: as3; gutter: false&#34;&gt;&#xA;var tt:TickTock = new TickTock();&#xA;tt.start();&#xA;doSomeWork();&#xA;tt.stop();&#xA;trace( &#34;That took &#34;+tickTock.elapsedTimeInMilliseconds+&#34; millisconds&#34; );&#xA;&lt;/pre&gt;&#xA;&#xA;or in a fancy-pants, functional, closure-y way:&#xA;&#xA;&lt;pre class=&#34;brush: as3; gutter: false&#34;&gt;&#xA;var tt:TickTock = TickTock.measure( function(){&#xA;  doSomeWork();&#xA;});&#xA;trace( &#34;That took &#34;+tickTock.elapsedTimeInMilliseconds+&#34; millisconds&#34; );&#xA;&lt;/pre&gt;&#xA;&#xA;Being primarily a ruby guy, I prefer the fancy-pants approach ;)&#xA;&#xA;The class, along with a little sample app, is &lt;a href=&#34;http://github.com/moredip/TickTock&#34;&gt;up on GitHub now&lt;/a&gt;.&lt;/div&gt;</description>
    </item>
    <item>
      <title>Why do we estimate effort?</title>
      <link>https://blog.thepete.net/blog/2010/03/07/why-do-we-estimate-effort/</link>
      <pubDate>Sun, 07 Mar 2010 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2010/03/07/why-do-we-estimate-effort/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;p&gt;I listened to a &lt;a href=&#34;http://www.se-radio.net/podcast/2010-02/episode-156-kanban-david-anderson&#34;&gt;really good podcast&lt;/a&gt; yesterday on Kanban. One of the topics discussed was the fact that with Kanban estimating story points is optional. Most of my agile experience is with Scrum, so my initial reaction was one of mild disbelief. How can a team perform work without estimating effort! But when you think about it, why do we have this vaguely obsessive focus on story points in Scrum? Surely in other areas there are teams that get by perfectly well without having to determine up-front how much effort each item of work is going to require. What &lt;i&gt;is&lt;/i&gt; the value in estimating? Here&#39;s what I came up with:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Primitive Obsession obsessions</title>
      <link>https://blog.thepete.net/blog/2010/02/22/primitive-obsession-obsessions/</link>
      <pubDate>Mon, 22 Feb 2010 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2010/02/22/primitive-obsession-obsessions/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;p&gt;After seeing the &lt;span style=&#34;font-variant: small-caps;&#34;&gt;Primitive Obsession&lt;/span&gt; code smell crop up in a few different places recently I got to thinking about it in the context of static and dynamic languages.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Essentially this code smell refers to using a primitive data type (int, string, etc), or a cluster thereof, where you could instead be using an explicitly defined type. Probably the most common variant of &lt;span style=&#34;font-variant: small-caps;&#34;&gt;Primitive Obsession&lt;/span&gt; would be a method like:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Encapsulating user interaction events in Flex</title>
      <link>https://blog.thepete.net/blog/2010/02/19/encapsulating-user-interaction-events/</link>
      <pubDate>Fri, 19 Feb 2010 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2010/02/19/encapsulating-user-interaction-events/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;p&gt;When developing the presentation layer in a Flex application I like to follow an MVC/MVP pattern. I also like to keep my views nice and skinny, with as much logic as possible in the controller/presenter. However, I do like to encapsulate &lt;em&gt;some&lt;/em&gt; of the details of the UI itself within the view, and so I shy away from exposing raw user interaction events (button clicks, list selections, etc) outside of the view. Instead I like to have the view capture those events and translate them into what I call &lt;em&gt;user action&lt;/em&gt; events, which represent higher-level, user-centric interactions. So instead of publishing a &#39;list item selected&#39; event, the view publishes a &#39;blog post selected&#39; event. For example, here what a typical event handler would look like in a view&#39;s MXML file:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Ruby Facets: the mash method</title>
      <link>https://blog.thepete.net/blog/2010/02/18/ruby-facets-mash-method/</link>
      <pubDate>Thu, 18 Feb 2010 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2010/02/18/ruby-facets-mash-method/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;p&gt;I keep meaning to write up some of the useful gems (if you&#39;ll pardon the pun) which are hidden in the super-handy &lt;a href=&#34;http://facets.rubyforge.org/&#34;&gt;Facets gem&lt;/a&gt;. Today I&#39;ll cover &lt;a href=&#34;http://facets.rubyforge.org/apidoc/api/core/classes/Enumerable.html#M000524&#34;&gt;Enumerable#mash.&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&#xA;Let&#39;s say you have a list of Users, and you&#39;d like to create a hash which lets you look up the Users based on their login. You might write something like:&#xA;&lt;/p&gt;&#xA;&#xA;&lt;pre class=&#34;brush: ruby; gutter: false&#34;&gt;&#xA;def create_login_hash_for( users )&#xA;  user_login_hash = {}&#xA;  users.each do |user|&#xA;    user_login_hash[user.login] = user&#xA;  end&#xA;  user_login_hash&#xA;end&#xA;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;With Enumerable#mash, you can trim that down to:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Partial commits with git</title>
      <link>https://blog.thepete.net/blog/2010/02/03/partial-commits-with-git/</link>
      <pubDate>Wed, 03 Feb 2010 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2010/02/03/partial-commits-with-git/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;p&gt;I&#39;ve been using git for a few months now. Like all the best dev tools it has slowly permeated my workflow to the point where I&#39;d feel pretty crippled without it. In fact, I don&#39;t think I would ever go back to a centralized system like svn at this point. In a pinch I&#39;d fall back to using git locally and then using the appropriate git-to-foo integration to push my local changes from my git repo to whatever the centralized repository was.&lt;/p&gt;</description>
    </item>
    <item>
      <title>an inverted include? for ruby</title>
      <link>https://blog.thepete.net/blog/2010/01/31/inverted-include-for-ruby/</link>
      <pubDate>Sun, 31 Jan 2010 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2010/01/31/inverted-include-for-ruby/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;p&gt;I&#39;ve always found it a slightly hard to read ruby which uses Enumerable#include?(), especially when the Enumerable your testing against is a literal or a constant. For example, let&#39;s say you&#39;re checking an input parameter to guard against invalid input. You might write something like:&lt;/p&gt;&#xA;&#xA;&lt;pre class=&#34;brush: ruby; gutter: false&#34;&gt;&#xA;unless VALID_COMMANDS.include?( command_param )&#xA;  whine_to_user()&#xA;  return&#xA;end&#xA;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This makes sense, but it seems backwards to me. I don&#39;t care whether some array has a value in it so much as I care whether a value is in some array. Obviously that&#39;s just two ways of saying the same thing, but the latter seems to capture the intent much more to me. I think it would be easier to understand this:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Flex Patterns: Presentation Adapter</title>
      <link>https://blog.thepete.net/blog/2010/01/17/flex-patterns-presentation-adapter/</link>
      <pubDate>Sun, 17 Jan 2010 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2010/01/17/flex-patterns-presentation-adapter/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;h1&gt;Flex Patterns: Presentation Adapter&lt;/h1&gt;&#xA;&#xA;&lt;a onblur=&#34;try {parent.deselectBloggerImageGracefully();} catch(e) {}&#34; href=&#34;http://1.bp.blogspot.com/_rzQrByr0AIg/S1aRKN1ceHI/AAAAAAAAFC0/G7CLFQUloUM/s1600-h/Presentation+Adapter+%28Abstract%29+Class+Diagram.png&#34;&gt;&lt;img style=&#34;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 360px; height: 277px;&#34; src=&#34;http://1.bp.blogspot.com/_rzQrByr0AIg/S1aRKN1ceHI/AAAAAAAAFC0/G7CLFQUloUM/s400/Presentation+Adapter+%28Abstract%29+Class+Diagram.png&#34; alt=&#34;&#34; id=&#34;BLOGGER_PHOTO_ID_5428686005540255858&#34; border=&#34;0&#34; /&gt;&lt;/a&gt;&#xA;&#xA;Encapsulate the logic for presenting a domain object, and provide an object for skinny views to perform data-binding against.&#xA;&#xA;&lt;h2&gt;Problem&lt;/h2&gt;&#xA;&lt;p&gt;When using &lt;a href=&#34;http://sl.thepete.net/presentation-model-pattern&#34;&gt;Presentation Model&lt;/a&gt; our goal is to bind UI elements in your Skinny View directly to individual components of  the Presentation Model. This requires translating information in Domain Model instances into a presentation-specific form. At the same time we need to be able to map back from that presentation-specific form to the underlying domain model instance in order to present user interactions in terms of our domain model.&lt;/p&gt;</description>
    </item>
    <item>
      <title>How much code did I just delete?</title>
      <link>https://blog.thepete.net/blog/2009/11/17/how-much-code-did-i-just-delete/</link>
      <pubDate>Tue, 17 Nov 2009 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2009/11/17/how-much-code-did-i-just-delete/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;Today I had the great pleasure of deleting a huge chunk of old code from my application. Using git it&#39;s surprisingly easy to figure out exactly how much code:&#xA;&#xA;&lt;pre&gt; &#xA;git checkout -b deletion_task&#xA;&#xA;# ... delete lots of code...&#xA;# ... time passes...&#xA;&#xA;git add -i&#xA;git commit&#xA;git co master&#xA;FILES_DELETED=`git diff --summary master deletion_task | grep &#34;^ delete&#34; | wc -l`&#xA;LINES_DELETED=`git diff --summary master deletion_task | grep &#34;^ delete&#34; | awk &#39;{ print $4 }&#39; | xargs cat | wc -l`&#xA;echo -e &#34;$FILES_DELETED files deleted.\n$LINES_DELETED lines deleted.&#34;&#xA;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    <item>
      <title>Introducing Gimme: a lightweight ruby Registry</title>
      <link>https://blog.thepete.net/blog/2009/11/16/introducing-gimme-lightweight-ruby/</link>
      <pubDate>Mon, 16 Nov 2009 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2009/11/16/introducing-gimme-lightweight-ruby/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;I recently created &lt;a href=&#34;http://github.com/moredip/gimme&#34;&gt;Gimme&lt;/a&gt;, a small ruby gem which allows you to configure and access a simple &lt;a href=&#34;http://martinfowler.com/eaaCatalog/registry.html&#34;&gt;Registry&lt;/a&gt; using a nice little DSL. &#xA;&#xA;&lt;h1&gt;Gimme in a paragraph&lt;/h1&gt;&#xA;&#xA;The general idea of Gimme is to allow a single point for configuring the well known services which your application uses (think DB connection, twitter API gateway, email server, etc). Once configured Gimme then exposes a single point to access those services, without needing to resort to singletons or global variables.&#xA;&#xA;&lt;h1&gt;Show me teh codez&lt;/h1&gt;&#xA;Here&#39;s a simple example showing how you would configure your registry:&#xA;&#xA;&lt;pre class=&#34;brush: ruby; gutter: false&#34;&gt;&#xA;Gimme.configure |g|&#xA;  g.for_the(ExternalService) do |env,name|&#xA;    ExternalService.new(env[:setting1],env[:setting2])&#xA;  end&#xA;end&#xA;&lt;/pre&gt;&#xA;&#xA;and here&#39;s how you&#39;d use it from within your app:&#xA;&#xA;&lt;pre class=&#34;brush: ruby; gutter: false&#34;&gt;&#xA;Gimme.the(ExternalService).some_method&#xA;&lt;/pre&gt;&#xA;&#xA;Here&#39;s a more complete example, showing both configuration and usage:&#xA;&#xA;&lt;pre class=&#34;brush: ruby; gutter: false&#34;&gt;&#xA;# your Emailer class&#xA;&#xA;class Emailer&#xA;  def initialize( smtp_hostname, port )&#xA;    @smtp_hostname, @port = smtp_hostname, port&#xA;    puts &#34;creating an emailer: #{inspect}&#34;&#xA;  end&#xA;&#xA;  def send_email( subject )&#xA;    puts &#34;Sending email &#39;#{subject}&#39; via #{inspect}&#34;&#xA;    # ...&#xA;  end&#xA;&#xA;  def inspect&#xA;    &#34;#{@smtp_hostname}:#{@port}&#34;&#xA;  end&#xA;end&#xA;&#xA;&#xA;# your Gimme configuration&#xA;&#xA;Gimme.configure do |g|&#xA;  g.for_the( Emailer ) do |env|&#xA;    email_settings = env[:email_settings]&#xA;    Emailer.new(email_settings[:hostname],email_settings[:port])&#xA;  end&#xA;end&#xA;&#xA;Gimme.environment = {:email_settings =&gt; {:hostname =&gt; &#39;smtp.mymailserver.com&#39;, :port =&gt; &#39;2525&#39;} }&#xA;&#xA;&#xA;&#xA;# in your app&#xA;&#xA;&#xA;Gimme.the(Emailer).send_email( &#34;Gimme is the awesomez&#34; )&#xA;Gimme.the(Emailer).send_email( &#34;Emailing is fun&#34; )&#xA;Gimme.the(Emailer).send_email( &#34;notice that only one Emailer was created above&#34; )&#xA;Gimme.the(Emailer).send_email( &#34;even though we sent 4 emails&#34; )&#xA;&lt;/pre&gt;&#xA;&#xA;&lt;h1&gt;Pseudo-singletons&lt;/h1&gt;&#xA;If you use the Gimme#for_the(Service) form when configuring Gimme then gimme will only create one instance of that object. If you use the Gimme#for_a(Service) form then the creation block will be called each time you ask for an instance of that object. That way things which hold on to expensive resources (database connections, TCP sockets) can be shared within your app, which services which need to maintain unique state for each client can be private to each client.&#xA;&#xA;&lt;h1&gt;Environments&lt;/h1&gt;&#xA;In any non-trivial application you need to configure your services. You can supply Gimme with an environment hash which it will then pass to your creation blocks whenever you ask for an object. This allows you to store settings like smtp hostnames, database passwords, twitter API keys, etc in a single environment hash, and use that hash in one place to configure all your external services at the point they are created.&#xA;&#xA;&lt;h1&gt;Dependency Injection/IoC&lt;/h1&gt;&#xA;There is nothing to stop you from calling Gimme.a() or Gimme.the() from within a creation block. This allows you to use Gimme as a lightweight IoC container.&#xA;&#xA;&lt;h1&gt;Check it out!&lt;/h1&gt;&#xA;Check out &lt;a href=&#34;http://github.com/moredip/gimme&#34;&gt;the github page&lt;/a&gt; for more info, including lots of example usages, and a more detailed README.&lt;/div&gt;</description>
    </item>
    <item>
      <title>Adding hamcrest-as matchers to mock4as</title>
      <link>https://blog.thepete.net/blog/2009/06/28/adding-hamcrest-as-matchers-to-mock4as/</link>
      <pubDate>Sun, 28 Jun 2009 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2009/06/28/adding-hamcrest-as-matchers-to-mock4as/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;p&gt;Just a quick post to mention that I recently did an experiment with extending mock4as to use &lt;a href=&#34;http://drewbourne.github.com/&#34;&gt;Drew Bourne&lt;/a&gt;&#39;s awesome &lt;a href=&#34;http://github.com/drewbourne/hamcrest-as3&#34;&gt;hamcrest-as3&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The idea for this work is to specify mocked method arguments in a more flexible way. It was actually surprisingly trivial to implement. I&#39;ll be writing a more detailed post in the future explaining what these changes mean to a user of mock4as.&#xA;&lt;/p&gt;&lt;p&gt;I also took the opportunity to experiment with using git and github, so the changes are available to all and sundry as a &lt;a href=&#34;http://github.com/moredip/mock4as&#34;&gt;github repository&lt;/a&gt;. I will be talking to the mock4as guys about getting my changes merged into the &lt;a href=&#34;http://code.google.com/p/mock4as/&#34;&gt;official mock4as codebase&lt;/a&gt;&#xA;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Presentation Model Pattern</title>
      <link>https://blog.thepete.net/blog/2009/06/14/presentation-model-pattern/</link>
      <pubDate>Sun, 14 Jun 2009 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2009/06/14/presentation-model-pattern/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;&lt;h1&gt;Presentation Model&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;We want to achieve a Skinny View without the View needing to expose UI details to the Controller.&lt;/p&gt;&#xA;&#xA;&lt;a onblur=&#34;try {parent.deselectBloggerImageGracefully();} catch(e) {}&#34; href=&#34;http://1.bp.blogspot.com/_rzQrByr0AIg/SjsXodNSTaI/AAAAAAAADaM/e6empQbFDig/s1600-h/Presentation+Model+Class+Diagram.png&#34;&gt;&lt;img style=&#34;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 318px;&#34; src=&#34;http://1.bp.blogspot.com/_rzQrByr0AIg/SjsXodNSTaI/AAAAAAAADaM/e6empQbFDig/s400/Presentation+Model+Class+Diagram.png&#34; border=&#34;0&#34; alt=&#34;&#34;id=&#34;BLOGGER_PHOTO_ID_5348894966235155874&#34; /&gt;&lt;/a&gt;&#xA;&#xA;&lt;h2&gt;Also known as&lt;/h2&gt;&#xA;&lt;p&gt;View State, Logical View&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Problem&lt;/h2&gt;&#xA;&lt;p&gt;We want to have as much presentation logic under test as we can by having a Skinny View. At the same time we don&#39;t want our Controller to be burdened with the minutiae of maintaining UI elements.&lt;/p&gt;</description>
    </item>
    <item>
      <title>REST: &#39;There aren&#39;t enough verbs&#39;</title>
      <link>https://blog.thepete.net/blog/2009/04/19/rest-there-arent-enough-verbs/</link>
      <pubDate>Sun, 19 Apr 2009 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2009/04/19/rest-there-arent-enough-verbs/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;I think one of the more frequent issues that people have when starting to work with a RESTful architecture is that &#34;there aren&#39;t enough verbs&#34;.&#xA;&#xA;&lt;h4&gt;Why having few verbs is good&lt;/h4&gt;&#xA;When we look at the big picture we see that this paucity of verbs is in fact one of the strengths of REST. A small, standard set of verbs allows all parties to agree (in the most part) on what the semantics of those verbs are. This in turn allows the creation of a lot of loosely coupled infrastructure which &lt;span style=&#34;font-style:italic;&#34;&gt;any&lt;/span&gt; REST system can take advantage of. An obvious example is the sophisticated caching system within the world wide web. All parties can agree on what a GET means, specifically that it&#39;s an idempotent operation. That allows intermediaries to know when a response is cachable. If each application was creating its own set of verbs we&#39;d no longer be able to leverage all this &#39;free&#39; infrastructure which has built up. If a cache somewhere between your user&#39;s browser and your data center doesn&#39;t understand what the semantics of some custom verb are then it can&#39;t safely cache your responses. Same goes for your user&#39;s browser. This is one of the reasons why RESTful folks don&#39;t like web services with RPC-style architectures. By tunnelling everything through POST and a single URI these services lose the ability to confer semantics to intermediaries. These kinds of services are on the web, but not &lt;span style=&#34;font-style:italic;&#34;&gt;of&lt;/span&gt; the web.&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;&lt;h4&gt;What to do when you &#39;need&#39; more verbs&lt;/h4&gt;&#xA;So, we are agreed that a small, standard set of verbs is a good thing. What then is an API designer to do when modeling a complex operation which doesn&#39;t map nicely onto that small set? In my experience there are generally two solutions. We can use an overloaded POST, or we can add some additional &#39;activity resources&#39; to the resource space of the API. I tend to prefer the latter, but I think it&#39;s important to not be dogmatic about this. There are certainly situations where an overloaded POST is the way to go.&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;Let&#39;s discuss what I mean by &#39;activity resources&#39;. Generally when people start designing the resource space for their RESTful API they might write a description of what functionality the API seeks to expose, and then go through the text underlining nouns. If this is reminding you of an analysis technique for a certain other paradigm then stick with me, I&#39;ll be coming back to that in the next section. This set of nouns would generally be a good starting point for identifying resources. I&#39;ll call these types of resources Entity Resources. Let&#39;s say we&#39;re working on a hotel reservation system. After this initial stage of analysis we might come up with a set of entity resources such as Guest, Room, Hotel, Bill, etc. We&#39;d probably also have Reservation in there too, but I wouldn&#39;t classify that one as an entity. So far so good. Now, let&#39;s say we&#39;re working on the checkout part of the system, in particular on credit card processing. We need a way to represent the act of a Guest paying their Bill with a credit card, having that credit card transaction approved or declined, etc. A lot of developers (particularly those coming from an RPC mindset) will want to do something like add a PAY verb to the Bill resource. This makes sense. Paying is an action that is applied to the Bill. It makes sense, but as we&#39;ve discussed above REST frowns upon extending our small set of verbs. So instead we can create an Activity Resource called Payment. This resource can contain a reference (in the form of a uri) to the Bill it is a Payment for, along with details like credit card number, etc. In addition we can add a Payments resource which belongs to each Bill. When a customer wants to pay a bill they can send a POST to the Payments resource, supplying a representation of the payment they want to make. That POST will create a Payment resource representing the transaction, and supply the user with a uri for that resource in the form of a redirect. The customer can GET on that resource to check on the state of the payment transaction (Processing,Successful,Denied), etc. Maybe if the payment was denied they could PUT to the resource with a corrected credit card number. The key pattern here was to take an action (paying a bill), and to model that as a transitory Activity resource. Adding that extra level allows us to model the behavior in a RESTful way. I&#39;ve frequently seen transactions modeled RESTfully in this way.&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;&lt;h4&gt;Sidebar: Parallels in grokking REST and grokking OO&lt;/h4&gt;&#xA;When I was going through the slow, laborious process of getting these ideas into my thick skull I experienced a vague feeling of déjà vu. I eventually realized that this was just like when I first started to really grok object-oriented design. Often when students are being taught to design object oriented systems a suggested technique is to write a description of the business domain and then underline the nouns in the description. These nouns will be the classes in your system. However, after gaining experience with OO I think most developers realize that these classes are not where the meat of a design lies. The meat lies in the interaction between these entities, how they are composed and how they interact. Using polymorphism and composition to create clean, loosely-coupled systems becomes much more interesting than designing the Is-A inheritance heirarchies that often appear in introductions to OO. And here lies the parallel with learning RESTful design, and my sense of déjà vu. When learning REST the core concepts of Resources, Actions, Uris, etc. are necessarily explained first, and most pedagogical examples focus on simple systems consisting of what I referred to above as Entity Resources. However when you start to do real work with a RESTful architecture you start realizing that large parts of the system are about modeling the relations and interactions &lt;span style=&#34;font-style:italic;&#34;&gt;between&lt;/span&gt; these Entity Resources. I expect that as we gain more experience with the REST style then the common problems and shared solutions will start to emerge, in the same way as we saw OO design mature in the 80s and 90s.&lt;/div&gt;</description>
    </item>
    <item>
      <title>mock.willExecute(...) in mock4as</title>
      <link>https://blog.thepete.net/blog/2009/04/02/mockwillexecute-in-mock4as/</link>
      <pubDate>Thu, 02 Apr 2009 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2009/04/02/mockwillexecute-in-mock4as/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;As I mentioned in a &lt;a href=&#34;http://blog.thepete.net/2009/03/liberal-mocks.html&#34;&gt;previous post&lt;/a&gt; I&#39;ve recently been adding some features to &lt;a href=&#34;http://code.google.com/p/mock4as/&#34;&gt;mock4as&lt;/a&gt;, a mocking library for ActionScript. In this post I&#39;m going to talk about the new mock.willExecute(...) feature which I recently implemented.&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;Perhaps the easiest way to describe willExecute is as a dynamic version of willReturn, so before we dive into willExecute I should briefly explain willReturn. willReturn allows a user to specify what value a mocked out method should return when called. An example should shed some light:&#xA;&#xA;&lt;pre class=&#34;brush: as3; gutter: false&#34;&gt;&#xA;var mock:MockInterface = new MockInterface();&#xA;mock.expects(&#39;lookupBookTitleByISBN&#39;).withAnyArgs().willReturn(&#39;War and Peace&#39;);&#xA;assertEquals( &#39;War and Peace&#39;, mock.lookupBookTitleByISBN() );&#xA;&lt;/pre&gt;&#xA;&#xA;You can see that when we call the method mock.lookupBookTitleByISBN() it returns &#39;War and Peace&#39;, because that&#39;s what we specified in our expectation. This is a fundamental feature that I would expect any mocking system to supply. It&#39;s the primary tool for controlling the indirect inputs into the system that your testing. That said, newcomers to mocking do sometimes get confused with this feature and think that willReturn is specifying what you &lt;span style=&#34;font-style: italic;&#34;&gt;expect&lt;/span&gt; the method to return. That&#39;s not what we&#39;re doing here, we&#39;re &lt;span style=&#34;font-style: italic;&#34;&gt;instructing&lt;/span&gt; the mock what to return. We&#39;re providing indirect input, not testing indirect output (the other main purpose of mocking). I suspect that adding a new method to mock4as which is similar mock.expects(...) but intended for use in cases where you just mocking the method to control indirect input would be helpful. Something like mock.ifCalled(&#39;foo&#39;).willReturn(someResult) might clear up some of the confusion between specifying an expectation that a method is called and injecting a return value for a method.&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;Anyway, back to the subject at hand. The willExecute feature takes the concept of willReturn and makes it dynamic. Rather than specifying a hard-coded value to be returned whenever the method is called you instead supply an arbitrary function which will be &lt;span style=&#34;font-style: italic;&#34;&gt;executed&lt;/span&gt; whenever the specified method on the mock is called. For example:&#xA;&#xA;&lt;pre class=&#34;brush: as3; gutter: false&#34;&gt;&#xA;var mock:MockInterface = new MockInterface();&#xA;mock.expects(&#39;lookupBookTitleByISBN&#39;).willExecute(&#xA;  function( isbn:String ):String{&#xA;    return &#34;Title for isbn &#34; + isbn;&#xA;  } );&#xA;&#xA;assertEquals( &#39;Title for isbn ABC&#39;, mock.lookupBookTitleByISBN(&#39;ABC&#39;) );&#xA;assertEquals( &#39;Title for isbn XYZ&#39;, mock.lookupBookTitleByISBN(&#39;XYZ&#39;) );&#xA;&#xA;&lt;/pre&gt;&#xA;Every time lookupBookTitleByISBN(...) is called the mocking system looks up and executes the attached function, passing in the arguments supplied to lookupBookTitleByISBN(...). In addition it returns whatever value was returned by the attached function. Note from our example that this allows output to vary with the input, because we have supplied a function rather than a static value.&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;The real fun starts when we realize that functions in actionscript can act as &lt;a href=&#34;http://martinfowler.com/bliki/Closure.html&#34;&gt;closures&lt;/a&gt;. This leads to a lot of interesting ways to use willExecute. To give one (rather contrived) example, we can use willExecute to specify some quite sophisticated ordering constraints:&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;&lt;pre class=&#34;brush: as3; gutter: false&#34;&gt;&#xA;public function test_accountsAreSubmittedInAscendingNumericalOrder():void {&#xA;  var mock:MockInterface = new MockInterface();&#xA;&#xA;  var lastAccountId:int = -1;&#xA;  mock.expects(&#39;submitAccount&#39;).withAnyArgs().willExecute(&#xA;    function(account:account):void {&#xA;      assertTrue( account.id() &gt;= lastAccountId );&#xA;      lastAccountId = account.id();&#xA;    }&#xA;  );&#xA;&#xA;  exerciseSystemUnderTestUsing( mock );&#xA;}&#xA;&#xA;&lt;/pre&gt;&#xA;Note here that we have used &lt;span style=&#34;font-weight: bold;&#34;&gt;variables outside of the closure&#39;s local scope&lt;/span&gt; to maintain state across calls to the mocked method. Also note that we can call methods like assertTrue(...) from inside the attached function.&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;Some other potential uses of this feature include:&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;&lt;span style=&#34;font-weight: bold;&#34;&gt;Verifying arguments passed to a method where the argument is complex:&lt;/span&gt;&#xA;Let&#39;s say a method takes a &lt;a href=&#34;http://www.refactoring.com/catalog/introduceParameterObject.html&#34;&gt;Parameter Object&lt;/a&gt; which is an instance of a class with 10 properties, but we&#39;re only interested in three:&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;&lt;pre class=&#34;brush: as3; gutter: false&#34;&gt;&#xA;public function testXYZCoordinatesAreAllSetToZero():void&#xA;{&#xA;  var mock:MockSomeInterface = new MockSomeInterface();&#xA;&#xA;  mock.expects(&#39;methodWithScaryParams&#39;).withAnyArgs().willExecute(&#xA;    function(bigObject:ComplexParameterObject):void{&#xA;      assertEquals( 0, bigObject.coordX );&#xA;      assertEquals( 0, bigObject.coordY );&#xA;      assertEquals( 0, bigObject.coordZ );&#xA;    }&#xA;  );&#xA;&#xA;  exerciseSystemUnderTestUsing(mock);&#xA;}&#xA;&#xA;&lt;/pre&gt;&#xA;&lt;span style=&#34;font-weight: bold;&#34;&gt;Verifying arguments passed to a method with a lot of parameters but where we&#39;re only interested in some of the arguments:&lt;/span&gt;&#xA;&#xA;&lt;pre class=&#34;brush: as3; gutter: false&#34;&gt;&#xA;public function testNameAndAddressAreNotEmpty():void&#xA;{&#xA;  var mock:MockSomeInterface = new MockSomeInterface();&#xA;&#xA;  mock.expects(&#39;methodWithManyParams&#39;).withAnyArgs().willExecute(&#xA;    function(boring:String,uninteresting:XML,name:String,address:String,dontCare:Function):void{&#xA;      assertNotEquals( &#34;&#34;, name );&#xA;      assertNotEquals( &#34;&#34;, address );&#xA;    }&#xA;  );&#xA;&#xA;  exerciseSystemUnderTestUsing(mock);&#xA;}&#xA;&#xA;&lt;/pre&gt;&#xA;&lt;span style=&#34;font-weight: bold;&#34;&gt;Verifying some internal characteristics of an argument:&lt;/span&gt;&#xA;&#xA;&lt;pre class=&#34;brush: as3; gutter: false&#34;&gt;&#xA;public function testNameAndAddressAreNotEmpty():void&#xA;{&#xA;  var mock:MockSomeInterface = new MockSomeInterface();&#xA;&#xA;  mock.expects(&#39;someMethod&#39;).withAnyArgs().willExecute(&#xA;     function(lotsOfXml:XML):void{&#xA;      assertEquals( &#34;Dave&#34;, lotsOfXml.body.person.firstName );&#xA;      assertEquals( &#34;Thomas&#34;, lotsOfXml.body.person.lastName );&#xA;    }&#xA;  );&#xA;&#xA;  exerciseSystemUnderTestUsing(mock);&#xA;}&#xA;&#xA;&lt;/pre&gt;&#xA;It&#39;s interesting to note that willExecute can be used to accomplish two goals. You can use it to control the Indirect Input into the system you&#39;re testing (which is what willReturn is also used for, as I touched on above). In addition you can also use it to test the Indirect Outputs of your system. This is what&#39;s happening above when assertEquals(...), assertTrue(...) and the like are called from within the attached functions. My personal experience is that something like willExecute tends to be used more often as an ad hoc way of testing Indirect Output than as a way of supplying Indirect Input (which can most time be handled adequately using willReturn). Most of the time I use it to express non-trivial expectations on the input to a method. In a lot of frameworks the need to do this is reduced by the presence of custom argument matchers. These allow you to capture complex expectations on a method&#39;s input parameters by implementing classes which you then provide to your mock during the expection setting phase. For examples from other mocking frameworks you could look at &lt;a href=&#34;http://www.jmock.org/custom-matchers.html&#34;&gt;jMock&lt;/a&gt; and &lt;a href=&#34;http://mockito.googlecode.com/svn/branches/1.7/javadoc/org/mockito/Matchers.html&#34;&gt;Mockito&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;Finally, you may remember I started off describing willExecute above is as a dynamic version of willReturn. In fact, willReturn could be trivially implemented using willExecute:&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;&lt;pre class=&#34;brush: as3; gutter: false&#34;&gt;&#xA;public function willReturn(object:Object):void{&#xA;  willExecute( function():Object{ return object; } );&#xA;}&#xA;&#xA;&lt;/pre&gt;&#xA;The same is true of the willThrow() feature (which allows a user to ask a mock to throw a specific exception when a method is called).&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;&lt;pre class=&#34;brush: as3; gutter: false&#34;&gt;&#xA;public function willThrow(error:Error):void{&#xA;  willExecute( function():void{ throw error; } );&#xA;}&#xA;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    <item>
      <title>fun with Symbol#to_proc</title>
      <link>https://blog.thepete.net/blog/2009/04/01/fun-with-symboltoproc/</link>
      <pubDate>Wed, 01 Apr 2009 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2009/04/01/fun-with-symboltoproc/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;As I start to get fluent in ruby I often find myself using a more functional programming style, particularly when dealing with collections. That generally leads to lots of little block-centric operations. I recently discovered a really elegant trick to make that code a little nicer.&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;Let&#39;s say there&#39;s a Person class:&#xA;&#xA;&lt;pre class=&#34;brush: ruby; gutter: false&#34;&gt;&#xA;class Person&#xA;    attr_accessor :first_name, :last_name, :age&#xA;end&#xA;&lt;/pre&gt;&#xA;and I have a collection of people which I&#39;d like to sort by age. An obvious approach would be:&#xA;&#xA;&lt;pre class=&#34;brush: ruby; gutter: false&#34;&gt;&#xA;people.sort_by{ |person| person.age }&#xA;&lt;/pre&gt;&#xA;&#xA;That works, but it is a little wordy. This is ruby, after all! Wouldn&#39;t it be nice if we could write this instead:&#xA;&#xA;&lt;pre class=&#34;brush: ruby; gutter: false&#34;&gt;&#xA;people.sort_by &amp;amp;:age&#xA;&lt;/pre&gt;&#xA;Isn&#39;t that neat? The magic that makes this work is this little &lt;a href=&#34;http://en.wikipedia.org/wiki/Monkey_patch&#34;&gt;monkey patch&lt;/a&gt; to the Symbol class.&#xA;&#xA;&lt;pre class=&#34;brush: ruby; gutter: false&#34;&gt;&#xA;class Symbol&#xA;  def to_proc&#xA;    Proc.new { |*args| args.shift.__send__(self, *args) }&#xA;  end&#xA;end&#xA;&lt;/pre&gt;&#xA;&#xA;Note that this is already done for you &lt;a href=&#34;http://api.rubyonrails.org/classes/Symbol.html&#34;&gt;in Rails&lt;/a&gt; and &lt;a href=&#34;http://facets.rubyforge.org/doc/api/core/classes/Symbol.html&#34;&gt;in Facets&lt;/a&gt; - in fact that&#39;s where I lifted this code from.&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;So how does this work? When we called sort_by we passed in the :age symbol, but we used the &amp;amp; to indicate that it should be treated as a block. When you supply a method with a block which isn&#39;t a Proc instance ruby helpfully attempts to coerce it into a Proc by calling to_proc. Because of the Symbol monkey patch to_proc now returns a block which will invoke a method with the same name as the symbol itself on whatever object it is passed in. Phew. Re-read that last sentence 5 times. The end result is that the following two blocks are identical:&#xA;&#xA;&lt;pre class=&#34;brush: ruby; gutter: false&#34;&gt;&#xA;block_a = :some_method.to_proc&#xA;block_b = proc { |x| x.some_method }&#xA;&lt;/pre&gt;&#xA;&#xA;It follows that the following two operations are identical:&#xA;&#xA;&lt;pre class=&#34;brush: ruby; gutter: false&#34;&gt;&#xA;people.sort_by{ |person| person.age }&#xA;people.sort_by &amp;amp;:age&#xA;&lt;/pre&gt;&#xA;&#xA;Voila! I should point out here that I&#39;m not exactly the first person to discuss this great trick. See for messirs &lt;a href=&#34;http://pragdave.pragprog.com/pragdave/2005/11/symbolto_proc.html&#34;&gt;Thomas&lt;/a&gt; and &lt;a href=&#34;http://drnicwilliams.com/2006/09/28/new-magical-version-of-symbolto_proc/&#34;&gt;Williams&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;In fact, it&#39;s such a common idiom that it will &lt;a href=&#34;http://www.infoq.com/news/2008/02/to_proc-currying-ruby19&#34;&gt;apparently&lt;/a&gt; be baked right into ruby 1.9.&lt;/div&gt;</description>
    </item>
    <item>
      <title>Liberal Mocks</title>
      <link>https://blog.thepete.net/blog/2009/03/23/liberal-mocks/</link>
      <pubDate>Mon, 23 Mar 2009 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/blog/2009/03/23/liberal-mocks/</guid>
      <description>&lt;div class=&#39;post&#39;&gt;&#xA;I&#39;ve been using &lt;a href=&#34;http://code.google.com/p/mock4as/&#34;&gt;mock4as&lt;/a&gt; recently as part of a drive to get better test coverage in a flex project. As I used it I noticed  a few features which I&#39;ve seen in other mocking libraries that were missing. I did what any engineer with an itch to scratch might do in such a situation - I started to implementing the features in mock4as that I wanted to use.&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;One of the things I added was support for a pattern/feature which I&#39;m going to refer to here as &#39;liberal mocks&#39;. I am not really sure what the right name for this pattern is. I&#39;ve seen it called &#39;null object&#39; before, and also &#39;stubs&#39;. In my opinion both those terms are too overloaded to be used in this context, although the &lt;a href=&#34;http://en.wikipedia.org/wiki/Null_Object_pattern&#34;&gt;Null Object&lt;/a&gt; pattern is very similar to what I&#39;ll be describing.&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;I definitely wouldn&#39;t use the word &#39;stub&#39; in connection to this pattern, although I&#39;ve seen that done in other mocking libraries. For a start there is already &lt;a href=&#34;http://martinfowler.com/articles/mocksArentStubs.html&#34;&gt;way too much confusion&lt;/a&gt; in automated testing between Stubs and Mocks. For the record, my definition of a Stub is pretty close to what&#39;s described in the &lt;a href=&#34;http://xunitpatterns.com/index.html&#34;&gt;XUnit Test Patterns&lt;/a&gt; book (which I highly recommend). It&#39;s a &lt;a href=&#34;http://xunitpatterns.com/Test%20Double.html&#34;&gt;Test Double&lt;/a&gt; which is used to control indirect input into a system under test, and possibly to record indirect output for later verification. That second part is where my definition differs from Meszaros&#39;s - I merge &lt;a href=&#34;http://xunitpatterns.com/Test%20Stub.html&#34;&gt;Test Stub&lt;/a&gt; and &lt;a href=&#34;http://xunitpatterns.com/Test%20Spy.html&#34;&gt;Test Spy&lt;/a&gt; together. Anyway, I&#39;d love to hear from anyone who has a better (or more &#39;correct&#39;) name for the pattern I&#39;m describing.&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;On to the main attraction. A Liberal Mock is a mock which will not fail when it receives an unexpected method. Instead it will silently ignore the method call. Contrast this to a regular, or &#39;strict&#39; mock. In most mocking libraries a standard mock which receives a method call that was not specified while the mock&#39;s expectations were being set will be considered an error, and the mock will not pass verification.&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;A couple of unit tests from the mock4as library&#39;s test suite should help to illustrate this:&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;&lt;pre class=&#34;brush: as3;gutter: false&#34;&gt;&#xA;public function&#xA;testFailsIfUnexpectedMethodCalled():void&#xA;{&#xA;  var mock:MockSomeInterface = new MockSomeInterface();&#xA;  mock.doSomething();&#xA;  assertFalse(mock.success());&#xA;}&#xA;&#xA;public function&#xA;testSuccess_whenUnExpectedMethodCalledOnLiberalMock():void&#xA;{&#xA;  var mock:MockSomeInterface = new MockSomeInterface();&#xA;  mock.isLiberal();&#xA;  mock.doSomething();&#xA;  assertTrue(mock.errorMessage(), mock.success());&#xA;}&#xA;&#xA;&lt;/pre&gt;&#xA;That covers the what, now on to the why. The main scenario where I find myself reaching for liberal mocks is when I have a method which uses several features of a dependency, but I&#39;m writing a test which is only interested in certain aspects of that usage. For example, let&#39;s say I have a controller object which is responsible for maintaining a view object. The controller has an &lt;span style=&#34;font-family:courier new;&#34;&gt;initialize()&lt;/span&gt; method which sets the view&#39;s UI elements to some initial state, and I&#39;d like to get that method under test. Now if the view has a lot of UI elements I wouldn&#39;t want to test all of the setup in one test. Instead I might want tests like &lt;span style=&#34;font-family:courier new;&#34;&gt;initialize_shouldSetupCampaignDropDownCorrectly()&lt;/span&gt;, &lt;span style=&#34;font-family:courier new;&#34;&gt;initialize_shouldSetupDaypartingViewWithModelContents()&lt;/span&gt;, etc. If I was mocking the view with a strict mock then every test would need to explicitly set expectations for all the calls which the controller will be making to the view, even if each individual test is only interested in a small subset of those calls. With liberal mocks that requirement is removed. I can essentially say &#39;this dependency is going to be used in a bunch of ways here, but I&#39;m only concerned with these specific method calls&#39;. The underlying motivation for this is to avoid &lt;a href=&#34;http://xunitpatterns.com/Fragile%20Test.html&#34;&gt;Fragile Tests&lt;/a&gt;. If you&#39;re not using liberal mocks and one aspect of your expected behavior changes then suddenly &lt;span style=&#34;font-style: italic;&#34;&gt;all&lt;/span&gt; your tests will fail, not just the test that specifies the behavior that&#39;s just changed. Fragile tests seem to be a common risk for new automated testing practitioners, and they can be really demoralizing.&lt;br/&gt;&lt;br/&gt;&#xA;&#xA;Now, just because you &lt;span style=&#34;font-style: italic;&#34;&gt;can&lt;/span&gt; doesn&#39;t always mean you &lt;span style=&#34;font-style: italic;&#34;&gt;should&lt;/span&gt;. I&#39;ve found that liberal mocks can be a bit of a crutch for a less-than-optimal design. If you find yourself needing to use a lot of liberal mocking then you should consider that to be a design smell. Maybe the method you&#39;re testing is doing too much work. If you can break your big method up into smaller methods that are testable then you&#39;re in a happier place, in terms of testing and more importantly in terms of design. Alternatively, the issue may be that the dependency which you&#39;re mocking out has some huge sprawling interface that should be &lt;a href=&#34;http://www.refactoring.com/catalog/extractInterface.html&#34;&gt;split into several pieces&lt;/a&gt;. After doing that you may find that you only need to set expectations on one of those pieces, and the other parts can be replaced with a true Null Object.&lt;/div&gt;</description>
    </item>
    <item>
      <title></title>
      <link>https://blog.thepete.net/about/training/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/about/training/</guid>
      <description>&lt;p&gt;&lt;img src=&#34;./images/lab.jpg&#34; alt=&#34;vintage shot of people learning in a science lab&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;accelerate-your-teams-ability-to-write-maintainable-well-tested-react-and-redux&#34;&gt;Accelerate your team&amp;rsquo;s ability to write maintainable, well-tested React and Redux.&lt;/h2&gt;&#xA;&lt;p&gt;In this intensive 2 day course I teach the best practices for creating React/Redux applications which are easy to understand and easy to maintain.&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;./about/contact&#34;&gt;Get in touch&lt;/a&gt; to learn more about how your team can start getting more done in less time.&lt;/p&gt;&#xA;&lt;div class=&#34;pullquote-container&#34;&gt;&#xA;  &lt;div class=&#34;pullquote&#34;&gt;&#xA;       why waste your most precious resource - engineer&amp;#39;s time - figuring this out from first principles?&#xA;  &lt;/div&gt;&#xA;&lt;p&gt;Developers who are new to React and Redux will eventually figure out the patterns and practices that lead to testable apps that are easy to extend, and the gotchas that prevent that. But why waste your most precious resource - engineer&amp;rsquo;s time - figuring this out from first principles - and creating tech debt along the way?&lt;/p&gt;</description>
    </item>
    <item>
      <title>Get In Touch</title>
      <link>https://blog.thepete.net/about/contact/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://blog.thepete.net/about/contact/</guid>
      <description>&lt;p&gt;You can reach me via&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;email: &lt;a href=&#34;mailto:workwith@thepete.net&#34;&gt;workwith@thepete.net&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;bluesky: &lt;a href=&#34;https://bsky.app/profile/thepete.net&#34;&gt;@thepete.net&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;github: &lt;a href=&#34;https://github.com/moredip&#34;&gt;moredip&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://linkedin.com/in/beingagile&#34;&gt;LinkedIn&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Alternatively, you can simply fill out this form:&lt;/p&gt;&#xA;&lt;form class=&#34;contact-form&#34; method=&#34;POST&#34; action=&#34;https://formspree.io/workwith+formspree@thepete.net&#34;&gt;&#xA;  &lt;input size=14 name=&#34;name&#34; placeholder=&#34;Your name&#34;&gt;&#xA;  &lt;input size=16 type=&#34;email&#34; name=&#34;email&#34; placeholder=&#34;Your email&#34;&gt;&#xA;  &lt;textarea rows=&#34;10&#34; name=&#34;message&#34; placeholder=&#34;Your message&#34;&gt;&lt;/textarea&gt;&#xA;  &lt;button type=&#34;submit&#34;&gt;Send&lt;/button&gt;&#xA;&lt;/form&gt;</description>
    </item>
  </channel>
</rss>
