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’s not your core expertise. this post is an opinionated cheat sheet for an engineering leader who finds themselves in the position of faking it as a product leader. Being expected to define a clear product strategy and build a product roadmap can be pretty intimidating. Doing this well can be a huge accelerator for your teams, and neglecting it can sca...| Blogs on Pete Hodgson
Despite the breathless hype from some corners of the internet, vibe-coding - fully autonomous AI coding - isn’t going to replace engineers in the near future. Anyone who’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. 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 ...| Blogs on Pete Hodgson
After a few hours of experimenting with Claude Code, I’m starting to take Agentic Coding/Vibe Coding seriously. Based on my experimentation the “full vibe” 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. So, let’s talk about: what types of task are a great fit for agentic AI, ...| Blogs on Pete Hodgson
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. Many of these exciting product features stalled out at MVP, and haven’t really delivered on their promise. Why? In this article series I’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.| Blogs on Pete Hodgson
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. The easiest way to roll out a breaking change is in a “big bang” - change both sides of the system all in one go. However, this option requires taking downtime during a deployment, and isn’t possible at all if you don’t have extremely...| Blogs on Pete Hodgson
We’re going to add feature flagging to a node service in under five minutes using OpenFeature, the open, vendor-agnostic feature flagging SDK. We’ll be working with a simple express server, but if you have any basic familiarity with JavaScript and node you should be able to follow along. Hello, world Here’s the service we’ll be working on: server.js import * as express from 'express' import Router from 'express-promise-router' const app = express() const routes = Router(); app.use(rou...| Blogs on Pete Hodgson
I’ve recently been involved1 in OpenFeature, 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’s just a function call and an if statement, right? Well, no, not really. I’ll explain why, and then talk about some of the benefits that I hope OpenFeature will bring to the space. The Feature Flagging iceberg When I talk to people about adopting feature flags, I often describe feature flag managemen...| Blogs on Pete Hodgson
An Explaining Variable is a code-level pattern which reduces the need for code comments, making your software a little more self-documenting. Here we have a function with some non-obvious business logic, with a comment to explain what’s going on: before.js function determineShippingSpeed(shippingRoute, shippingMethod) { // if the shipping route is very short, or it’s by air if( shippingRoute.distance < 20 || [BY_AIR,BY_AIR_EXPRESS].includes(shippingMethod) ){ return SAME_DAY; } // ... } A...| Blogs on Pete Hodgson
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. 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 food1. Sadly, while they succeeded in being the first consumers, they also ended up being pretty much the only consumers.| Blogs on Pete Hodgson
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. When a startup is young, it’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 distin...| Blogs on Pete Hodgson
Every codebase carries some amount of technical debt. Every team would like to get better at managing that tech debt. The first step in managing something is making it visible. A tech debt wall is a simple, effective way to make tech debt visible. Building a tech debt wall A tech debt wall is a 2-dimensional map used to track a codebase’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 - roughl...| Blogs on Pete Hodgson
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. 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’s hard to see the big picture.| Blogs on Pete Hodgson
As engineering organizations move towards smaller services and more autonomous teams, it’s common to run into situations where teams are duplicating effort on “table stakes” platform functionality. Rather than spending time solving business problems, engineers waste that time building the same basic technical plumbing multiple times, using inconsistent approaches. Engineering organizations can avoid this waste by creating a Service Chassis - an org-specific service runtime which provide...| Blogs on Pete Hodgson
“Sorry, that just sounds… dangerous”. I sometimes hear things like this when explaining concepts like Trunk-based Development and Feature Flagging to someone who’s not worked that way before. The testers on a team are often the first to speak up. 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. I’m all for healthy skepticism, and when it comes to testing and feature flags some misgi...| Blogs on Pete Hodgson
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. I spend a fair amount of time helping engineering teams with the initial build and release of a product. There’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...| Blogs on Pete Hodgson
This post is part of a series, covering techniques for testing redux reducers. In the first post of this series we discovered that it’s better to test reducers and actions together, as an integrated, cohesive unit - the duck. In the next part of the series 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 t...| Blogs on Pete Hodgson
This post is part of a series, covering techniques for testing redux reducers. In the first installment of the series we saw that it’s better to test reducers and actions together as an integrated, cohesive unit. In this post we’ll take this idea a little further and see what happens when we pull selectors into our reducer testing strategy. Specifically, we’re going to see whether we can make our reducer unit tests even more expressive, by validating our expectations of redux state usin...| Blogs on Pete Hodgson
This post is part one of aseries, covering techniques for testing redux reducers. 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. 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 te...| Blogs on Pete Hodgson
Here’s a crazy idea: software companies should require new engineers to make a production code change on their first day at work. Not allow engineers to deploy to prod on day one, but require it. What exactly is it about this idea that makes it seem crazy, or at least ill-advised? Is it that it’s a bad idea, or is it that it doesn’t seem feasible? 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 brought in from Fli...| Blogs on Pete Hodgson
I once thought that code review was all about catching bugs, but I was wrong. In this article I’ll discuss the additional value that teams get from code review beyond defect detection, and how Pull Requests (PRs) can get in the way of maximizing that value. Understanding the drawbacks of PR-based workflows, we’ll then discover a few simple practices which prevent pull requests from dragging down a team’s efficiency. Almost every team I’ve worked with in the last few years has been usi...| Blogs on Pete Hodgson
Engineering decisions made at the very early stages of a product’s life can have repercussions which extend far into the future. Making well-informed, thoughtful decisions is important. 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 - You’ll Never Know Less Than You Know Right Now. In the second post I covered maxim 2 - Optimize For Iteration. In ...| Blogs on Pete Hodgson
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 Continuous Delivery 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. The rise of the static site The client-side capabilities of modern browsers have made great strides in recent years. We’ve also seen an explosion in P...| Blogs on Pete Hodgson
Engineering decisions made at the very early stages of a product’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 first post in this series I introduced the first maxim - “You’ll Never Know Less Than You Know Right Now”. In this post I’ll cover maxim 2 - “Optimize For Iteration”. In an upcoming post I’ll talk about the final maxim ...| Blogs on Pete Hodgson
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 after the MVP. Grounding your choices against a small set of guiding principles will help keep them sensible and coherent.| Blogs on Pete Hodgson
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. Matchers when making assertions Unit-testing JavaScript code means making assertions about the shape of things. We make simple assertions like expect(result).to.eql("SUCCE...| Blogs on Pete Hodgson
In this post I’ll show three different techniques for encapsulating internal state in JavaScript, concluding with my preferred approach, a pattern I’m calling “Symbol-keyed State Accessor”. 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 class or prototype to create a Value Object type, and managing the object’s internal state via this. Here...| Blogs on Pete Hodgson
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. Stir plates aren’t super expensive, but at around100USD they’re not something you’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 sinc...| Blogs on Pete Hodgson
I travel a fair bit for work and have discovered that when you’re living in a hotel it’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 good 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...| Blogs on Pete Hodgson
I had the opportunity to present at Forward JS a few weeks ago on “different.js”. No, the presentation wasn’t about a new, shiny, artisinally-crafted micro-framework. I talked about how to “level up” 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 this and prototypes in favor of closures. Slides for the talk are here, video is below (thanks New Circle).| Blogs on Pete Hodgson
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’re not careful then one rogue provider can create a really poor experience for users on your site. I don’t have any original thoughts here, just a collection of resources which I found that summarize techniques I’ve heard about in the past ...| Blogs on Pete Hodgson
I got to present a talk at RailsConf this year. video is here, slides are here. My talk was about Rails as an SOA client. I talked about things like Conway’s Law, Contract Testing, Hexagonal Architecture, the faraday gem, and HTTP Caching.| Blogs on Pete Hodgson
./go can eventually become the primary interface into the dev tooling for the project. Every ThoughtWorks project I’ve ever been on has a script in the root of the project repo, often named ./go or ./go.sh (or ./go.bat if you’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 r...| Blogs on Pete Hodgson
I’m a bit fan of static sites, and have created afairfewlittlestaticone-page 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’re reading one of those S3-hosted static sites right now! 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. “I’m a dev”, I thought to my...| Blogs on Pete Hodgson
Martin Fowler recently added a bliki entry for the Page Object pattern. It’s a good writeup - if you haven’t read it I recommend doing so now. Go ahead. I’ll wait. 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 with assertions baked in but couldn’t come up with a compelling reason...| Blogs on Pete Hodgson
I’m pleased to announce rack-flags, a very simple way to add feature flags/bits/toggles to your Rails app (or any other rack-based web app). The rack-flags gem allows you to define a set of feature flags 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.| Blogs on Pete Hodgson
##TL;DR I’ll be running a couple of free workshops on iOS Unit Testing in San Francisco in late August/early September. If you’d like to attend please fill out this simple form and I’ll be in touch with details. ##Why is it free? What’s the catch? I’m preparing to run a paid 3 hour workshop on iOS unit testing for the upcoming super-awesome StrangeLoop conference. As part of that prep I’ll be doing a couple of ‘dry runs’ of the workshop so I can fine tune the content, delivery...| Blogs on Pete Hodgson
Travis CI is a cloud-based Continuous Integration service which is free to use (but only on public github projects). They recentlyannounced support for OS X agents, which means you can now use Travis to build and test iOS applications. In this post I’ll show how I set up basic CI for an example iOS app using Travis, with the help of xctool. xctool is the ‘better xcodebuild’ which Facebook recently open-sourced. It allows you to not only build your app on the command line but also run yo...| Blogs on Pete Hodgson
In the previousposts in this series we’ve done some test-driven development of Backbone Models, Collections, and Views. In this post I’m going to cover another role which I believe should be present in most SPA Backbone apps: Controllers. Controllers in a Backbone app There’s nothing in the Backbone.js library for building Controllers. There’s not a Backbone.Controller for you to extend from. But that doesn’t mean that Controllers don’t have a part to play in your Backbone app. I ...| Blogs on Pete Hodgson
In this series of posts I’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’ll discover. Setup We’ll be using backbone and underscore to build a single page app which simulates a card wall. We’ll be writing our app and our tests using coffeescript. If there’s enough interest I’d be happy to set up a JavaScript translation of the code snippets - pl...| Blogs on Pete Hodgson
In the previous installment 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. In this installment we’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.| Blogs on Pete Hodgson
In my previous post I discussed why you might want to deploy to Heroku as part of a CI build. I demonstrated how my heroku-headless gem makes it very easy to script such a deployment. In this post I’ll go into the details on how that gem does its work. I’ll talk about what the Heroku deployment tooling expects to be available, why that’s not necessarily going to be there in the context of a CI build environment, and how the gem helps resolve that.| Blogs on Pete Hodgson
If you’re working on top of a modern web stack then the Heroku 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 git push heroku. Heroku as a staging environment This makes Heroku a compelling choice for hosting a staging environment for your application. Staging environment contain...| Blogs on Pete Hodgson
In this post I’ll describe an experiment where rather than using Frank to write iOS acceptance tests I instead combined Kiwi 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 KIF works. What? Before I start, let me be clear that I personally wouldn’t use this approach to writing acceptance tests. I much prefer using a higher-level language like ruby to write ...| Blogs on Pete Hodgson
Introduction If you’re practicing Continuous Delivery then you’re probably using Feature Flags to hide half-baked features which are being shipped into production as latent code. It’s useful to allow individual users to manually override 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. This is a similar concept to the Canary Releas...| Blogs on Pete Hodgson
A Frank field trip Today I’m visiting 955 Dreams (the guys who make Band of the Day, amongst other things) visiting my friend (and their CTO) Chris. We had a fun time figuring out how to get Frank to play nicely with CocoaPods. It wasn’t that tricky, and I’m going to document what we found here to hopefully make it easier for other Cocoapod users. Problem the first Frank had trouble with cocoapods for two reasons. Firstly when frankifying the app we needed to frankify the app’s Xcode ...| Blogs on Pete Hodgson
One of the many geeky hats I wear is that of maintainer for Frank, 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’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 c...| Blogs on Pete Hodgson
I’m excited to announce PublicAutomation, a friendly wrapper around Apple’s private UIAutomation framework. PublicAutomation allows you to use Apple’s own private framework to simulate user interactions (taps, swipes, keyboard typing) via a simple Objective-C API. Previous approaches to this problem have relied on reverse-engineering and monkey-patching iOS’s touch events system. PublicAutomation takes a different approach. It links in the low-level API of the private framework which ...| Blogs on Pete Hodgson
In my last post I talked about setting up a basic deployment pipeline using marker branches in git to keep track of what was where. In this post I want to go into a little more detail describing how these marker branches work. To do that I’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.| Blogs on Pete Hodgson
I spent a fun evening recently setting up a deployment pipeline for this blog. I’d like to share some details on what I set up and why. The motivation was that I wanted some way to publish draft blog entries for other people to review, but I didn’t want these drafts to show up on my public site. I played with Octopress’s published: false option, but it really didn’t give me what I needed. Then I saw someone commenting that the ideal would be to have a preview version of the entire sit...| Blogs on Pete Hodgson
Frank is a tool that allows you to run automated acceptance tests against your native iOS application. A major reason for creating automated acceptance tests is so that you can run them as part of your Continuous Integration (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. In this post I’ll show how to configure a basic CI setup using Jenkins which will build your app and run Frank ...| Blogs on Pete Hodgson
I’ve recently spent a few hours investigating how feasible it would be to use Apple’s private UIAutomation framework to simulate user interactions in iOS apps. The motivation for this is of course being able to use this for Frank, the UI testing tool I maintain. This post will summarize my progress to date. You can also check out my work-in-progress uiautomation branch for Frank. Note that that branch is very rough and ready at the moment. I pushed it up to my github repo just so anyone w...| Blogs on Pete Hodgson
You’ve heard about how awesome Frank is and you’re all fired up about getting some automated functional testing set up for your iOS app. Now you’re ready to start writing your first test. In this article I’ll cover the fundamentals of writing Frank tests, using an open source iOS application written for the 2012 Olympic Games as an example. get the code for your app I’m guessing you’ll already have the code for your own app, but if you’d like to follow along with the examples in...| Blogs on Pete Hodgson
I’ve always known that it’s really important new users of Frank 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. 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’s startup code.| Blogs on Pete Hodgson
Software designs don’t pop into existance fully formed. They evolve over time. In this post I’m going to show how a concept can grow from a simple method parameter to an all-growed-up Domain Object. Initial requirements Imagine we’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:| Blogs on Pete Hodgson
On a recent project we were applying Continous Delivery practices and were releasing to production reasonably frequently - sometimes multiple times a week. We didn’t want to expose features which were under active development in our production environment but we also wanted to avoid feature branches. I’m going to describe the simple approach we used to solve this problem using feature flagging with javascript and CSS. What are feature flags? Features flags (aka feature bits, feature toggl...| Blogs on Pete Hodgson
Yes, like many other dork bloggers I’ve jumped onto the Octopress bandwagon. 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’m that vain), but I’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.| Blogs on Pete Hodgson
It seems that everyjavascriptframeworkofacertainsize 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’d like to describe an alternative approach to dealing with types in JavaScript. This approach comes from a recent project where my team was building a pure-JavaScript single-page web application. This wasn’t a huge codebase, but due to the single-page nature of the app it did have a reasonable amoun...| Blogs on Pete Hodgson
Intro We’ve been building mobile web apps using JQuery Mobile with the main target being webkit-based mobile browsers - Android and iPhone, basically. We’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’s what I’ll be sharing here. The approach Our team members have a lot of experience using Cucumber to write automated acceptance tests, and we’re big fans. In previous projects we we...| Blogs on Pete Hodgson
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’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 callbacks which are subsequently invoked once the operation completes, allowing you to move on ...| Blogs on Pete Hodgson
The Background 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'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.| Blogs on Pete Hodgson
What's Symbiote? Frank comes with a useful little tool called Symbiote. It's a little web app which is embedded inside your native iOS application. Its purpose is to let you inspect the current state of your app'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. Recently I've added some improvements to Symbiote, adding some new features and making it easier to use. This screencast demonstrates most of...| Blogs on Pete Hodgson
I maintain Frank, a tool which lets you write automated acceptance tests for your iOS app using Cucumber. I've been trying to reduce the hurdles in getting started with Frank. My latest attempt is to record a tutorial screencast showing how to take your existing app and 'Frankify' it. 'Frankifying' 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 intimida...| Blogs on Pete Hodgson
Testing how a unit of code interacts with its environment 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. 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’re controlling what the System Under Test (SUT) pulls in from its environment (the 2 and the 4) and also observing what it pushes o...| Blogs on Pete Hodgson
Introduction In this post I’m going to cover the basics of creating and publishing a gem using the bundle gem command provided by Bundler. We’re going to use bundler to create a gem template for us. We’ll then take that skeleton gem, add some functionality to it, and publish it for all the world to use. 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 Sinatra web app which tells you the t...| Blogs on Pete Hodgson
I just published a new Ruby gem called timestamped-scenarios. As usual the code is also available on github. What's this gem for? 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. You might wonder why I created these formatters. I...| Blogs on Pete Hodgson
In my last post I talked about memory leaks in Objective C. In this post I'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'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...| Blogs on Pete Hodgson
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's examine one very common mistake, which I will call the Property Assignment Memory Leak. I've seen this a few times, and indeed committed this error myself du...| Blogs on Pete Hodgson
Some colleagues at Thoughtworks and I recently recorded a 30 minute podcast about Frank, our UI automation tool for iPhone/iPad testing which I introduced in this post. In the podcast we cover: an overview of Frank, what it is and where it came from. How our testers and developers use Frank and cucumber at our current client (and how we'd ideally like to be using it). Alternatives to Frank, such as iCuke and brominet. Some waffling by me about some of the reasoning that drove my design decisi...| Blogs on Pete Hodgson
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't quite what we needed, so we built our own 'Frankenstein's Monster' by plumbing t...| Blogs on Pete Hodgson
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 "Red, Green, Refactor", I think a more accurate version would be "Red, Green, Red, Green, Red, Green, Refactor". Less catchy, I know. Letting tests drive your design is great, but if you're not careful you will...| Blogs on Pete Hodgson
Generating HTML tables in ruby has always seemed like more of a hassle than it should be. Most of the times that I've had to do it I've been a little frustrated with how, well, ugly the view code looks. So, I decided I'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.| Blogs on Pete Hodgson
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: ...we developed a new monitoring script, called Stormcloud, to kill Unicorns when they ran out of control... ...Monit would still monitor the master Unicorn process, but Stormcloud would watch over the Unicorns... ...child death during request processing ... would cause that request and all requests queued in the mongre...| Blogs on Pete Hodgson
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: var tt:TickTock = new TickTock(); tt.start(); doSomeWork(); tt.stop(); trace( "That took "+tickTock.elapsedTimeInMilliseconds+" millisconds" ); or in a fancy-pants, functional, closure-y way: var tt:TickTock = TickTock.measure( function(){ doSomeWork(); }); trace( "That took "+tickTock.elapsedTimeInMilliseconds+" millisco...| Blogs on Pete Hodgson
I listened to a really good podcast 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-fr...| Blogs on Pete Hodgson
After seeing the Primitive Obsession code smell crop up in a few different places recently I got to thinking about it in the context of static and dynamic languages. 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 Primitive Obsession would be a method like:| Blogs on Pete Hodgson
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 some 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 ca...| Blogs on Pete Hodgson
I keep meaning to write up some of the useful gems (if you'll pardon the pun) which are hidden in the super-handy Facets gem. Today I'll cover Enumerable#mash. Let's say you have a list of Users, and you'd like to create a hash which lets you look up the Users based on their login. You might write something like: def create_login_hash_for( users ) user_login_hash = {} users.each do |user| user_login_hash[user.login] = user end user_login_hash end With Enumerable#mash, you can trim that down to:| Blogs on Pete Hodgson
I'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'd feel pretty crippled without it. In fact, I don't think I would ever go back to a centralized system like svn at this point. In a pinch I'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.| Blogs on Pete Hodgson
I'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's say you're checking an input parameter to guard against invalid input. You might write something like: unless VALID_COMMANDS.include?( command_param ) whine_to_user() return end This makes sense, but it seems backwards to me. I don't care whether some array has a value in it so much as I care whether a value is i...| Blogs on Pete Hodgson
Flex Patterns: Presentation Adapter Encapsulate the logic for presenting a domain object, and provide an object for skinny views to perform data-binding against. Problem When using Presentation Model 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 ...| Blogs on Pete Hodgson
Today I had the great pleasure of deleting a huge chunk of old code from my application. Using git it's surprisingly easy to figure out exactly how much code: git checkout -b deletion_task # ... delete lots of code... # ... time passes... git add -i git commit git co master FILES_DELETED=`git diff --summary master deletion_task | grep "^ delete" | wc -l` LINES_DELETED=`git diff --summary master deletion_task | grep "^ delete" | awk '{ print $4 }' | xargs cat | wc -l` echo -e "$FILES_DELETED f...| Blogs on Pete Hodgson
I recently created Gimme, a small ruby gem which allows you to configure and access a simple Registry using a nice little DSL. Gimme in a paragraph 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. Show me teh codez Here's a s...| Blogs on Pete Hodgson
Just a quick post to mention that I recently did an experiment with extending mock4as to use Drew Bourne's awesome hamcrest-as3. The idea for this work is to specify mocked method arguments in a more flexible way. It was actually surprisingly trivial to implement. I'll be writing a more detailed post in the future explaining what these changes mean to a user of mock4as. I also took the opportunity to experiment with using git and github, so the changes are available to all and sundry as a git...| Blogs on Pete Hodgson
Presentation Model We want to achieve a Skinny View without the View needing to expose UI details to the Controller. Also known as View State, Logical View Problem We want to have as much presentation logic under test as we can by having a Skinny View. At the same time we don't want our Controller to be burdened with the minutiae of maintaining UI elements.| Blogs on Pete Hodgson
I think one of the more frequent issues that people have when starting to work with a RESTful architecture is that "there aren't enough verbs". Why having few verbs is good 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 any REST system...| Blogs on Pete Hodgson
As I mentioned in a previous post I've recently been adding some features to mock4as, a mocking library for ActionScript. In this post I'm going to talk about the new mock.willExecute(...) feature which I recently implemented. 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...| Blogs on Pete Hodgson
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. Let's say there's a Person class: class Person attr_accessor :first_name, :last_name, :age end and I have a collection of people which I'd like to sort by age. An obvious approach would be: people.sort_by{ |person...| Blogs on Pete Hodgson
Strategic Architectural Initiatives help align autonomous teams around a technical strategy. We'll learn techniques for co-creating an SAI and ensuring that it's widely understood.| Pete Hodgson
empower software teams to make self-directed, strategically-aligned decisions within a rapid feedback loop| Pete Hodgson
Get In Touch| blog.thepete.net
Almost every company feels pain when it comes to organizing work that spans multiple teams. Let's look at different patterns for code ownership amongst teams, and code collaboration across teams.| Pete Hodgson
Achieving sustained architectural progress at scale takes a clearly articulated strategy, a strong product/tech partnership, and empowered teams.| Pete Hodgson