bouzuya.hatenablog.com

ぼうずやのにっき

bouzuya/bbna 1.3.0 をつくった

2017-06-25bouzuya/bbna 1.3.0 をつくった。ベータ版を公開している。正式公開は今週末にする。

1.2.0 から約二ヶ月だ。この間、なんだかんだと blog に書いていたけれど、外から見える変更はなかった。良く言えばリファクタリングだし、悪く言えば無意味な変更だ。

1.3.0 の変更点は↓のとおりだ。

  • blog.bouzuya.net の URL を bbna で開けるようになった
  • 通知から bbna を開いた際に個別の記事を開けるようになった

地味だが、良い変更だ。そしてかかった期間と内容がまったく伴っていない。この機能のためのコードはほんの数行だ。

変更に意味を持たせるためにも外から見える部分を変えるように心がけたい。

2017-W25 ふりかえり

2017-W25 をふりかえる。

2017-06 の目標

  • bbna あるいは別の Android アプリに知見を活かす
  • Haskell / Rust を日常に取り込んでいく

2017-06 もあとすこし。 bbna は 1.3.0 のベータ版をリリース。 Haskell / Rust はまったくだ。

2017-W25 の目標 とその記事

目標。

記事。

ハマった点は書いていない。 The Clean Architecture や Repository なども。アーキテクチャ関連は、書き出す→いろいろ書きたくなる→途中で面倒になって書くのをやめる、というサイクルを繰り返している。

Dagger 2 について書いた。まだ Subcomponent などには触れていない。

散髪を奇数週の水曜日で習慣にしようとしている。

つくったもの

2017-06-19/2017-06-25

小さな機能追加して 1.3.0 を公開。中身をいじるばかりで公開しないのは良くない。また別で書く。

その他

忙しさが落ち着いてきた。今週は土曜日もおやすみだ。ようやくだ。

ゲーム。『ゼルダの伝説 神々のトライフォース』を進めている。今日で闇の世界の二人目まで来た。あと五人。行動範囲が広がったので、取り逃しが増えている。

インサイド・ヘッド』を観た。記事は書いていない。なんだろうな、この気持ち悪さは……。ネガティブであることをネガティブに捉える自称ポジティブな人間がぼくは大嫌いなので、カナシミをきちんと受け入れる的な大枠は良いんだけど……。なんだろうな……。ヨロコビが生理的に無理なのかな。

StackOverflow に書く件。書いてない。

2017-W26 の目標

Dagger 2 でも javax.inject の Provider<T> が使える

Dagger 2 での Provider<T> について書く。

Dagger 2 の過去の記事は↓。

Provider<T>JSR 330javax.inject に含まれている interface だ。2017-06-19 で内部的に生成されていると書いたものの共通の interface だ。

interface Provider<T> {
  T get();
}

この Provider<T> に対しての注入は T への提供がされていれば、問題なくできる。これは↓のようなことだ。

class A {
  private final B b;
  @Inject A(Provider<B> bProvider) {
    this.b = bProvider.get();
  }
}

class B {}

class XModule {
  @Provides B provideB() { return new B(); }
  // @Provides Provider<B> providerBProvider() { ... } のようなものは不要
}

/* ... Component は省略 ... */

で、この Provider<T> に何ができるかは Provider<T> のドキュメントにある。

Provides instances of T. Typically implemented by an injector. For any type T that can be injected, you can also inject Provider. Compared to injecting T directly, injecting Provider enables:

retrieving multiple instances.
lazy or optional retrieval of an instance.
breaking circular dependencies.
abstracting scope so you can look up an instance in a smaller scope from an instance in a containing scope.

For example:

class Car { @Inject Car(Provider seatProvider) { Seat driver = seatProvider.get(); Seat passenger = seatProvider.get(); ... } }

2017-06-22 で循環依存について書いた。これの回避策はいろいろあるが、 Provider<T> を使うのもひとつだ。

class A {
  private final B;
  @Inject A(B b) {
    this.b = b;
  }
}

class B {
  private final C;
  @Inject B(C c) {
    this.c = c;
  }
}

class C {
  private final A;
  @Inject C(Provider<A> aProvider) { // Provider<T>
    this.a = aProvider.get();
  }
}

話はすこし変わる。ぼくが探していたものとしては、コンストラクタに依存以外の引数がある場合の対処法だ。

不変クラスが望ましいのは説明不要だとして、不変クラスのためにはコンストラクタインジェクションが望ましい。 Java ではフィールドの final 化にはコンストラクタでの設定が不可欠だからだ。 (もちろん、フィールドを final にしなくても不変クラスは実現できるのだけど、より意図が伝わりやすいだろう) 。同時に、コンストラクタインジェクションを採用すると、コンストラクタの呼び出しが DI コンテナの管理下になるため、依存以外の引数を取るのが難しくなる。

この問題を説明すると↓のようになる。

class A {
  private final B b; // final のためにフィールドインジェクションは避けたい
  private final C c;
  A(B b, C c) { // B を @Inject したいが、 C を動的に変更したいため、できない。
    this.b = b;
    this.c = c;
  }
}

おそらく一般的な解決策はファクトリーを使って回避する方法だ。ファクトリーに依存させ、ファクトリーのメソッドに依存以外の引数を取れば良い。ファクトリーに依存させるところまでは、上記の Provider<T> がまさにそれだ。

