cockscomblog?

cockscomb on hatena blog

Android Studio便利テク #3 — メソッドをグルーピングする

Javaでクラスの実装を進めていくと、あるメソッドが継承元クラスのメソッドをオーバーライドしているのか、あるいは何らかのinterfaceの実装なのか、だんだん見分けがつかなくなります。一定の規則でメソッドを並べたり様々な工夫があることと思います。


Xcodepragma mark

#pragma mark - UITableViewDelegate

iOSアプリ開発に慣れていれば、上記のような#pragma markを残しておく習慣があることでしょう。ちなみにSwiftでは以下のようになります。

// MARK: - UITableViewDelegate

region

Android Studioにはpragma markとは少し違いますが、regionというコメントの書き方があります。

    //region GoogleApiClient.ConnectionCallbacks
    @Override
    public void onConnected(Bundle bundle) {
        connectLocationService();
    }

    @Override
    public void onConnectionSuspended(int i) {
        disconnectLocationService();
    }
    //endregion

上記のように//region//endregionの間に囲まれた範囲を、任意の名前で定義することができます。この例であれば、二つのメソッドGoogleApiClient.ConnectionCallbacksインターフェースの実装であることが明白です。

f:id:cockscomb:20140813230713p:plain
Surround Withで選択範囲を囲う

f:id:cockscomb:20140813230732p:plain
//regionコメントで囲まれている

またこのregionの範囲はフォールディングできます。

f:id:cockscomb:20140813230747p:plain
region部分がフォールディングされている

ちなみに//regionの書き方はVisual Studio風ですが、NetBeans<editor-fold desc="GoogleApiClient.ConnectionCallbacks">``</editor-fold>という書き方もできます。


本質的には、クラスにメソッドが増え過ぎて迷子になるようなら、役割が広すぎるクラスになってしまっているのかもしれません。そのような場合でもコメントなどによって適切なグルーピングが行われていれば、リファクタリングの助けになるでしょう。いずれにせよ、読みやすくコードを整理することはよい習慣です。

プロの力が身につく Androidプログラミングの教科書

プロの力が身につく Androidプログラミングの教科書

Android Studio便利テク #2 — デバッグ中にbyte[]の中身の文字列を読む

Androidアプリの開発では、デバッグ中にbyte[]型のバイト列を見ることがあります。ネットワーク通信の結果やファイルから読み出したデータなど様々ですが、たいていの場合は文字列です。本記事では、Android Studiobyte[]の内容を簡単に確かめる方法を紹介します。


例えばネットワーク通信のレスポンスとして、40Xのステータスコードと共に、ボディにエラーの内容を表すバイト列が含まれているとします。そのようなとき、エラーの内容を知るために

byte[] body = response.getBody();
Log.d(TAG, new String(body));

のようなコードを事前に仕掛けておいてログを眺めるのはいかにも効率が悪いですね。このようなプリントデバッグでは、目的の情報が得られるまでに何度も実行してみないといけないかもしれません。

ブレークポイントを置いてデバッガで止めてみるのは良いアイデアです。しかしデバッガでVariablesを見てみても、表示されるのはただのbyteの配列であり、お世辞にもわかりやすいとは言えません。

f:id:cockscomb:20140805193018p:plain
デバッガでVariablesを表示するとbyte[]が見える

Expression Evaluation

デバッグ中にExpression Evaluationボタンを押すと、Javaのコードを評価できるダイアログが表示されます。

f:id:cockscomb:20140805193052p:plain
Expression Evaluationでは任意のJavaのコードを評価でき、byte[]の中身を確かめられる

String.copyValueOf(new String(message).toCharArray())

ここで上記のコードを評価すると、byte[]型の値をStringオブジェクトに変換でき、内容が表示されます。

new String(message)のようにできそうに思いますが、手元のAndroid Studio 0.8.2ではなぜかうまく表示されませんでした。

Data Type Renderers

Debuggerの設定のData Type Renderersでは、byte[]型の値を表示するのに評価されるコードを設定することができます。

String.copyValueOf(new String(this).toCharArray())

f:id:cockscomb:20140805193124p:plain
Data Type Renderersbyte[]の表示に利用するコードを設定できる

