I want to tackle an issue which seems prevalent in the modern software engineering industry. The idea, laid down by Steve Jobs, is that “real artists ship” and everyone else is forgotten. What does it mean to be a “real artist,” and what does it mean to “ship” as one? Unfortunately, it’s become a facade, analogous to YOLO, intended to cover one’s tracks of poor engineering practices, lack of tooling, and lack of concern for the success of the product beyond delivery.
It’s not a joke
Many people do say “real artists ship” as joke, when knowingly tolerating some poor practice. The problem worth pointing out is that, while this said in jest, it’s actually masking the underlying issue in unsettling humor. It’s become affordable, in engineering social circles and development teams, to subvert good software practice in favor of reaching deadlines – and here’s the kicker – with no intention of returning to the code to refactor.
Furthermore, it’s become an attack against those who do care about software quality. In this form, it’s not a joke at all, but a claim from a high horse that shipped products are not polished products, or stable products, or secure products, but at least they’re shipped. A lunch-time conversation between two equal-ranked devs may go like this:
Sally: “Did you get tests written for the new notification system?”
Heather: “No, I needed to get it out the door.”
Sally: “Yeah, that dealine was tight. Do you plan on getting the tests written before the next sprint?”
Heather: “No, I don’t think they’re important. The code works and it’s live.”
Sally: “It is important, since it’s such a core system; we can verify all parts of it behave as expected, and protect against regressions, with tests.”
Heather: “If we do it your way, Sally, we never ship. Real artists ship.”
Like so many other aspects in this world, software practices are treated as black and white. You’re either apparently a “real artist,” who ships, or you’re someone who cares about the quality of your product and you never ship. Surely, this is absurd. Everything is gray, not black or white, and modern software engineering is neither the Kung Fu nor the Aikido nor the Wrestling; it’s the mixed martial arts, pulling the most practical pieces from as many sources as possible.
Having software tests typically means one thing, specifically: you care, or are required to care, about software quality. Do companies with automated tests actually ship code? Let’s take a look at the big four.
Ok, let’s try smaller companies.
What about some of the big open source projects?
My experience is primarily in game development, where software testing is apparently far less common. Imperative programming exacerbates this problem, since impure functions are harder to test, but games, and especially game engines, are just as testable as anything else. Again, some examples.
Clearly, it’s entirely possible to have automated tests running continuously, alongside your typical QA. The best thing about it is, you can still ship! Even better, you can both ship and iterate more confidently. If you do have to ship without testing, in order to meet some external deadline, fine. Will you test next sprint? Will you ensure there are no regressions in functionality or performance?
No stance on this should be religious; in every aspect, we must be pragmatic. Too much testing and you may not meet your deadline. Too little of it and you may not meet many users, or you may struggle to keep them. Build a company around a foundation of untested code, continue to accrue hundreds of thousands of lines of it, and then expect stability and performance? That is not sane.
NOTE: A common argument: “But interactive applications are impossible to test!” Ok, they require a different setup, but Xamarin does it, PhantomJS does it, Android does it, iOS does it, and even Unity3D does it.
ANOTHER NOTE: Many devs seem to think that testing means writing unit tests for each function in the codebase. Fortunately, that’s far from the truth. There are a number of types of tests and a system can be reasonably well tested without a single unit test.
“Real artists” also seem to not have time to refactor old code. Write it once, get it done, and ship it. If you’re one of those devs who goes back, after cranking out a new system, and removes duplication, improves API type safety, or adds more assertions and documentation, you may not be a “real artist.” Worse, according to them, you may never ship.
Refactoring code should be thought of as code hygiene. Just as most of us shower regularly, brush our teeth, and wipe after shitting, we need to clean up our code and fight bit rot; feature work, in a short sprint, can be very dirty work! The social norm, it seems, has us hiding from those who don’t shower, but embracing those who skip on the refactoring, anointing them as “real artists.”
It also seems that “real artists” claim to know all that’s needed for shipping their products; anything new, no matter how old the teachings may be, is superfluous. However, I’d argue that there is always room for growth. We should always be striving to improve our craft. We should always be looking to modernize our practices. We can greatly benefit from reflecting on our flaws, or even having our code reviewed by the team. Yet these ideas are not of the “real artist.”
The more one observes “real artists,” the more it becomes clear that they are entirely one dimensional. They’re built to ship, regardless of parameters, and will sacrifice anything to do so. Technical debt will accrue without bound and, after years, the hope to gain a firm grasp of the product’s stability and behavior will be immaterial.
The army of “real artists” may have barricaded your workplace. If so, you’ll be met with great reluctance when trying to introduce code reviews, continuous integration, and modern safety practices. You’ll be labeled an extremist for calling out and proposing fixes for poor tooling, bit-rotten systems, and haggard practices. You may find solace in some colleagues, but only rigidity on a department level.
Consider the effect of this behavior on the product. Can you release continuously? Probably not; getting stable binaries out is a slow chug, so bugs linger. Are your users frustrated that your software crashes often? That goes without saying. Is your new-user experience poor because of your degrading performance? Can you address this without systemic changes? Is your poor developer tooling hurting the productivity of your devs and significantly increasing your iteration time? Is is troubling to on-board new devs, given the poor documentation and bus factor of your proprietary tech?
Gaming is a $100 billion market; mobile comprises a third of that. How much is your company losing because the “real artists” are so quick to ship bugs?
If you’re hunting for a job, be sure to make note of the culture around quality. When you’re interviewing, ask the interviewers about their software practices. Is there automated testing? Are there code reviews? Static analysis? Linting? What’s the test coverage? What sort of tests are there? Is there a style guide which prohibits certain dangerous practices? Are third-party libraries kept up to date to minimize security holes and duplicated patching efforts? What’s the most stale system? Is there time between feature sprints to refactor code?
A final note to “real artists”
I’d note that we all ship quick and dirty hacks; what matters is that we go back and clean them up. Every step of the way, we should be pragmatic and focused on maintaining quality software; that doesn’t need to get in the way of shipping, but it does need to be done. I’d note that repeated bastardization of software practices leads to an unmaintainable mess. I’d ask you to attempt to quantify the summation of all “real artist” moments you’ve had, where sane practice was abandoned. Was it worth it? What was the cost? Are you still paying for it?