2016년 11월 29일 화요일

Immutability

Converter utility class 에서 convert table 에 대한 immutable collection을 사용하는 게 필요한지, 필요하다면 왜 필요한지 검토해 볼까한다. 제대로 결론이 나올지 모르겠지만...

converter utility class 란?

health project에서 clean architecture(onion architecture) 를 적용하면서 각 layer 간의 data type 변환을 위해서 만들어 놓은 utility class 이다.
일반적으로 다음과 같은 형태를 가진다.

class XXXConverter {
   final Map<A, B> XXXMap = Map.create().put(a, b).put(a1, b1).put(a2, b2);

   B convert(A a) {
       return XXXMap.get(a);
   }

   A convert(B b) {
       return XXXMap.reverse().get(b); // guava bimap 사용시
   }
}

health project의 production code 에서는 Map<A, B> 대신에 Guava library 의 ImmutableMap / ImmutableBiMap 을 이용하여 코드가 작성되어 있다.

Guava ImmutableCollections

Guava library 에서 설명하는 guava 의 immutable objcet 의 장점은 아래와 같다.
(https://github.com/google/guava/wiki/ImmutableCollectionsExplained)

  • Safe for use by untrusted libraries.
  • Thread-safe: can be used by many threads with no risk of race conditions.
  • Doesn't need to support mutation, and can make time and space savings with that assumption. All immutable collection implementations are more memory-efficient than their mutable siblings (analysis)
  • Can be used as a constant, with the expectation that it will remain fixed
이에 비해서 jdk 에서 제공하는 Collections.unmodifibleXXX() 는 다음과 같은 단점이 있다고 한다.

  • unwieldy and verbose; unpleasant to use everywhere you want to make defensive copies
  • unsafe: the returned collections are only truly immutable if nobody holds a reference to the original collection
  • inefficient: the data structures still have all the overhead of mutable collections, including concurrent modification checks, extra space in hash tables, etc.

Converter에서 ImmutableCollections

다시 converter 로 돌아와서 converter 에서 ImmutableMap 을 사용하는 게 의미가 있을까?
내가 내린 결론은,
Converter 목적상으로는 사용의 의미가 없다. 해당 map 을 copy 해서 사용할 이유도 없고 외부에 open 할 이유도 없다. 단순히 Converter class 내에서 matching table 역할만 하기 때문에 동작중에 내용이 변경되지 않는다고 가정할 수 있다.(100%???) matching table 의 크기도 크지 않기 때문에 속도나 메모리의 잇점도 크지 않다. 따라서 반드시 사용할 이유는 없어 보인다. Collections.unmodifiableXXX() 만으로도 충분하다. 
게다가 Guava 사용시에 proguard 사용하지 않으면, method 갯수 limit 도 신경써야 한다.(이 부분은 guava 에서는 android에서는 proguard 사용을 당연히 가정하기 때문에 문제 안되는다고 명시되어 있다. proguard 를 잘 적용하면 문제 안되겠지...)


Immutable Object

Immutable object 를 어떻게 만드는지 설명하고 있다. Immutability 는 functional programming 에서는 가장 강조하는 개념(?)이다. multi-thread 환경에 가장 강점을 발휘한다. java 에서 immutable object 를 만들기 위해서는 아래와 같이 한다.

- 모든 member 를 final 로 지정하고,
- class 도 final 로 지정한다.
- 최소 1개의 constructor 를 제공
- no-argument constructor 는 제공하지 않는다.
- setter 를 제공하지 않는다.
- you need to make sure you defensively copy any object references you return from getXXX methods

< Immutable Address class >
public final class Address {
    private final String name;
    private final List<String> streets;
    private final String city;
    private final String state;
    private final String zip;

    public Address(String name, List<String> streets, 
                   String city, String state, String zip) {
        this.name = name;
        this.streets = streets;
        this.city = city;
        this.state = state;
        this.zip = zip;
    }

    public String getName() {
        return name;
    }

    public List<String> getStreets() {
        return Collections.unmodifiableList(streets);
    }

    public String getCity() {
        return city;
    }

    public String getState() {
        return state;
    }

    public String getZip() {
        return zip;
    }
}

장점
- Immutable classes make a host of typically worrisome things in Java go away.
- Immutable objects are also automatically thread-safe and have no synchronization issues.
- one of the best features of immutable classes is how well they fit into the composition abstraction.


from wikipedia(https://en.wikipedia.org/wiki/Immutable_object#Java)
final MyObject m = new MyObject(); //m is of reference type
m.data = 100; // OK. We can change state of object m (m is mutable and final doesn't change this fact)
m = new MyObject(); // does not compile. m is final so can't be reassigned


Google AutoValue


https://github.com/google/auto/tree/master/value


Generated immutable value classes for Java 1.6+ Kevin Bourrillion, Éamonn McManus Google, Inc.
원본 code :
https://github.com/google/auto/blob/master/value/userguide/builders.md

generated code :
https://github.com/google/auto/blob/master/value/userguide/generated-builder-example.md

최종 결론

Immutable 은 좋은 것이여!
Converter 에서도 쓰고, 모든 곳에서 사용하자. 
극단으로 사용해서 습관화하자.(??)

덧붙임.
Immutable class 를 많이 사용하면 GC 가 많이 돌수도 있다는 우려도 있다.
객관적인 자료는 없지만, 엄청나게 큰 시스템이 아니면 지금과 같은 h/w 사양에서 크게 문제가 되지는 않을 것 같다.
언어적으로는 memoization이 이런 문제에 대한 해결책 같은 걸까? 아니면 다른 개념인가...

2016년 3월 17일 목요일

[WebApp] google fit imitation 만들어 보기 - 4

개요

Google fit api 를 활용한 hybrid app 개발

목적

- web app 구조를 학습한다.
- hybrid app 의 구조를 학습
- html/javascript 기본 학습

Source :

https://github.com/tigerbalm/my-google-fit2


Component diagram

PlantUML Diagram

PNGSVGTXTEdit

 

Screen flow

screen-flow

 

HTML page structure

webapp 에서는 하나의 html 내에서 여러 page 를 처리한다.
resource loading 문제등의 이유로 하나의 html 내에서 처리하기를 권장하는 사람도 있다.
html 내에 여러 page 가 있기 때문에 html 자체가 매우 복잡해지고 가독성도 많이 떨어진다. boiler code 가 많기 때문에 html 당 하나의 page 는 효율이 떨어진다.
적절하게 html수와 page 수를 조절하는 게 필요하다.
page-structure

 

Android mock

처음 작업할때는 android studio에서 작업해서 phone 이나 emulator 에 띄워서 html/javascript test 했다. 한번 build 해서 올리고 logcat 으로 확인하고 debugging 하는 게 생각보다 시간도 걸리고 귀찮은 작업이다. 어차피 html/javascript 이니 PC 상에서 작업하고, PC browser 에서 바로 확인하는 방법을 아래와 같이 사용했다. UI 작업은 많이 편해지고, chrome/firefox 의 개발자모드에서 바로 log 등을 확인할 수 있는 장점도 있다.
<< index.html / detail.html header  >>
image


<< androidmock.js >>
image

<< index.html >>
image

javascript <-> java code call

<index.html>
PlantUML Diagram

PNG |  SVG |  TXT |  Edit

<index.html>

PlantUML Diagram

PNG |  SVG |  TXT |  Edit


JSON data

Today's total data
[
    {
    "value" : 300,
    "color" : "#F7464A"
    "highlight" : "#FF5A5E"
    "label" : "Walking"
    }, 
    {
    :
    }
]


Workout List
[
    { "date" : "3/8", "steps" : 450 },
    { "date" : "3/7", "steps" : 450 },
    { "date" : "3/6", "steps" : 450 },
    :
] 

Workout daily detail
[
    { "time": 6, "steps": 456, "calories": 62,  "distance": 0.1 },
    { "time": 7, "steps": 56, "calories": 12,  "distance": 0.01 },
    { "time": 8, "steps": 106, "calories": 30,  "distance": 0.02 },
    :
]

사용한 library

Chart.js(http://www.chartjs.org/)
Timber
RxFit(X)

결론

- javascript의 기본 문법은 쉽다. -> debugging 은 어려움
- html/javascript/css/webview framework 자체에 대한 학습 시간이 필요
- UI 부분은 재사용이 가능할 수 있을 것 같다.
- 하지만, 단순한 UI 인 경우에는 native 로 platform 별로 각각 만드는 거나 html 사용하는 거나 차이가 있을까.
- hybrid 방식으로 구현된 open source app 을 찾기 어렵다. -> 많이 사용하지 않는 방식??
- hybrid 방식이 아닌 순수한 webapp 의 경우에는 차이가 있을 수도 있으니, 순수 webapp 구조를 생각해보는 것도 방법

2016년 1월 21일 목요일

[WebApp] google fit imitation 만들어 보기 - 3

Java native 코드와 JavaScript 코드사이의 interface 가 필요하다.
java script 의 argument 는 json 으로 받을 수 있으니 native 와 script 간의 data 는 json 형식으로 한다.

https://github.com/tigerbalm/my-google-fit2

PlantUML Diagram

PNG |  SVG |  TXT |  Edit

[WebApp] google fit imitation 만들어 보기 - 2

WebInfterace 에서 data 교환
Hybrid 형태로 만들기 때문에 중요 logic 은 java native 로 작성한다.
java native 와 js 간의 interface 는 WebView 에서 제공하는 WebAppInterface를 이용해서 간단히 구현이 가능하다.
하지만, native java 와  js 간의 교환 가능한 data type 이 primitive type 이기 때문에 복잡한 data 교환에는 json 을 이용해야 한다. (http://stackoverflow.com/a/2251691)

Debugging

chrome 을 이용한 debugging
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    WebView.setWebContentsDebuggingEnabled(true);}

logcat 을 이용해서 js의 console log 확인하기
webView.setWebChromeClient(new WebChromeClient() {
    public boolean onConsoleMessage(ConsoleMessage cm) {
        Log.d("MyGoogleFit2", cm.message() + " -- From line "                + cm.lineNumber() + " of "                + cm.sourceId() );        return true;    }
});