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
23
Single-responsibility principle meets the real world!
ragunathjawahar
0
130
Making sense of large Java and Kotlin classes
ragunathjawahar
1
220
Building Robust Software, Episode 3
ragunathjawahar
1
130
Building Robust Software, Episode 2
ragunathjawahar
1
84
Building Robust Software (Episode 1)
ragunathjawahar
1
310
Speed as a workplace habit
ragunathjawahar
1
270
Building Robust Apps (Swift Edition)
ragunathjawahar
0
200
Re-architecture
ragunathjawahar
0
420
Other Decks in Programming
See All in Programming
ChatGPT とつくる PHP で OS 実装
memory1994
PRO
2
130
testcontainers のススメ
sgash708
1
130
良いユニットテストを書こう
mototakatsu
8
3.1k
Semantic Kernelのネイティブプラグインで知識拡張をしてみる
tomokusaba
0
180
「Chatwork」Android版アプリを 支える単体テストの現在
okuzawats
0
180
快速入門可觀測性
blueswen
0
410
Amazon S3 NYJavaSIG 2024-12-12
sullis
0
110
Haze - Real time background blurring
chrisbanes
1
520
ドメインイベント増えすぎ問題
h0r15h0
2
420
PHPとAPI Platformで作る本格的なWeb APIアプリケーション(入門編) / phpcon 2024 Intro to API Platform
ttskch
0
300
フロントエンドのディレクトリ構成どうしてる? Feature-Sliced Design 導入体験談
osakatechlab
8
4.1k
ブラウザ単体でmp4書き出すまで - muddy-web - 2024-12
yue4u
3
490
Featured
See All Featured
Imperfection Machines: The Place of Print at Facebook
scottboms
266
13k
How To Stay Up To Date on Web Technology
chriscoyier
789
250k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
2
290
Dealing with People You Can't Stand - Big Design 2015
cassininazir
365
25k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
48
2.2k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
1
110
Measuring & Analyzing Core Web Vitals
bluesmoon
4
170
Facilitating Awesome Meetings
lara
50
6.1k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
159
15k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
28
2.1k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
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