class A {
  private final B b;
  private final C c;
  A(B b, C c) {
    this.b = b;
    this.c = c;
  }
}
class AFactory {
  private final B b;
  @Inject AFactory(B b) { // A ではなく A の Factory を Inject できるようにする
    this.b = b;
  }
  A create(C c) {
    return new A(this.b, c);
  }
}

Guice では AssistedInject というものがあるらしい。ぼくの要求どおりなので、まさにこれがほしいんだけど、 Dagger 2 にはおそらくない。ここは諦めてファクトリーを使っていくつもりだ。

ただ、ここでもせっかくなので Provider<T> を活かしていくと良い。上記の AssistedInject のドキュメントにもあるが、上記のファクトリーの例は B に直接依存させるより createget するほうが望ましい。

class AFactory {
  private final Provider<B> bProvider;
  @Inject AFactory(Provider<B> bProvider) { // B よりも Provider<B>
    this.bProvider = bProvider;
  }
  A create(C c) {
    return new A(this.bProvider.get(), c);
  }
}

細かい点ではあるが、こういうものの積み重ねが意外と大きい差になるはずだ。

Visual Studio Code で制御文字を表示する

最近いろいろなところで制御文字を入力してしまっているようだ。キーボードの設定が悪いのかもしれない。誤って入力しても気づけるように Visual Studio Code で制御文字を表示したくなった。

まずは設定を変えて制御文字を表示する。 Preferences: Open User Settings コマンドを実行して設定を書き換える。

...
"editor.renderControlCharacters": true,
...

ただ、これだけだと文字色が同じで分かりづらいので Whitespace+ という拡張を入れる。

Whitespace+ Config コマンドを実行して設定を書き換える。ぼくは↓のようなものを入れた。ほかの設定からとってきて、 patterndark のときの backgroundColor を変えただけ。

...
{
    "name": "control",
    "enabled": true,
    "pattern": "[\\cA-\\cZ]+",
    "style": {
        "borderWidth": "1px",
        "borderRadius": "2px",
        "borderStyle": "solid",
        "light": {
            "backgroundColor": "rgba(58, 70, 101, 0.3)",
            "borderColor": "rgba(58, 70, 101, 0.4)"
        },
        "dark": {
            "backgroundColor": "rgba(255, 0, 0, 0.5)",
            "borderColor": "rgba(117, 141, 203, 0.4)"
        }
    }
}
...

あとは Whitespace+ Toggle で有効にすると……。いい感じだ。

Dagger 2 の @Inject constructor / ゼルダの伝説 神々のトライフォース進捗

2017-06-19 に続いて Dagger 2 の挙動を調べている。対象に @Inject なコンストラクタがあると、 @Provides なメソッドがなくても、 Dagger 2 はそれを生成してくれるっぽい。なんとなくしっくり来てない。 @Inject はそのインスタンスが Dagger 2 の管理下にあるという解釈をすればいいのか……。参考に Dagger 2 の使用している javax.inject の API リファレンス をメモしておく。

↑から interface の場合は @Provides をつくらないといけない……のかな。 class@Inject コンストラクタを使うほうが手抜きできる……のかな。

ちなみに循環依存すると "Found a dependency cycle" というメッセージが出て、ビルドできない。循環依存は↓のようなもの。 A は B に、 B は C に、 C は A に依存している例。

class A {
  private final B;
  @Inject A(B b) {
    this.b = b;
  }
}

class B {
  private final C;
  @Inject B(C c) {
    this.c = c;
  }
}

class C {
  private final A;
  @Inject C(A a) {
    this.a = a;
  }
}

混乱していなければ、そう起きないと思うけど……。


ゼルダの伝説 神々のトライフォース』の進捗。

知恵の紋章を手に入れた。巨大ないもむしみたいのに苦戦したが何度も落下しつつも倒した。これで勇気・力・知恵のみっつの紋章を手に入れた。

マスターソードを抜きに行った。手に入れた。ようやく司祭アグニムを倒しに行ける。

またハイリア湖の東の洞窟でアイスロッドを手に入れた。昨日 (2017-06-21) は気づかなかったが、入り口の隣に穴を開けることができた。穴さえ開いたら、何事もなく手に入った。

hageya

髪を切った。直近は 2017-06-062017-06-11 に書いたとおり奇数週の水曜日で切ってみた。ハゲが大きくなっていると言われた。そうか…… bouzuya じゃなく hageya になる日も近いか……。


ゼルダの伝説 神々のトライフォース』の進捗。迷った。湖の東の洞窟へ行ってみたけど、うまく入れなかった。何か間違っているんだろうな。別の道がありそう……。諦めて山に登っている。もらった鏡をうまく使って山頂には着いた。明日はそこから。

Ruby on Rails の scope / ゼルダの伝説 神々のトライフォース進捗

Ruby on Railsscope を使う。クエリの組み立てに使える。 eager_load(:child).merge(Child.condition) な感じで、複数クラス間で組み合わせてみたけど、LEFT OUTER JOIN child ON ... ではなく WHERE に入ってしまうものだから期待した通りには動いてくれなかった。


ゼルダの伝説 神々のトライフォース』の進捗。

  • 勇気の紋章
  • 力の紋章
  • 水かき

すこしずつ進めている。明日は最後の紋章を狙えるかな。