Hacker News new | comments | show | ask | jobs | submit login
Harnessing Code Generation to Increase Reliability and Productivity on iOS at Uber (uber.com)
14 points by chmaynard 10 months ago | hide | past | web | favorite | 10 comments

It's good that they at least recognize that code-generation is a crock.

"If you are using code generation to solve a problem that might be better solved by making your code more generic, code generation will probably have a degradative effect on the health and maintainability of your codebase."

Basically, if you have to resort to code generation:

1) Abandon all hope, ye who enter here[1]

2) The abstraction mechanisms available to you are deficient.

[1] http://www.cs.cmu.edu/afs/cs.cmu.edu/project/able/www/paper_...

I don’t think it’s that clear-cut. Most abstractions come with a runtime cost. Code generation is a buildtime tool that can be deployed judiciously, and with modern version control it’s much easier to understand which sections of the codebase are dependent on compiled models elsewhere.

Ultimately it’s a cycle. Runtime abstractions tend to pile up until they hinder performance and debugging, and then code generation becomes interesting. Over time those patterns become incorporated into languages, at which point code generation seems pointless again (think Qt’s code generation tools in 1996 vs. C++14). And when the language has new interesting features, it seems to translate into people creating runtime abstractions, thus setting off another iteration of the cycle.

They're recognizing for the first case that if you have to resort to it you're trying to cover for some sort of deficiency in the language. Which is good.

I think the kind of thing they're doing would be possible without code generation in a good dynamically typed language or a language with a feature like F#'s type providers, but maybe swift doesn't allow it.

The second use case (generating test mocks) is a pretty bad reason to use code generation IMHO. Instead they should be generating non-turing complete code representing the mock (JSON or something).

Indeed, and I think people are missing a lot of nuance here.

Code generation to avoid parametricity is (AFAICT) unequivocally a bad thing. Parametricity in code is almost always a good thing because it constrains what any implementation can do -- and thus gives you guarantees (subject to compiler correctness).

Code generation to avoid boilerplate in a sane way? IMO it's actually a pretty low-tech and simple way to avoid huge amounts of repetetive work, especially if you're targeting multiple platforms in different languages. Obviously, there's LISP-like macros and maybe pseudo-dependent types in Haskell (Servant) which may buck the trend[1], but I, for one, actually appreciate the simplicity of a bit of actually generated "on disk" code when it's appropriate.

IME code generation really shines when you're approaching the business domain, i.e. closer to the "edges" of your program/service. This is where "generic" solutions tend to not work as well just by virtue of every business case being slightly different. For logic that works on top of core data structures like vector-of-X or vector-of-Y? Hell no! You're writing lots of code that 'talks to' vector-of-$ all the time and you'd be crazy to want to have to duplicate all of that.

[1] Servant actually seems to be a sort of "define the types" and generate code for all the platforms, so that may actually be an example of my "sane" way. Whatever. LISP-like macros obviously kind of avoid the point entirely because they're never "materialized" as source. Just wanted to bring them up because they tend to be brought up in these discussions, regardless.

The mock is called by Swift code in test cases (that's the point of a mock) so how would generating some JSON help?

Actually I'm now starting to think that the idea I had in mind (generate the mocks on the fly using JSON data) might not be possible.

Code generation aka compilation. Everyone generates code all the time. And all abstractions leak eventually.

> iOS does not have an equivalent to Android’s R class

I use R.Swift in every project for a while already. My template Podfile has it as well as a linter.

The mock generation tools look neat. Swift is a complicated language to write tests in as it stands now and using Objective-C limits the things you can do in swift.

If you are not Uber and do not suffer from NIHS there are https://github.com/mac-cain13/R.swift and https://github.com/SwiftGen/SwiftGen

They mention at the end of the article that SwiftGen did not exist at the time they made their own tooling.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact