Designing Auto Generated Codes

49
Designing Auto Generated Codes 17 Nov 2015 Roppongi.aar #2 @kikuchy

Transcript of Designing Auto Generated Codes

Designing Auto Generated Codes

17 Nov 2015 Roppongi.aar #2 @kikuchy

• Hiroshi Kikuchi (@kikuchy)

• Belonging to , inc , Working on , inc (mixi group)

• Making “Dating App” for Android

• Strict review OJISAN

Who am I

APT made our work reduced!!

So, you use APT, and be happy!!

\\\\٩( 'ω' )و ////

… I was going to talk about like that, but

Oh, you are already using APT.

fin.

\(^o^)/

So, I’ll talk about

Designing Auto Generated Codes

What is the best way to use Generated Code in our project?

Please consider and discuss.

The Problem Make Us Wakeful

Case 1 (/2)

If you make an awesome library hiding generated codes…

// Fields@ExecuteSomethingString foo;

// Executor class “ThisClass$$Executor” is generated.// My library loads executor class automatically!AwesomeLibrary.execute(this);

Alice changes “Naming Rule” of Generated Class.

ex) (ClassName)$$Executor -> (ClassName)$$Doer

proguard-rules.pro ????

< Hey, I obfuscated your code!

Proguard @ Production Build

Case 2 (/2)

If you make awesome “proguard-safe” library…

// Fields@ExecuteSomethingString foo;

// Executor class “ThisClassExecutor” is generated.// There are no reflection, no ClassNotFoundException!!new ThisClassExecutor().execute(this);

Bob often asks you “What’s the name of Generated Classes and methods and constructor arguments and

interfaces will use in Generated Code blablabla…”

“Why ask me repeatedly”? Why I have to remember invisible codes?

Bob

<

https://www.flickr.com/photos/greeblie/2190709020/

 / / / /    / |  /    `、 i  !  |i   i  ,  l   / / //   /   | /       | |  |  l !  i  |  | `/ー- 、 / /    | /       | l   |  l l  !  !  i / ,,,,- ニ=x- 、_   !/       |i  _, +十'イ  i  !  ! ''" / :;;r jヽ ` ̄  リ      ,, -=、 レ | / /  :|  /:::::;;;;;;;:`::::::l          / :;;r ヽヽ   |/| /   :!  |::::::::;;;;;;;;:::::::l             l:::;;;;;` ::| l  //    :!   '、:_ ''''  ノ          l  '''' ノ |  /    :| ::::::::..  ̄               ` ー '   ,'      :| ::::::::::::            ,    ..::::::::::::..l  .:|   :| ::::::::::                :::::::::::::::::::|  :|   :| Mmmm…                     ::::::::::::::: l .:|  l  :|                          /  :| :l  :|                       , '   :::| :|  :| ` 、     ⊂ニ==ー‐-     , イ    ::::| :|  :|

hiding generated codes

no reflection

vs

“Butter Knife” pattern

“Dagger2” pattern

vs

Compare patterns“Butter Knife” pattern (hiding generated codes)

“Dagger2” pattern(no reflection)

How to load generated codes Library dose everything Developers have to import

Proguard configuration is needed not needed

Developers have to learn only usage of library + generated class naming rules

Type-Safe No Yes

Which we should adopt?

case by case

My Recommend: “Dagger2” pattern

Don’t forget proguard conf?

Start ↓

Like beautiful API?

Is not solidity app necessary? → →

Yes

No↓

“Dagger2” pattern

No

Yes

↓ No↓

“Dagger2” pattern “Dagger2” pattern

“Butter Knife”

pattern

Yes

No proguard, and save the team

https://www.flickr.com/photos/katrinasagemuller/3751402009/

Appendix 1: Auto code generation patterns

• Java Annotated Source Codes

• Using APT.

• ex) Dagger2, ButterKinfe, JsonPullParser, etc…

• Externals

• Gradle Task (depends on “compileJava” task)

• ex ) R.java, genum (← I’m developing now!!!!!!!!!!!)

Source of Source Codes

Generated Class Depends on…• Only Interface

• MyOwnInterface instance = new GeneratedClass();

• ex) Dagger2, (Retrofit)

• Library Classes

• LibrarySuppliedBase instance = new GeneratedClass();

• ex) Shillelagh, etc…

• Nope || Unknown

• (Generated classes are hidden.)

• ex) ButterKnife, IntentBuilder, DeepLinkDispatch

Appendix 2: Episode

POJO ↓

Map<String, String>

https://www.flickr.com/photos/yoshimov/10256644/

public class UserSearchRequest { public EnumSet<UserKind> kind; public String freeWord; public int ageMax;

…}

@ToQueryMappublic class UserSearchRequest { @QueryParam(name = “kind”, adapter = UserKindAdapter.class) public EnumSet<UserKind> kind;

@QueryParam(name = “free_word”, adapter = StringAdapter.class) public String freeWord;

@QueryParam(name = “age_max”, adapter = IntAdapter.class) public int ageMax; …

public final class UserSearchRequestSerializer { public Map<String, String> serialize(UserSearchRequest request) {

Map<String, String> map = new Map<>(); map.put(“kind”, userKindAdapter.adapt(request.kind)); map.put(“free_word”, stringAdapter.adapt(request.freeWord)); map.put(“age_max”, intAdapter.adapt(request.ageMax)); …

return map;}

GENERATED

Yheaaaaaaaa \\\\٩( 'ω' )و ////

Thank you for listening!

Question?

@kikuchy