このように設定しておくことで、Variablesにいつでも内容が表示されるようになります。

f:id:cockscomb:20140805193140p:plain
Data Type Renderersが設定されているとVariablesにその評価結果が表示される

Expression Evaluationを毎回実行する必要もなくなり、たいへん便利です。


今回紹介したのはIntelliJ IDEA由来のデバッグ機能です。便利な機能を利用することで、より効率的に開発することができます。

ここでお知らせですが、筆者の勤務先である株式会社はてなが、京都でAndroidの勉強会を開催します。

「京都 Android 勉強会」を8/23(土)に京都で開催します! #kyotoandroid - Hatena Developer Blog

筆者も発表を行いますので、皆さまぜひご参加ください。懇親会でお待ちしています。

Android Studio便利テク #1 — フィールド名にプリフィックスを付ける

Androidの一般的なコーディングスタイル*1によれば、フィールド名にいくつかの規則がある。このなかにprivatestaticじゃないフィールドはmから始まること、staticなフィールド名はsから始まること、という二つの決まりがある。

Android Studioでそのように書いていると、ゲッターやセッターをGenerateしたときなどにちょっと困ったことが起きる。

    private Object mField;

    public Object getField() {
        return mField;
    }

    public void setField(Object field) {
        mField = field;
    }

本来は上記のようなメソッドが生成されてほしい。しかしデフォルトでは以下のようになる。

    private Object mField;

    public Object getmField() {
        return mField;
    }

    public void setmField(Object mField) {
        this.mField = mField;
    }

mの部分までメソッド名に入ってしまい、getmField()のようなアクセッサが生成されている。これを手でチマチマと修正してはいないだろうか。

Android Studioでは、PreferencesからCode StyleJavaを開いて、Code GenerationタブのNamingルールを変更することでこれを解決できる。

f:id:cockscomb:20140803221407p:plain
NamingルールにName prefix:を設定する

プロジェクト単位ではなくデフォルト値を変えたければFileメニューから辿るとよい。

f:id:cockscomb:20140803221353p:plain
FileメニューからOther SettingsDefault Settings…と辿る

またこれらの設定はRefactor ThisからField…を選択したときのデフォルトの名前にも適用される。

一般的に便利なので必ず設定しよう。


下記の書籍にはこれらの情報は記載されておりませんが単に役に立ちます。

EFFECTIVE JAVA 第2版 (The Java Series)

EFFECTIVE JAVA 第2版 (The Java Series)

モバイルアプリのObserverパターン

ReactiveCocoa勉強会関西にてObserverパターンについてお話ししましたので、以下にその内容をまとめます。


Observerパターンは、GoFの23のデザインパターンのうちの一つで、モデルが状態の変化をしビューに通知するパターンです。GUIアプリケーションの開発で多用されます。もちろんスマートフォンアプリの開発においても大変役に立つので、いくつかの例を挙げて見ていきます。

Objective-CのKey-Value Observing

static void * Context = &Context;


- (void)anything
{
    [object addObserver:self
             forKeyPath:NSStringFromSelector(@selector(property))
                options:NSKeyValueObservingOptionNew
                context:Context];
}


- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    if (context == Context) {
        doSomething();
    }
}

上記は監視する側の例です。NSKeyValueObservingプロトコルaddObserver:forKeyPath:options:contextを呼び出し、変化があったときobserveValueForKeyPath:ofObject:change:context:が呼ばれるというものです。NSStringFromSelector()contextを利用するのは良い習慣です。

self.property = object;
NSMutableArray *arrayProxy =
    [array mutableArrayValueForKeyPath:
        NSStringFromSelector(@selector(property))];
[proxy addObject:object];

KVOの通知を発火させるためには、Key-Value Codingに準拠するようにプロパティへの代入を行うか、あるいはコレクションのKVOを発火させるためにmutableArrayValueForKeyPath:が返すプロキシオブジェクトを利用します。

このようにObjective-Cでは、KVOという仕組みによってObserverパターンを簡単に利用できるようになっています。

AndroidJavaのObserverパターン

AndroidにおけるObserverパターンの実現ためには、素朴にObserverパターンを実装するほか、java.beansパッケージのPropertyChangeSupportクラスを利用する方法があります。

