Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Code Generation for Fun & Profit (Swift Edition)
Search
Ragunath Jawahar
April 22, 2017
Programming
1
220
Code Generation for Fun & Profit (Swift Edition)
Presented in April '17 Swift Delhi meetup.
https://www.meetup.com/Swift-Delhi/events/239248482/
Ragunath Jawahar
April 22, 2017
Tweet
Share
More Decks by Ragunath Jawahar
See All by Ragunath Jawahar
Single-responsibility principle meets the real world! (Dubai Edition)
ragunathjawahar
0
37
Single-responsibility principle meets the real world!
ragunathjawahar
0
140
Making sense of large Java and Kotlin classes
ragunathjawahar
1
250
Building Robust Software, Episode 3
ragunathjawahar
1
160
Building Robust Software, Episode 2
ragunathjawahar
1
120
Building Robust Software (Episode 1)
ragunathjawahar
1
340
Speed as a workplace habit
ragunathjawahar
1
300
Building Robust Apps (Swift Edition)
ragunathjawahar
0
230
Re-architecture
ragunathjawahar
0
460
Other Decks in Programming
See All in Programming
Porting a visionOS App to Android XR
akkeylab
0
590
AI コーディングエージェントの時代へ:JetBrains が描く開発の未来
masaruhr
1
190
AIエージェントはこう育てる - GitHub Copilot Agentとチームの共進化サイクル
koboriakira
0
600
MDN Web Docs に日本語翻訳でコントリビュートしたくなる
ohmori_yusuke
1
130
Composerが「依存解決」のためにどんな工夫をしているか #phpcon
o0h
PRO
1
270
効率的な開発手段として VRTを活用する
ishkawa
0
150
dbt民主化とLLMによる開発ブースト ~ AI Readyな分析サイクルを目指して ~
yoshyum
3
1k
オンコール⼊⾨〜ページャーが鳴る前に、あなたが備えられること〜 / Before The Pager Rings
yktakaha4
0
120
“いい感じ“な定量評価を求めて - Four Keysとアウトカムの間の探求 -
nealle
2
11k
20250628_非エンジニアがバイブコーディングしてみた
ponponmikankan
0
700
生成AI時代のコンポーネントライブラリの作り方
touyou
1
240
Azure AI Foundryではじめてのマルチエージェントワークフロー
seosoft
0
190
Featured
See All Featured
RailsConf 2023
tenderlove
30
1.1k
Code Reviewing Like a Champion
maltzj
524
40k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
53
2.9k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
46
9.6k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
331
22k
Adopting Sorbet at Scale
ufuk
77
9.5k
Art, The Web, and Tiny UX
lynnandtonic
299
21k
Building an army of robots
kneath
306
45k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
29
1.8k
Why Our Code Smells
bkeepers
PRO
336
57k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
15
1.5k
Balancing Empowerment & Direction
lara
1
430
Transcript
Code Generation for Fun & Profit (Swift Edition) Ragunath Jawahar
A mobile app developer walks into the bar…
A mobile app developer walks into the bar office…
None
Tracking Code (Swift) let properties = [ "Gender": "Female", "Logged
in": false, "Source": "Twitter" ] Mixpanel.mainInstance() .track(event: "Signup", properties: properties)
Tracking Code (Swift) let properties = [ "Gender": "Female", "Logged
in": false, "Source": "Twitter" ] Mixpanel.mainInstance() .track(event: "Signup", properties: properties)
Tracking Code (Swift) let properties = [ "Gender": "Female", "Logged
in": false, "Source": "Twitter" ] Mixpanel.mainInstance() .track(event: "Signup", properties: properties)
Tracking Code (Java) MixpanelAPI mixpanel = MixpanelAPI.getInstance(this, token); try {
JSONObject payload = new JSONObject(); payload.put("Gender", "Female"); payload.put("Logged in", false); payload.put("Source", "Twitter"); mixpanel.track("Signup", payload); } catch (JSONException exception) { Log.e("Frodo", "JsonException", exception); }
Tracking Code (Java) MixpanelAPI mixpanel = MixpanelAPI.getInstance(this, token); try {
JSONObject payload = new JSONObject(); payload.put("Gender", "Female"); payload.put("Logged in", false); payload.put("Source", "Twitter"); mixpanel.track("Signup", payload); } catch (JSONException exception) { Log.e("Frodo", "JsonException", exception); }
Tracking Code (Java) MixpanelAPI mixpanel = MixpanelAPI.getInstance(this, token); try {
JSONObject payload = new JSONObject(); payload.put("Gender", "Female"); payload.put("Logged in", false); payload.put("Source", "Twitter"); mixpanel.track("Signup", payload); } catch (JSONException exception) { Log.e("Frodo", "JsonException", exception); }
Tracking Code (Java) MixpanelAPI mixpanel = MixpanelAPI.getInstance(this, token); try {
JSONObject payload = new JSONObject(); payload.put("Gender", "Female"); payload.put("Logged in", false); payload.put("Source", "Twitter"); mixpanel.track("Signup", payload); } catch (JSONException exception) { Log.e("Frodo", "JsonException", exception); }
GREMLINS
None
None
…and only 300 more rows
MAY THE “BRUTE” FORCE BE WITH YOU
Problems •Slow •Boring •Inaccurate •Error Prone •Hard to Test •Difficult
to Change •Multiple Platforms •Multiple Apps
Requirements • Accuracy • Accommodate Changes • Don’t Leak Cognitive
Resources • Testability • Support Multiple Apps and Platforms
None
WORKFLOW – SCREEN – EVENT
workflow().screen().event()
SOLVING MYSTERY
Java Poet – Method MethodSpec mainMethod = MethodSpec.methodBuilder("main") .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.addParameter(String[].class, "args") .addStatement( "$T.out.println($S)", System.class, "Hello, World!” ).build();
Java Poet – Method MethodSpec mainMethod = MethodSpec.methodBuilder("main") .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.addParameter(String[].class, "args") .addStatement( "$T.out.println($S)", System.class, "Hello, World!” ).build();
Java Poet – Method MethodSpec mainMethod = MethodSpec.methodBuilder("main") .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.addParameter(String[].class, "args") .addStatement( "$T.out.println($S)", System.class, "Hello, World!” ).build();
Java Poet – Method MethodSpec mainMethod = MethodSpec.methodBuilder("main") .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.addParameter(String[].class, "args") .addStatement( "$T.out.println($S)", System.class, "Hello, World!” ).build();
Java Poet – Method MethodSpec mainMethod = MethodSpec.methodBuilder("main") .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.addParameter(String[].class, "args") .addStatement( "$T.out.println($S)", System.class, "Hello, World!” ).build();
Java Poet – Method MethodSpec mainMethod = MethodSpec.methodBuilder("main") .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.addParameter(String[].class, "args") .addStatement( "$T.out.println($S)", System.class, "Hello, World!” ).build();
Java Poet – Class TypeSpec greeterClass = TypeSpec.classBuilder("Greeter") .addModifiers(Modifier.PUBLIC) .addMethod(mainMethod)
.build();
Java Poet – Class TypeSpec greeterClass = TypeSpec.classBuilder("Greeter") .addModifiers(Modifier.PUBLIC) .addMethod(mainMethod)
.build();
Java Poet – Class TypeSpec greeterClass = TypeSpec.classBuilder("Greeter") .addModifiers(Modifier.PUBLIC) .addMethod(mainMethod)
.build();
Java Poet – Class TypeSpec greeterClass = TypeSpec.classBuilder("Greeter") .addModifiers(Modifier.PUBLIC) .addMethod(mainMethod)
.build();
Java Poet – Class TypeSpec greeterClass = TypeSpec.classBuilder("Greeter") .addModifiers(Modifier.PUBLIC) .addMethod(mainMethod)
.build();
Java Poet – Compilation Unit JavaFile greeterFile = JavaFile.builder("in.kitecash", greeterClass).build();
greeterFile.writeTo(System.out);
Java Poet – Compilation Unit JavaFile greeterFile = JavaFile.builder("in.kitecash", greeterClass).build();
greeterFile.writeTo(System.out);
Java Poet – Compilation Unit JavaFile greeterFile = JavaFile.builder("in.kitecash", greeterClass).build();
greeterFile.writeTo(System.out);
Java Poet – Compilation Unit JavaFile greeterFile = JavaFile.builder("in.kitecash", greeterClass).build();
greeterFile.writeTo(System.out);
Java Poet – Generated Class package in.kitecash; import java.lang.String; import
java.lang.System; public class Greeter { public static void main(String[] args) { System.out.println("Hello, World!"); } }
BLUEPRINT
Objective workflow().screen().event()
ITERATE ON PAPER
Components •CSV Parser •Source Code Generator
High-Level Design •Generated abstract Tracker class •Generated Analytics class •Generated
Workflow classes •Generated Screen inner classes
Class Diagram … more workflow classes
Class Diagram … more inner screen classes
Tracker public abstract class Tracker { public abstract void track(String
event, Map<String, String> payload); }
Tracker public abstract class Tracker { public abstract void track(String
event, Map<String, String> payload); }
Tracker public abstract class Tracker { public abstract void track(String
event, Map<String, String> payload); }
Tracker public abstract class Tracker { public abstract void track(String
event, Map<String, String> payload); }
Analytics •Instantiated by supplying a Tracker implementation •Entry-‐point to event
tracking
workflow().screen().event() •Generated as top-level classes •Encapsulates screen inner classes
workflow().screen().event() •Workflow inner classes •Encapsulates event tracking methods
workflow().screen().event() •Event tracking methods •Resides inside screen classes •May accept
parameters for collecting additional data
ACCURACY
WRITE CODE TO GENERATE CODE
WRITE CODE TO GENERATE CODE
CHANGES
CSV Removals – Red Markers
CSV Removals – Red Markers
CSV Additions – Gray Methods
CSV Additions – Gray Methods
PRODUCTIVITY
Auto-Completion
Auto-Completion
Checklist
Checklist
Checklist
Checklist
Checklist
Checklist
Checklist
TESTING
HOW? •Schemes (iOS) & Product Flavors (Android) •Dependency Injection
Trackers •Log Tracker •Mixpanel Tracker •Dialog Tracker •Verifying Tracker
iOS + Swift
DIFFICULTIES •Swift •No Transpilers •No Code Generation Libraries
J2ObjC
J2ObjC Java Objective-C Swift
J2ObjC Java Objective-C Swift
J2ObjC Java Objective-C Swift
PEACE
PEACE
abstract class(es) NOT interface(s)
J2ObjC NUANCES •Runtime Library •Adds ~10 MB
CODE GENERATION TIPS • Doesn’t have to be DRY •
Iterate through the design several times • Add “Auto-Generated” comments and documentation • Prefer abstract classes over interfaces • Extract platform-specific code and provide abstraction • Communicate with Business Intelligence team
ragunathjawahar GitHub / Twitter / Speakerdeck