My #1 value is transparency. Transparency is how I conduct my business and professional relationships. I expect anyone I do business with to reciprocate. From recording my time and billing, to keeping accurate backlogs, and giving warnings when bad news is coming are some of the ways I remain transparent with my clients.
My Work Week
My work week is designed to maintain a sustainable pace and work life balance. This model ensures I deliver on milestones, grow my business and maintain a high level proficiency in my craft.
I work a sustainable pace. I work three days for clients and consulting, and two days on "investment time". I typically spend Monday - Wednesday on client work and Thursday - Friday on investment.
If there is a holiday during the week, or if I am sick or unexpectedly absent from client work, I will use investment days as an extra client day to avoid slipping behind schedule.
When taking a planned vacation for attending a conference spanning multiple days, I generally do not "make up" client work on investment days.
Sending off-hours communication may create an unintended sense of urgency with the recipients of my message. I will avoid creating that urgency when possible.
Unless actually urgent, I will generally ignore off-hour messages which I receive and handle them once I am back at work.
Investment time is time for investment in myself, my company, and my community. Primarily this means doing something that interests me like learning a new programming language, contributing to open source, discussing interesting things, attending community events, or reading an educational book. The goal is to encourage myself to improve and share my knowledge.
Ideas for investment time include:
- Contribute to open source software
- Write a blog post
- Work on conference and meetup talks and proposals
- Volunteer mentor for another solid learning organization
- Meet someone new or make an exsiting relationship stronger
- Answer questions on StackOverflow
- Build on an idea of my own
I primarily develop in Ruby on Rails. It’s a robust, proven framework with a large community. It’s well structured, so whether the project is brand new or 5 years old, it’s familiar to other developers and the learning curve won’t be steep. It makes security easy so I can focus on features instead of worrying about cross-site scripting or SQL injection. Out of the box I get an admin interface. The ORM is really nice. I have wonderful deployment tools built and ready to go. Most importantly, there’s a large body of knowledge sitting around you that is intimately familiar with Rails.
If you decide to go with another framework, that’s cool. I only ask that you consider how it will impact development speed of your project. Ask yourself this: Will others have to learn a new language? Is this framework well supported? What does this framework give me that Rails doesn’t?
Outside of the Ruby on Rails stack, I will develop in the Python stack if requested.
Examples of languages I typically use are:
- Ruby: My server-side preference
"Server-side" means code that is run on servers provided by the application hosting company. "Client-side" means code that is run in users' web browswers.
Examples of frameworks I typically use are:
- Ruby on Rails
A framework is a library that makes performing a particular task in a programming language easier. Like the framework of a house, it is there when I begin programming and is always there giving the program structure and support.
It can be difficult to switch from one framework to another. The more code that's written specifically for Rails, the harder it will be to switch to Django. That would approach "total rewrite" territory.
For data that must be saved and stored correctly, I use PostgreSQL (I usually refer to it as "Postgres").
It's a 30 year old open source database that is highly respected, well supported by documentation and hosting providers, and used by any developer who knows the SQL standard.
In recent years, a movement called NoSQL has gained popularity. Best translated as "not only SQL", tremendous effort has been made to create different kinds of databases for different use cases, often based off academic or industry research.
My most frequently used NoSQL database is Redis, which I use for storing transient, high quantity read/write data such as activity feeds, tags, background jobs, sessions, tokens, and counters.
Redis is reliable, open-source, and simple. It offers high performance and reliable predictions of its performance. It can flexibly model different data sets but I typically use it for small data structures, not large images, videos, or text documents.
I typically use Redis to Go to host my production Redis databases.
In contrast with a proprietary license, the source code of an open source program is made available for review, modification and redistribution. The difference between open source licenses is what I can and can't do with the source code.
Open source licenses can be divided in two categories: permissive and copyleft.
Permissive examples include:
- Berkeley Software Distribution (BSD) licenses
- MIT license
- Apache license
- A copyleft example is the General Public License (GPL).
Both categories have the purpose of establishing the copyright holder for the software, granting users the right to copy, modify and redistribute it, protecting the copyright holder from any potential guarantees that the software may provide (software is provided as-is), and optionally imposing some restrictions.
Permissive licenses let us modify a program, redistribute it, and even sell it. I can embed or link code with other programs without restriction or explicit permission by the copyright holder.
Copyleft licenses only allow us to link or distribute code with other code that has the same license. It also forces modifications to be released under the same license. Combining anything with the GPL makes it GPL.
Non-copyleft licenses do not enforce derivative works to also be open source.
Some software is released under a dual license: both a permissive and copyleft license. This provides developers who use the dual licensed code to apply the license that better suits their needs.
Most of the software I use has a permissive license:
- PostgreSQL, PostgreSQL License (BSD based)
- Redis, BSD
- Ruby (MRI), Ruby license (BSD based)
- Ruby on Rails, MIT
- jQuery, Dual MIT and GPL
The majority of my development practices follow practices detailed in Kent Beck's classic Extreme Programming Explained: Embrace Change and in Gerald Weinberg's The Psychology of Computer Programming.
I always use source code control. It's like a time machine. I can work in parallel universes of my source code, experimenting without fear of losing work. Roll back if something goes wrong.
Git is an open source source code control system written by Linus Torvalds. It's fast and great for working in branches.
I use GitHub for hosting my git repositories.
I write code in a consistent style that emphasizes cleanliness and communication.
High level guidelines:
- Be consistent.
- Don't rewrite existing code to follow this guide.
- Don't violate a guideline without a good reason.
- A reason is good when you can convince a others.
Test-Driven Development (TDD) is perhaps the most important Extreme Programming (XP) rule that I practice.
Business benefits of TDD:
- Deliver more value, faster
- Always ship working software
- Adapt to change quickly
Code benefits of TDD:
- Readable specs and code
- Clean public interfaces
- Decoupled modules
Process benefits of TDD:
- Regression safety net
- Fearless refactoring
- Team trust
At a high level, how to test is very simple:
- Write test first.
- Red-Green-Refactor cycle.
Acceptance tests are code created from jobs stories. This code is run against the application. When executed for the first time, the test will fail. I then write application code until the test passes.
When the test passes, then I commit the code into version control with a message such as:
Guest creates pledge
The code is then run on the Continuous Integration server to make sure the acceptance test still passes in an environment that matches the production environment.
Meanwhile, the code is pushed to the staging environment and I test it in the browser.
When the acceptance test is green for the CI server and I am satisfied that the jobs story is complete on staging, the feature can be deployed to production at will. This can result in features being pushed to production very frequently, and therefore more value is being delivered to customers sooner.
The third step of the "red, green, refactor" step is refactoring, the process of improving the design of existing code without altering its external behavior. It's a critical step in the process.
We live in a magical modern era where many problems have already been solved for us. I focus on the client's product as much as possible and outsource operations as much as possible to external services.
This saves time and money. I can get started using those services in minutes. Our clients pay a service tens or hundreds of dollars per month instead of paying developers thousands or tens of thousands.
I often create a Google spreadsheet listing the monthly cost, description, and credentials of each of our clients' external services. It includes line items like GitHub, Heroku, SendGrid, New Relic, Airbrake, and Splunk.
Most of the things I do are solve problems. There’s no need for me to write my own analytics or crash reporting software or have a physical server. Instead I use services and stick to proven techniques.
I use Heroku. It's a platform built on Amazon's cloud infrastructure. It is simple to use when our app is just a toy and is built to scale up for high concurrency or high sustained load.
Like Rails, Heroku uses conventions to make decisions for us that are unnecessary for us to make. Some things like web servers and app servers are solved problems. They act as our outsourced operations team. The amount of time I can focus on the product instead of solved problems is worth the premium over bare-bones Amazon Web Services.
The cloud promises lower operating costs, especially at the beginning when capacity can be lower. Forget about sunk costs of expensive servers.
The cloud and the services it enables will empower our clients' businesses to start and operate in a manner that has never been possible before without significant upfront investment.
If I offer file uploads for features like user avatars, I upload them to Amazon S3.
I use NewRelic (Free-$100s/month) to monitor performance of production applications.
Debugging performance might be the best part of a developer's job. There's a clear, numeric problem. When I fix it, that number improves. I can say things like "I made this 175% better."
There's many established techniques for fixing performance problems. A number of them come "for free" with Rails + Heroku:
- Amazon server clusters
- Asset pipeline
- SQL query caching
A number of them require developer thought:
- Database indexing
- Eager loading
- HTTP caching
Page caching is the heaviest handed technique I have, but if I can cache an entire page and push it into a CDN, that will be the fastest option.
I use Rollbar Bug Tracker (Free-$249/month).
I use Sendgrid (free - $399.95 per month) to have our application deliver email to users, known as transactional email.
Examples of transactional email are:
- Follow ups after the first 3 days of use
- Free trial is expiring
- Message another user in the system
For collecting payments from users via credit or debit card, I use Stripe. It is a payment gateway and merchant account. I also use it for recurring billing.
Charges for Stripe will vary depending on usage. Successful charges are 2.9% + 30 cents. There are no setup fees, monthly fees, or card storage fees.
I am a developer. I want to design and develop software. Before I can do that, I need clients to hire me. The following section details how my sales process works and answers commonly asked questions by potential clients.
The overall process is:
- Someone contacts me.
- I have them fill out our new project form.
- I have a phone call or meet them for coffee.
- Qualify/disqualify: am I a good fit for the client?
- Qualify/disqualify: is the client a good fit for me?
- Understand the client's vision.
- Agree to the outcomes we're trying to achieve.
- Estimate iterations.
- Schedule for the iterations.
- Sign the contract.
- Pay me for the first iteration.
- I begin work.
No Fixed Bids
Some consulting relationships start with a requirements document or RFP ("Request For Proposal"). The requirements are often extremely detailed.
The probability of this document containing the optimum feature set is extremely low. The right features are better learned through user interviews, prototyping, releasing actual software, and getting feedback from real users.
Based on that document, clients expect consultants in the industry to submit an exact timeframe and bid. This contract style sets the client and consultant working against each other right from day one. Instead of focusing on designing the product experience or evaluating what assumptions were wrong, they spend time negotiating about what was meant in a document written a long time ago or focusing on arbitrary deadlines. But it's worse than negotiating; it's retroactively discussing something that no one remembers the same way.
As you might have guessed, I don't do fixed-bid, fixed-feature-set proposals.
I do need to know clients' budgets. This is often uncomfortable for them but their budget helps determines what scope is possible. It saves time. If they don't know their budget, I discuss different options.
I talk about breaking product rollout into stages and try to improve the product's chances of success at each stage by:
- Focusing on a small subset of features.
- Designing a valuable user experience.
- Developing a meaningful relationship with users.
- Budgeting for marketing tactics to tell users about the product.
- Designing interactions into the product for users to bring other users to the product.
Do Not Exceed
A Do Not Exceed is a term referring to a number that both parties will actively work towards to not exceed. I bill in a Time & Materials manner (hourly), and give copious amounts of updates along the way for my clients. This means that when I reach key milestones in my budget, I will inform my client, revisit my projectons, and readjust my expectations.
I like this approach because it is a mutual process to ensure that design and engineering budgets are not over-committed and yet are not over-estimated. Each week as I work through the backlog of work in front of me, I should have a clearer and clearer picture of when the launch will occur. If I project a launch past the budget amount, I work with the client to ensure appropriate alternatives to fit within the Timeline.