public class Bean {
    private final PropertyChangeSupport mChanges;

    private String mName;


    public Bean() {
        mChanges = new PropertyChangeSupport(this);
    }


    public void addListener(PropertyChangeListener listener) {
        mChanges.addPropertyChangeListener(listener);
    }


    public void deleteListener(PropertyChangeListener listener) {
        mChanges.removePropertyChangeListener(listener);
    }


    public String getName() { return mName; }


    public void setName(String name) {
        String oldName = mName;
        mName = name;
        mChanges.firePropertyChange("name", oldName, mName);
    }

}

PropertyChangeSupportインスタンスを保持し、PropertyChangeListenerインターフェースのオブジェクトを受け付けます。そして監視させたいフィールドの変更があったとき、firePropertyChange()を呼び出すことで、PropertyChangeListenerPropertyChangeEventが送られます。

java.beansパッケージの中で、このPropertyChangeSupport関連の機能だけがAndroidにも存在しています。KVOと似たような形で利用できるかもしれません。

またjava.util.Observableを継承するという方法もありますが、あまり使い勝手が良くないかもしれません。

Swift

Swiftについてはどうでしょうか。SwiftからもNSObjectのKVOは利用できます。しかし純粋なSwiftのオブジェクトについては、これまでのKVOは利用できません。

Appleのドキュメント“Using Swift with Cocoa and Objective-C”の“Adopting Cocoa Design Patterns”を参照すると、今日現在で

Information forthcoming.

となっています。正式なリリースまでに何か明らかになるとよいのですが。

ここからは与太話ですが、もしSwiftにKVOライクな仕組みが導入されるとしたら、Objective-Cのようなランタイムで動的に何かするのではなく、コンパイルタイムで解決できるような仕掛けになるのではないでしょうか。そのほうがSwift的で、より安全かつ最適化しやすいようにも思います。

以上となりますが、今後もライフワークとしてObserverパターンについて考えていきたいと思います。

Ghost Stories

Ghost Stories

Ghost Stories

Coldplayのアルバム出てたので買いました。

Magic

Magic

落ち着きがあっていい感じ。

A Sky Full of Stars

A Sky Full of Stars

こっちは爽快感がある。

Clocks

Clocks

  • コールドプレイ
  • Rock
  • ¥250

Viva la Vida

Viva la Vida

Charlie Brown

Charlie Brown

ずっといい感じだからおすすめです。

iOSアプリ開発における便利OSSライブラリの選定について

f:id:cockscomb:20140506123733j:plain

(Andy Myers and the CocoaPods Dev team. Creative Commons - Attribution-NonCommercial 4.0 International)

iOSアプリを作るとき、今日ではCocoaPodsを用いて簡単に便利なライブラリの力を借りることができる。

ライブラリを利用するメリットは多い。自分でメンテナンスする必要がないので、放っておいても勝手に改善されていく。潜在的な問題があったとしても、多くの人が利用しているものなら誰かが気付いて直してくれる可能性も高い。また自分より優れたエンジニアの手によって、優れたインターフェースや実装になっているということも多い。何より、自分で実装する手間が省けるのがよい。

反面、デメリットについても考えなければならない。ライブラリがメンテナンスされなくなったとき、なにか問題が起こったり、あるいはAppleの気まぐれでコンパイルが通らなくなったらどうするのか。乗り換えるコストや、あるいは自分自身でメンテナンスすることを考慮する必要がある。またライブラリのインターフェースが全く変わってしまったら、これに対応するコストも必要である。リリースサイクルとの兼ね合いもある。

iOSアプリ開発においては、iOSが毎年大きなメジャーバージョンアップを繰り返すことや、言語仕様まで含めて開発環境が変わっていくことまで考慮しなければならない。もしアプリを一度リリースしてそれっきりで良いのなら何ら心配要らないだろう。しかし継続的なアップデートを数年にわたって続けていくつもりなら、無思慮なライブラリの選択はコードベースの寿命を縮める結果になりかねない。

ここで憚りながら、筆者のライブラリ選択の指針を公開する。参考になれば幸いである。

Effective Objective-C 2.0

Effective Objective-C 2.0

続きを読む