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 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 Slide

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

    View Slide

  4. Enum

    View Slide

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

    View Slide

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

    View Slide

  7. 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 Slide

  8. 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 Slide

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

    View Slide

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

    View Slide

  11. * 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 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 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 Slide

  14. 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 Slide

  15. 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 Slide

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

    View Slide

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

    View 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 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 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 Slide

  21. 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 Slide

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

    View Slide

  23. Event handling with enum

    View Slide

  24. 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 Slide

  25. Example - handling click event

    View 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 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 Slide

  28. 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 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 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 Slide

  31. 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 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) {}
    };
    // ...
    public static ClickEventHandler valueOf(int resId) {
    for (ClickEventHandler handler : values()) {
    if (handler.getResId() == resId) { return handler; }
    }
    return UNKNOWN;
    }
    }

    View Slide

  33. 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 Slide

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

    View Slide

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

    View Slide

  36. * 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 Slide

  37. Why don’t you use enum ?

    View Slide