How’s your greenfield project game?
Here’s something a lot of devs would like to hear:
I’d say that anyone at senior level (and definitely above1) should have some justified2 thoughts on the greenfield question:
Obviously you can’t decide ahead of time a shopping list of what you’d use. But being well informed about some choices for when you do have to make those decisions can pay off. Not just because you might get put in that hot seat3, but also because researching around the question can make you more effective in your non-greenfield development work.
Decisions, decisions
Broadly we can split project technology decisions into two categories:
- A: project core (frameworks, APIs, data storage/handling)
- B: project structuring and building, peripheral tooling, pipeline/CI
To illustrate these categories, here’s some example choices for a fictional iOS project4:
Project core:
- SPM (in conjunction with tuist) for 3rd party libs5
- plain old Swift for dependency injection6 (i.e. no use of helpers like Swinject)
- Valet for securing data in keychain
- GRDB for non-trivial data persistence (sqlite)
- URLSession directly used for HTTPS comms (i.e. no use of helpers like Alamofire)
- Firebase for feature flags, analytics, auth
Project structuring and building, peripheral tooling, pipeline/CI:
- mise for consistent tool versioning and task running
- tuist for project structure management and cache
- SwiftSyntax for automatic generation of some types around analytics
- Fastlane for some local cert management
- swiftlint and swiftformat
- GitHub pipelines for CI/CD
- BrowserStack for remote on-device testing
Notice that one decision (DI) is not use a 3rd party helper at all; sometimes it’s the right choice.
Not all tools are necessarily decided by you, of course; you might start a new project with something like Firebase already committed to.
And some tools are outwith my two categories, e.g. Figma or Thunderdome.
Choosing the right tools
I’m going to sound like Captain Obvious here, but choosing appropriate tools is not just a matter of “this tool does that thing I need! Decided!”
Nothing is free. Even free (gratis) frameworks or libs have a cost: time invested in getting to know them, time cost if you have to remove them, costs of them being defective (time? organisation/dept/team reputation? etc.), and the opportunity cost of not using something else that is better!7
And some orgs consider free-gratis dependencies to be more risky than paid-for ones: if you rely on something that makes the author no income, they might have less skin in the game and it’s easier for them to stop maintaining this dependency.8 I’ve noticed sensitivity to this aspect particularly in my public sector work.
It’s not just cost, it’s potential cost, which dove-tails in with risk:
- what risk comes with a decision? e.g. architecture X might be excellent, but it’s hard to find devs right now that know that well. Or: This tool is great, but it’s unmaintained for 4 years now.
There’s a certain amount of crystal-ball gazing when making these decisions. You want your decisions to be correct here and now, but ideally also in five years time!
No-one knows what the future holds, but we can be diligent. We can also structure things so that it’s a bit less painful if we have to change some of our choices later.
Basic due diligence
Some signals for basic evaluation of a third party dependency:
- license – too restrictive with org/product aims?
- for free dependencies: is it actively maintained? By how many people? Does it exist just on one person’s whim? Is there any community around it, in case original author lost interest?
- for commercial dependencies: how is the company positioned? How’s their outlook? Are there alternatives?
- how responsive is the project to issues being filed? (could look at GitHub issue handling etc.)
- community reputation – how is it regarded? Look for the bad and the good. Who trusts it?
And there’s more technical due diligence such as
- source static check: look over source code for quality, lint it, look for potential security risks (e.g. if you see source for a string formatting lib reaching out to the network). How ‘old’ is the source, in terms of APIs and style? Is there obvious tech debt?
- runtime check: for security sensitive apps, run it in a safe environment (off your org network), monitor comms (ProxyMan, Charles, etc.) to look for anything unexpected, etc.
Justification proportionality rule
So the choice for an over-arching application architecture technology needs careful justification and due diligence. Compare that to e.g. a string formatting helper that is used in one place; that’s not too much bother to replace.9
The Golden Hammer
Every developer (we hope) reaches a point of maturity where they recognise the danger of the Golden Hammer mindset: when you have a golden hammer, everything looks like a nail.
Which is to say, none of these things are justification in themselves for using a tool:
- really liking it
- being heavily invested in it
- wanting to practice using it10
- not knowing any other tool
We should aim for self-awareness of possible bias, even if we are already familiar with the golden hammer principle!
Who gets to make greenfield projects?
I don’t have statistics on hand, but I can tell you that in my contracting career I’ve seen a lot of greenfield projects spun up by digital agencies.
If it’s the kind of project the agency has done quite a few of already then the project is usually reasonably structured. But this can also mean that the project isn’t using some of the newer and reasonable technologies it could be, because the agency has a house template they use for their technology X projects and this template exists in both new and existing projects; and they can’t update their template without causing effort/risk for the older projects.
And of course the minimum version of the targeted platform comes into it too. If you’re targeting something quite old, you can probably forget about that new exciting runtime feature X.
A war story
I was working with a client on their iOS app. It was using a commercial PDF display and markup library which was horrendous. I mean, the documentation was ‘look at the header file’, and then you find some of the header file comments were incorrect or even perfectly wrong (they said the exact opposite of the truth).
And this library was hardly maintained at all. And memorably, despite Apple warning years in advance about the deprecation of libstdc++
(you had to move to libc++
), the lib company didn’t fix it in time. We reached the point where we weren’t going to be able to release new builds of the iOS app!
There was an alternative commercial PDF lib, that is highly regarded, and I successfully argued for its use in the project.
The old lib was about a quarter of the yearly cost of the one we moved to. But the old lib was a bad choice at any price.11
what engineering roles comes after senior on a non-management path? A lot depends on the organisation. What some call ‘senior+’ as a catch-all can refer to staff engineer, lead, principal, and more. Notable books on this: The Staff Engineer’s Path, Staff Engineer: Leadership beyond the management track ↩︎
thoughts are cheap. Justified, reasoned-out thoughts are rarer ↩︎
imagine being given this sought-after responsibility, and then not having enough ideas and research under your belt. You might become one of those anonymous devs others curse later on: “Why on earth did they use Llama-kit for the pet feeding API?!” ↩︎
example being the operative word here! I am not saying “just automatically use these”! ↩︎
at one time Cocoapods, then Carthage, were riding high. But if you’re using tuist, SPM is pretty compelling. If you were choosing between the other two, Carthage is definitely the better choice IMO – Cocoapods got its claws too much into projects for my liking ↩︎
true story: for a while I confused the dependency inversion principle (the D in SOLID) with dependency injection. I’m pretty sure I got that wrong in some interviews too, but the interviewer either didn’t notice or didn’t pick me up on it ↩︎
and don’t forget the cost of honouring (or not honouring!) their license. This cost can come in many interesting forms, such as “oh we’re supposed to publish our entire app source because we’re using this lib?” and then having to switch to a different lib very quickly ↩︎
reminder: if you use an open source project in your product, have your own fork that is regularly updated just in case the original goes away ↩︎
but, to play devil’s advocate a bit: quite a few things start ‘just used in one place’ and before you know they’re all over the place :) This is one reason we like to inject dependencies ↩︎
my favourite Golden Hammer memory is from 25 years ago: a colleague had just discovered gang-of-four software design patterns. He was trying to shoe-horn as many GOF patterns as he could into any task at hand! And so one interview question I like asking candidates is not the typical “recite some design patterns”, but instead “How do you feel about the use of software design patterns?” – I’m looking for a mature view in response.12 If they actually show knowledge about a specific pattern in their answer, bonus ↩︎
I’m pretty sure I know what happened with the awful PDF lib: the company responsible had a commercial PDF reader app, and someone there had a light bulb moment: “Hey we could monetize the PDF component as a standalone lib!”. And they did that, despite it being terrible. And digital agencies, like the one who provided a broken app to my client, used that lib ↩︎
an unforgettable answer I once got to that question: “I haven’t done much Photoshop” ↩︎