This document is an attempt to pin down all the things you don't think about when quoting for a project, and hopefully provide a starting point for some kind of framework to make quoting, working and delivering small-medium jobs more predictable and less stressful.
The hardest bit of any job, and lots of pitfalls
Estimating the work
- the actual work of what you see on screen will only be a fraction of the work to do
- you can estimate the steps needed "to do a thing" but not always the complexity of the steps
- don't underestimate "the work to do the work", "the work between the work" and "the work around the work"
Price for value
- if you can do something others can't, price accordingly
- if the hassle for the client starting again, or going elsewhere is prohibitive, price accordingly
You need to account for working with unfamiliar services
Domain knowledge
- multi-domain or multi-dependency projects are more difficult (naming, objects, APIs, etc)
Do you know the technology?
- knowing something exists is very different from knowing it inside out
- it may be difficult or even extremely difficult to learn, meaning you spend a long time writing bad code
- it may turn out to be unsuitable after all
- you may not properly learn it and create a mess which will need to be cleared up at some point
Picking the right technology
- Nuxt vs Vue
- Elastic vs Postgres
- Azure vs ???
You may be skilled, but it's highly unlikely you will know everything you need to
You won't know what you don't know
- you may need to learn new skills (elastic, nuxt, some api, etc)
- you may not know this until it comes time to actually do the work
- this could significantly impact your timelines / profit margins / client relationship
- is there any way to predict this in advance?
Your current skills may be adequate for small but not medium or large jobs
- relying on basic skills may get you over the line, or may bite you later in the project
- how should you tackle this? Level up? Subcontract? Who will pay for this?
Unforeseen problems
- you will underestimate the difficulty of some tasks
- you will underestimate the timings on some tasks
- you may have showstoppers where you can't go on
- how should you predict / manage / cost for these?
Third party tools
- save time by using something already made for the job
- note that depending on the scale of the tool, it will still take time to learn
First party tools
- sometimes, you have to build it yourself
- time saved learning something else may be taken up in planning, development, debugging, refactoring, packaging, documenting
- a tool could take a few days or a few weeks, and will require ongoing maintenance and updates
You need to put a lot of things in place before you can do the actual work
Project setup (these could all be separate sections!)
- config and build setup
- keys and security
- 3rd-party dependencies
- component library
- initial folder structure
- routing and layouts
- Api
- login and logout
- store and state
- additional services
- individual utilities
- repositories and deployment
Dependencies
Design
- new layouts to think about
- the ui kit does not account for many use cases, and does not cover layout
- figuring out how all the ui components should fit together in your layout may take longer
- compound UI components may take longer
Also see "the work between the work"
POC is completely different from something the client / users will be happy with
Developing the actual code (utility, library, service, component, feature, module, app)
- POC is bare minimum to show it can work, crap UI, can only be used by devs
- Alpha is first rough working version, that can be used by (brave!) humans
- Beta / MVC is mainly working, but there may be bugs
- Release is working, big-free, polished, potentially documented and with tests
Getting the details right takes time
- the 80/20 rule of getting things perfect
- changing your mind or making something better
- realising that you were doing it wrong
- iterating (getting it working, vs getting it right) to the best solution
- keeping things consistent
Examples
- API with notifications
- form interaction
- form validation
- modals
Stuff that if it wasn't there would look broken
- empty states
- loading indicators
- error handling
- notifications
Design and finish
- adding the polish to make it look nice
- fixing bugs which may or may not be your fault
Quality control
- adding tests
- adding support like storybook
- writing documentation
Any project longer than a few weeks has invisible costs built in
Note: these kinds of changes are invisible to the client!
Debugging
- your own code because it's not working as expected
- third party code or configuration because it doesn't support something you need
Configuration
- updating or fixing configuration
- keeping up with framework changes and patches
Tooling
- updating build tools to make things faster / more reliable
- building dev tools to help you do the work
- introducing new processes and tools
General maintenance as you go along
- building systems to keep things DRY
Migrations
- could be database, services, anything
- planning a migration
- running two sets of code
- implementing the migration
Refactoring
- stitch-in-time updates (even if out of scope) so it doesn't turn to shit
- larger refactors to prevent spaghetti or make hard things possible
- updating older systems as you find bugs or expand functionality
Defactoring
- as requirements change, you may even need to take functionality out!
- removing complexity can sometimes be as hard as adding it
Design
- what is works in once place today, may not work in two places tomorrow
- new layouts or components may be required (dropdown, modal, notification)
- as the app gets more advanced, more components will be expected to work together
Requirements
- expectation management / negotiation (over or under / difference of opinion)
- omissions
Changes
- client changes
- feature creep
- mission creep
Larger projects have different constraints and inherent increased complexity vs small projects
Going from small to medium
- think about thresholds when going from a simple app to a complex app (routing, store, tools, etc, etc)
- once the application grows, consistency is an issue; adding new layouts to old, keeping track of components
- you'll need to scale up things like naming conventions, css file structure, store paths, etc
- taking time to make the styling consistent as it scales
Increased size will (in part) mean increased complexity
- complexity can increase as more features are added ((n*(n+1))/2)
- coupled features means more dependencies
- something which was quick to edit at a small scale may slow down as the project grows
- need to account for more time moving between sections of the application
Shortcuts
- shortcuts taken in a small project will likely not scale well in a larger project
- for example, window.prompt, password protected folders,
Hierarchies
- meaning folders, routes, APIs
- as the app grows you may need to introduce additional levels
State
- local state is easy, but not flexible
- need to access same state from two different places? Make it global
- the calls and format will be different
- you may need additional tooling like Vuex Pathify
- or, it may bemore complex than a simple vuex store
- might need to build services, use a new technology, or something else
Persistence
- initial state / loading
- saving the data
- loading the data
- using cookies, localstorage, URL, database
Things you could get away with in a small project, you might not in a big project
- updating the URL with form changes
There will always be a significant amount of work around the work
Experiments
- reading docs
- trying out libraries
- code sketches
Internal work
- code reviews
- writing issues
- repository management
Client management
- meetings
- reviews
Once the project is live, or nearly live, there is still work to do
Sections
- hosting
- deployment
- updates / upgrades
- bug fixes
- security
Often the "work" is only a fraction of the work.
Phrase | Meaning |
---|---|
The work to get the work | Planning, quoting, pitching |
The work before the work | Setup, configuration, prototyping |
The work | The actual build, product, etc |
The work between the work | Debugging, development, refactoring, tooling, maintenance |
The work beyond the work | Omissions, scope creep, mission creep |
The work around the work | Client meetings, code reviews, project management, etc |
The work after the work | Hosting, deployment, support, security |
See final article here.
Great insights! I really like organizing around the work to do the work, the work between the work and the work around the work. It's a unique take -- but very sensible. Here are suggestions that might fit in the "The work around the work" or "Requirements" section:
Consider adding more detail on duration. Although it's mentioned in The Work Between the Work, the length of an engagement usually correlates directly with the risk of a bad estimate. I almost feel like you could write separate articles for short- vs. longer-term projects. Maybe a note about how/when a short-term dev project turns into a long-term project and how to consider this possibility when preparing your estimate.
Maybe a section about estimating by project phases -- breaking up a large estimate into smaller phases that are easier to estimate. Webdev projects tend to have clearly defined phases.
Mention the importance of client sign-off to signify the closure of a phase and protect against feaure creep.