Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Why don't you use enum ?

Why don't you use enum ?

【第20回】potatotips(iOS/Android開発Tips共有会) 発表資料 http://connpass.com/event/17624/

Masayuki Izumi

August 11, 2015
Tweet

More Decks by Masayuki Izumi

Other Decks in Technology

Transcript

  1. Why don’t you use enum ?
    Masayuki IZUMI - @izumin5210
    potatotips #20

    View full-size slide

  2. Ƅ Rekimoto Lab. at the University of Tokyo
    (2008-2015: Akashi-NCT)
    Ɠ Enginner at Wantedly, Inc.
    (2014.9-2015.2: Dmetlabel, Inc.)
    2

    View full-size slide

  3. 2
    Ruby
    JavaScript
    Android
    Design
    pry(main) > izumin.skill_ratio

    View full-size slide

  4. Enum as constants
    public class Status {
    public static final int OK = 0;
    public static final int ERROR = -1;
    }

    View full-size slide

  5. public enum Status {
    OK,
    ERROR;
    }
    public class Status {
    public static final int OK = 0;
    public static final int ERROR = -1;
    }
    Enum as constants

    View full-size slide

  6. Example - Enum as constants
    public void onSomethingAction(int status) {
    switch (status) {
    case Status.OK:
    Log.d(TAG, "status: OK");
    break;
    case Status.ERROR:
    Log.d(TAG, "status: ERROR");
    break;
    }
    }

    View full-size slide

  7. Example - Enum as constants
    public void onSomethingAction(int status) {
    switch (status) {
    case Status.OK: // => int
    Log.d(TAG, "status: OK");
    break;
    case Status.ERROR: // => int
    Log.d(TAG, "status: ERROR");
    break;
    }
    }

    View full-size slide

  8. Example - Enum as constants
    public void onSomethingAction(Status status) {
    Log.d(TAG: "status: " + status.name());
    }

    View full-size slide

  9. Example - Enum as constants
    public void onSomethingAction(Status status) {
    Log.d(TAG: "status: " + status.name());
    }
    \ enum /

    View full-size slide

  10. * type safe !
    - "int enum pattern" is fragile
    - Add/Remove a new item easliy
    * Prefixes of names are unnecessary
    - Because each enum types has its own namespace
    Enum as constants

    View full-size slide

  11. Enum that has member constants/methods
    public enum Status {
    OK("Succeed the process!"),
    ERROR("Error has occurred...");
    private final String message;
    Status(String message) {
    this.message = message;
    }
    private String getMessage() {
    return message;
    }
    }

    View full-size slide

  12. Enum that has member constants/methods
    public enum Status {
    OK("Succeed the process!"),
    ERROR("Error has occurred...");
    private final String message;
    Status(String message) {
    this.message = message;
    }
    private String getMessage() {
    return message;
    }
    }

    View full-size slide

  13. Enum that has member constants/methods
    public enum Status {
    OK("Succeed the process!"),
    ERROR("Error has occurred...");
    private final String message;
    Status(String message) {
    this.message = message;
    }
    private String getMessage() {
    return message;
    }
    }

    View full-size slide

  14. Example - Enum that has member constants/methods
    public void onSomethingAction(int status) {
    switch (status) {
    case Status.OK:
    Log.d(TAG, "Succeed the process!");
    break;
    case Status.ERROR:
    Log.d(TAG, "Error has occurred...");
    break;
    }
    }

    View full-size slide

  15. Example - Enum that has member constants/methods
    public void onSomethingAction(Status status) {
    Log.d(TAG, status.getMessage());
    }

    View full-size slide

  16. Example - Enum that has member constants/methods
    public void onSomethingAction(Status status) {
    Log.d(TAG, status.getMessage());
    }
    \ enum /

    View full-size slide

  17. Constant-specific method implementations
    public enum Status {
    OK("Succeed the process!") {
    @Override
    void log(String tag) { Log.d(tag, message); }
    },
    ERROR("Error has occurred...") {
    @Override
    void log(String tag) { Log.e(tag, message); }
    };
    // ...
    abstract void log(String tag);
    }

    View full-size slide

  18. Constant-specific method implementations
    public enum Status {
    OK("Succeed the process!") {
    @Override
    void log(String tag) { Log.d(tag, message); }
    },
    ERROR("Error has occurred...") {
    @Override
    void log(String tag) { Log.e(tag, message); }
    };
    // ...
    abstract void log(String tag);
    }

    View full-size slide

  19. Constant-specific method implementations
    public enum Status {
    OK("Succeed the process!") {
    @Override
    void log(String tag) { Log.d(tag, message); }
    },
    ERROR("Error has occurred...") {
    @Override
    void log(String tag) { Log.e(tag, message); }
    };
    // ...
    abstract void log(String tag);
    }

    View full-size slide

  20. Constant-specific method implementations
    public enum Status {
    OK("Succeed the process!") {
    @Override
    void log(String tag) { Log.d(tag, message); }
    },
    ERROR("Error has occurred...") {
    @Override
    void log(String tag) { Log.e(tag, message); }
    };
    // ...
    abstract void log(String tag);
    }

    View full-size slide

  21. * type safe !!
    * Implements comparable / serializable
    * They are immutable / singleton
    Constants / Methods

    View full-size slide

  22. Event handling with enum

    View full-size slide

  23. Example - handling click event
    public void onClick(View v) {
    swtich(v.getId()) {
    case R.id.button1:
    // do something...
    break;
    case R.id.button2:
    // do something...
    break;
    // ...
    }
    }

    View full-size slide

  24. Example - handling click event

    View full-size slide

  25. Example - handling click event
    public enum ClickEventHandler {
    BUTTON1(R.id.button1) {
    @Override public void handle(Context context) { /* ...*/ }
    },
    BUTTON2(R.id.button2) {
    @Override public void handle(Context context) { /* ...*/ }
    };
    // ...
    abstract public void handle(Context context);
    }

    View full-size slide

  26. Example - handling click event
    public enum ClickEventHandler {
    BUTTON1(R.id.button1) {
    @Override public void handle(Context context) { /* ...*/ }
    },
    BUTTON2(R.id.button2) {
    @Override public void handle(Context context) { /* ...*/ }
    };
    // ...
    abstract public void handle(Context context);
    }

    View full-size slide

  27. Example - handling click event
    public enum ClickEventHandler {
    BUTTON1(R.id.button1) {
    @Override public void handle(Context context) { /* ...*/ }
    },
    BUTTON2(R.id.button2) {
    @Override public void handle(Context context) { /* ...*/ }
    };
    // ...
    abstract public void handle(Context context);
    }

    View full-size slide

  28. Example - handling click event
    public enum ClickEventHandler {
    BUTTON1(R.id.button1) { /* ... */ },
    BUTTON2(R.id.button2) { /* ... */ };
    // ...
    public static ClickEventHandler valueOf(int resId) {
    for (ClickEventHandler handler : values()) {
    if (handler.getResId() == resId) { return handler; }
    }
    throw new IllegalArgumentException();
    }
    }

    View full-size slide

  29. Example - handling click event
    public enum ClickEventHandler {
    BUTTON1(R.id.button1) { /* ... */ },
    BUTTON2(R.id.button2) { /* ... */ };
    // ...
    public static ClickEventHandler valueOf(int resId) {
    for (ClickEventHandler handler : values()) {
    if (handler.getResId() == resId) { return handler; }
    }
    throw new IllegalArgumentException();
    }
    }

    View full-size slide

  30. Example - handling click event
    public enum ClickEventHandler {
    BUTTON1(R.id.button1) { /* ... */ },
    BUTTON2(R.id.button2) { /* ... */ };
    // ...
    public static ClickEventHandler valueOf(int resId) {
    for (ClickEventHandler handler : values()) {
    if (handler.getResId() == resId) { return handler; }
    }
    throw new IllegalArgumentException();
    }
    }

    View full-size slide

  31. Example - handling click event
    public enum ClickEventHandler {
    BUTTON1(R.id.button1) { /* ... */ },
    BUTTON2(R.id.button2) { /* ... */ },
    UNKNOWN(-1) {
    @Override public void handle(Context context) {}
    };
    // ...
    public static ClickEventHandler valueOf(int resId) {
    for (ClickEventHandler handler : values()) {
    if (handler.getResId() == resId) { return handler; }
    }
    return UNKNOWN;
    }
    }

    View full-size slide

  32. Example - handling click event
    public enum ClickEventHandler {
    BUTTON1(R.id.button1) { /* ... */ },
    BUTTON2(R.id.button2) { /* ... */ },
    UNKNOWN(-1) {
    @Override public void handle(Context context) {}
    }; // NULL Object pattern
    // ...
    public static ClickEventHandler valueOf(int resId) {
    for (ClickEventHandler handler : values()) {
    if (handler.getResId() == resId) { return handler; }
    }
    return UNKNOWN;
    }
    }

    View full-size slide

  33. Example - handling click event
    public void onClick(View v) {
    ClickEventHandler.valueOf(v.getId()).handle(this);
    }

    View full-size slide

  34. Example - handling click event
    public void onClick(View v) {
    ClickEventHandler.valueOf(v.getId()).handle(this);
    }

    View full-size slide

  35. * Delegates event handling from controller
    - We can avoid fat controller !!!!
    * Improves testability
    - Because they are referentially transparent (?)
    * Other usecases
    - BLE (BluetoothGattCharacteristic), HTTP response, etc.
    Event handling with enum

    View full-size slide

  36. Why don’t you use enum ?

    View full-size slide