Which is better, elegant untested code or ugly tested code?
We periodically pose a question to our devs on slack, then post the lightly edited conversation here.
Our first Hacky Slack question comes courtesy of Sam:
I keep thinking about this premise. If you had to choose development priorities between elegance and testing, which would you choose?
A. Elegant code that is released with minimal testing, or
B. Poorly written code that’s been tested thoroughly before release.
Gah. Both are bad, but I guess I would go with B if I absolutely had to choose
I think B pretty well sums up most of the toy industry…
(which I often found pretty frustrating)
In the past, we’ve seen what chaos can happen when folks have made an elegant but untested change…
yeah, it was an attempt in the direction of elegance…
Elegant code is also much easier to unit test though.
Testing messy code can mean a system is thoroughly tested, but the code isn’t really tested
the really annoying thing about this scenario is that “tested thoroughly” means “we have run it a bunch of times and nothing too bad has happened yet” and not “we have a well-developed test suite that we can use for future work”
I’m just thinking back to last June when I made a document for a client about how we should refactor their code to make it more elegant, two of the reasons being “it’s easier to test, and it’s harder for bugs to sneak in”
Messy code puts so much pressure on the dev engineers, since they are the only ones who really knows how the messy code works.
Yeah, that too
so, is the sweet-spot for production: decent, testable code that gets thoroughly tested? Since elegance usually takes too long for production and really gnarly code is not really testable (not to mention a nightmare to maintain).
Yes, though I’d argue a degree of elegance doesn’t have to be so time consuming.
and maybe bonus points if it it leads to it being more testable…
I think it’s important to think about the tests just as hard or harder than we think about the code. I think that’s what’s really missing in many implementations
It’s not a pure software example, but an example anyways: Skot probably spent ~4 person-months designing our Data Logger’s original hardware and firmware, then another ~6 person-months designing the test jig and test automation suite.
Don’t get me wrong, developing the testing part is way less fun, but it’s the organization’s job to prioritize that.
Bottom Line: A or B?
I would still go with ugly code that has been well wrung-out (not using the word testing here on purpose because happy-pathing stuff repeatedly isn’t really testing)
but I want to emphasize that this is definitely a “do you want me to cut off your hand or your foot” kind of question
Good code tends to be a lot easier to read and test, so it’s not an equal time effort to do either
Legibility and testability might be actually what makes it good code
Also in my experience, code that is more clear and legible is more likely to do what you intended it to do. Granted, sometimes your code can’t be super simple, but still. If it’s broken up into more simple chunks it’s more likely to do what you meant it to.
It depends on the application.
- NASA: This cannot fail, but we’ll only use it once → B
- Tesla: Maybe some things can fail, but we can OTA → somewhere between B and A
- Facebook: ship it! → A if there is time