Spica*

プログラミングの話。

Daggerに入門した

GDG DevFest Okayama 2019に参加した際、STAR_ZEROさんに色々Daggerに入門するときのリソースを教えてもらったので、Android Daggerに入門してみました。(やっと個人的な宿題を一段落させた気持ち…)

具体的にはCodeLabsのUsing Dagger in your Android appを教えてもらいました。yanzmさんのMaster of Daggerも教えてもらったんですけど、英語を勉強中なのと、公式のリソースだけで進めたい気持ちもあり、どれを読むかを悩んだ結果CodeLabsを選びました。 今回はそのときに学んだ内容のメモを書きます。ほぼ超訳です。主にDaggerで使用するAnnotations周りのメモとなります。

僕がDaggerを勉強したいなと思ったのは、ユニットテストをやりたかったからです。 僕は今DIを使っていないプロジェクトを触っていて「ユニットテストを書きたい」気持ちがわりとあります。しかし、どうしてもユニットテストをするために書かなければならないコードが多い、かつmockにしないといけないオブジェクトが多いために、テストが書き始めれない…となっているところです。DIを使うと、クラスをインスタンス化する時に渡す必要のあるインスタンスを必要なものだけにできるので、モックにするものを限定的にすることが可能です。そこに魅力を感じています。

Daggerについて

DaggerはDependency Injection(DI)のためのライブラリです。Androidだけでなく、Javaプロジェクトでも利用できます。 「Daggerを使用することで、コードの再利用性を高め、リファクタリングやテストを容易にします」とのこと。 「DIって何?」という箇所に関しては、Dependency injection in Androidやその他リソースを読むのがよさそうです。

基本的なAnnotations

@Inject

二種類あります。

  • コンストラクタにつける@Inject
    • Daggerが、どうやってインスタンスを作るかを知るために必要なアノテーション
    • これをクラスのコンストラクタにつけることで、@Injectをつけたコンストラクタの引数は、そのクラスの依存であることをDaggerが知ることができる
    • これはDaggerが生成できるインスタンスに限ってつけることが可能。例えばAndroidではActivity/Fragmentなどはシステムが生成する。Dagger自身が生成することはできない。Activity/Fragmentなどは、代わりにfield injectionを使用する。
class RegistrationViewModel @Inject constructor(val userManager: UserManager) {
    ...
}
  • field injectionでの@Inject
    • Androidフレームワークは、システムによってActivityやFragmentが生成される。そのため、Daggerによってインスタンスを生成できない。そのため、Field Injectionを使う。
    • 注入したいフィールド変数の宣言に@Injectをつける
      • @Inject lateinit var registrationViewModel: RegistrationViewModel のような感じ
      • この時、宣言にprivate修飾子をつけないこと
class LoginActivity: Activity() {
    @Inject lateinit var loginViewModel: LoginViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        // ① #inject(LoginActivity) で、LoginActivity内の@Injectのついたフィールド変数にDaggerによってインスタンス化された値が注入される
        (applicationContext as MyApplication).appComponent.inject(this)
        // ②この時点で、 this.loginViewModel にはインスタンスが注入されている

        super.onCreate(savedInstanceState)
    }
}

@Component

@Component
interface AppComponent {
    ...
    fun inject(activity: LoginActivity)
}
  • 上記の例であれば、依存を注入して欲しい
  • インターフェースメソッドのパラメータは、Daggerに何を注入して欲しいか伝えるためのもの
    • LoginActivityには、var loginViewModel: LoginViewModelの宣言に、@Injectをつけた。この場合、Daggerは、LoginActivityをDaggerコンポーネントであるAppComponent#inject()メソッドにLoginActivityを渡すことで、DaggerにLoginViewModelを注入して欲しい事がわかる
  • AppComponent#inject(this)をActivityで呼び出す場合、super.onCreateよりも前に書く必要がある。Fragmentの再生成時の問題を回避するため。

@Module

  • classに対して@ModuleをつけたものをDaggerモジュールと呼ぶ
  • Dagger Moduleは、Daggerがどうやってインスタンスを用意するかを、Daggerに教えるもの
    • @Provides, @Binds, @BindsInstanceを使ってインスタンスを提供する方法を定義できる
  • Dagger ModuleはDaggerがアプリケーショングラフを構成するのために、@Componentを付与しているインターフェースに対して@Component(modules = [StorageModule::class])のようにDaggerに教える必要がある
  • モジュールは、オブジェクトを提供する方法を隠す手段である

@Binds

  • インターフェースを用意する手段をDaggerに教えるためのもの
    • もっと複雑な教え方をすることも可能(CodeLabsでは触れていない)
  • 必ずabstractメソッドにする必要がある
  • 返却の型を、用意したい型とすること
@Module
abstract class StorageModule {

    // Storageクラスを要求した場合、DaggerはSharedPreferencesStorageを用意させる
    @Binds
    abstract fun provideStorage(storage: SharedPreferencesStorage): Storage
}

@Provides

@BindsInstance

スコープ

  • Daggerでは、@Injectの対象のインスタンスは、毎回Daggerによって生成される。これがデフォルトの動き。
  • しかし、毎回newするのではなく、同じインスタンスを複数の画面で使いまわしたい場合がある。この場合に使うのがスコープ。

    @Singleton

  • これをクラスに着けると、必ずアプリケーショングラフにつき一つのインスタンスとなる
@Singleton
class UserManager @Inject constructor(private val storage: Storage) {
    ...
}

@Subcomponent

所感

DaggerのDocumentationを読んでて思ったのは、「なんか便利そうだから入れてみる」みたいなノリで入れると、「DI使うのかい?使わないのかい?どっちなんだい?」って感じになって地獄を見るかもしれないので、基礎を勉強した上で(チームでの開発をしている場合はチームを説得するなりして)入れるのがよいかなって思っています。 あと、もし既存プロジェクトにDaggerを導入する場合は、まずはリファクタリングから始めなければならないかも知れません。どのようにリファクタリングするかは、Daggerの基礎を読み、ゴールとなるapplication graph(アプリで使用しているクラスの依存関係)を考え確立したうえで、導入した方がよさそうです。

Daggerは情報量が多く、ドキュメントが色んな所に散らばっている上に、古い情報も残っていたりして、かなりいろいろなところを読まないといけない状態になっています。これは学習コストをさらに引き上げている一つの要因のような気がします…。

おまけ:dagger-androidについて

DaggerをAndroidプロジェクトに導入するには、下記をbuild.gradleに入力すればOKです。

dependencies {
    ...
    implementation "com.google.dagger:dagger:2.24"
    kapt "com.google.dagger:dagger-compiler:2.24"
}

これはCodeLabsのapp/build.gradleを見ると分かります。

ただ、僕は終わってから気づいたんですが、CodeLabsの内容は、Daggerの基本のみです…。このままでもプロジェクトへの導入は可能ですが、もっと効率的にAndroidのプロジェクトでDaggerを使うには、dagger.dev/androidにある、dagger-androidやdagger-android-supportといったライブラリの使い方も覚えたほうが良いです。Android Architecture Component - GitHubBrowserSampleには、実際にこれらのライブラリを使ったサンプルがあります(基礎がわかってないとソースみてもちんぷんかんぷんです)。

dagger-androidを含めたDaggerライブラリ全体を入れるには、下記のコードをbuild.gradleに入れる必要があります。

dependencies {
    ...
    implementation "com.google.dagger:dagger:2.24"
    implementation "com.google.dagger:dagger-android:2.24"
    implementation "com.google.dagger:dagger-android-support:2.24"
    kapt "com.google.dagger:dagger-compiler:2.24"
    kapt "com.google.dagger:dagger-android-processor:2.24"
}

↑のようなdaggerの基本ライブラリからdagger-android-supportまでを含めたすべてのdependenciesの導入方法は、GitHubBrowserSampleの中身を見て調べました。公式に書いてそうなんですが、僕自身がその導入方法を書いてるところを見つけれていません。。 (CodeLabsは基本だけなのでdagger-android-supportに関する記述がないし、Dagger公式のHow do I get it?セクションは古いし…。)

Catalinaへアップグレードした

会社のPCをアップデートする前に、自分のPCをCatalinaにアップグレードしといた。

インストール

  • ダウンロードで20分程度、インストールは1時間程度だった
    • 酷使しているPCではないので、よく使っているPCとかだともっと時間かかるのかも

気になったこと

  • Catalinaインストール後、通知を許可するかどうかのNotificationが沢山表示された。
    • アプリ毎に表示されるっぽい
  • 確かにWebページとか見てるとフォントが太くなった
  • Google日本語入力の学習データが無くなったような気がする
    • 以前は普通に一番欲しい変換候補が一番上に出てきていたが、でなくなった
    • 学習機能が動いていないわけではないので、使ってたらすぐに直っていく感じ
  • Googleのバックアップと同期アプリが、「パスが見つからない」というダイアログを出してきた
    • ダイアログが出た後、ディレクトリを選択する画面が出てきた
    • ~/Google ドライブディレクトリを選択すると、通常通り使えるようになった
  • Mac付属の辞書アプリ(dictionary.app)を開くと「辞書が構成されていません」という状態になっていた
    • しかし、辞書を構成する画面を開くと、以前選択していた辞書にチェックは入っていた
  • Xcodeをインストールするために容量を開けるのが大変だった
    • ストレージ自体は23.01GB空いていたが、それでも足りないと言われた

所管

  • アップデートして少し使ってみたけど、大きな問題は起きてない
    • Steamを手動でアップデートしなければならなかったくらい。
    • あと、一つだけゲーム入れてたんだけど、32-bitのみ対応だったので動かなくなった…
      • 古いゲームなので仕方がない。おそらく今後64-bit対応されることもないだろう…
  • Xcodeは現在インストール中
    • 3-4時間くらいかかってる気がする…
    • Catalinaのアップグレードよりも時間がかかってる
  • SidecarはiPad持ってないので試してない。けどちょっとiPadが欲しくなってきた。
  • Twitter for Macはインストールした
    • バッチリ動いている
    • iOSアプリ開発者は多いので、iOSアプリが作れればmacOSアプリが少ない手順で作れる、という認識
    • 結構これはインパクトでかいのでは。

SwiftUIとMac Catalystがすげー気になる。わくわく。

ルータ変更記: Aterm WG1200HS -> Buffalo WSR-2533DHP2

経緯

  • Aterm WG1200HSを使っていた
  • 比較的新しい機器、具体的にはPixel 3や、MacBook Pro(2018) with TouchbarでWi-Fiがブチブチ切れる問題が発生していた
  • 「これはあかんなー」みたいな感じ
  • なのでルーターを買い換えた
  • ちなみにWSR-A2533DHP2 っていうのもある。型番にAがついてる。Amazonではこれが人気。
    • WSR-2533DHP2との違いは「バンドステアリングLite」という機能がついているかどうか
    • これは、Wi-Fi SSIDを一つにして、そこにつないでおくと、電波状況に応じて5GHzと2.4GHzを切り替えてくれる機能
    • この機能が切り替わるときに瞬断が発生する可能性があるのではないかと思い、買わなかった
      • 家せまいし必要なさそうっていう理由もあった
    • ちなみにこの機能がない、僕が購入したやつは、価格も3,000円ほど安い

速度

Googleのインターネット速度計測を使用。

  • Aterm WG1200HS
    • #1: download: 49.6, upload: 91.7
    • #2: download: 45.3, upload: 92.1
    • #3: download: 36.1, upload: 91.8
  • Buffalo WSR-2533DHP2
    • #1: download: 81.0, upload: 91.7
    • #2: download: 90.7, upload: 91.6
    • #3: download: 86.9, upload: 91.6

まぁ、発売時期ぜんぜん違うし、価格も倍違うので…って感じはある。

機能的な部分

  • あんまり使い倒さないので、Atermでも十分だった
  • AtermよりもBuffaloのほうが、専門用語みたいなのは少なくて印象は良かった
    • 例えばAtermプロテクション機能とだけ書かれた、Wi-Fi 2.4GHzのみの設定なんか全然なんなのかよくわからなかった
    • ヘルプついてないし
  • マニアックなところでいうとsyslog機能はBuffaloの方にだけあった
    • macのsyslog有効にして、ルータの情報とって障害追求して遊ぶのもアリ?

Hello, Flutter! (各種フレームワーク間比較)

Getting Startedの記事ではありません。各種フレームワーク間のアーキテクチャを元に良し悪しを考えた記事です。

Flutter 1.0 is out!!

Flutterがついに1.0になったようです!

とはいえ、僕はFlutterを追いかけてはいなかったので、「お前が言うな」とか言われそうですが。

僕がFlutterを気になっている理由

僕がFlutterが気になっているのは、クロスプラットフォームアプリ開発ツール、という点だけではありません。それ以上に UIの描画を自前で行う というコンセプトがあるのが僕的に重要な点になっています。(ちなみに僕はあまりTwitterを見たりしていないので、流行りには疎めです)

クロスプラットフォーム開発のフレームワークというのは、今までにもたくさんありました。僕はAndroid/iOSのネイティブアプリ開発者ですが、ionic(当時は2.0でした)やvue.jsといったフレームワークも扱ったことがあります。それゆえに、OSのデザインとしての制約に関しては無視できない部分があり、ずっと"ちゃんと"クロスプラットフォームで良いアプリを作ることのできないむず痒い気持ちを抱えています。

ionicの事例

例えばionic。ionicはCordovaを基礎としたフレームワークで、Cordova上でAngularを動作させることでクロスプラットフォーム開発を行うフレームワークです。各プラットフォームに合わせた美しいコンポーネントが用意されており、少しのHTMLを書くだけで簡単にAndroid/iOSに合わせたデザインが適用できます。そしてLive Reload機能もあるため、ソースコードを変更するとすぐに画面に結果が反映される。まさに高速に開発できるフレームワークです。

僕はこのフレームワークを採用するのを過去に渋ったことがあります。ionicが心配だったのではありません。問題は、Cordovaがベースとなっている点でした。

Cordovaはご存知でしょうか。ネイティブアプリ上にWebViewを一枚表示し、そのWebViewとネイティブアプリ(AndroidだとJava, iOSだとObjective-Cソースコードを書く部分)間の共通インターフェイスを提供することでクロスプラットフォームを実現するフレームワークです。

このアーキテクチャには、決定的に問題のある点が一点ありました。ネイティブAnroidアプリ開発者はおそらくご存知でしょう。Androidは現在フォアグラウンドにあるアプリを快適に動かすために、「アプリをバックグラウンドに移した後、端末のメモリが不足した場合、現在フォアグラウンドにあるアプリ以外のアプリのActivityやプロセスを状況に応じて殺す」という仕組みがあります。これはOSのデザインの一部であり、設定によってなんとかViewを殺さないようにする、といったことは不可能です。

ionicはCordovaの仕組みに加えてAngularをWebView上で動作させるため、大量のメモリを食います。ここで、ionicアプリからIntentで端末にプリインストールされているカメラアプリを起動してみましょう。どうなるでしょうか。カメラはご存知のように大量にメモリを食います。Nexus 5Xのようなメモリの少ない端末や、Pixel 3のように大量のCPU/メモリを使用するカメラアプリの場合は、バックグラウンドプロセスをすぐに殺しにかかるでしょう。そして元のionicアプリに戻ったときには、Angularの動くWebViewは既に殺されており、アプリは最初からになります。当然、WebView上の画面のスタックはクリアされ、それを復元する術はフレームワーク側にはありません(僕の触った時点では少なくともそうだった)。

また、Cordovaには罠が多く、プラグイン制作に関しては多くの人がStackoverflowにお世話になったことでしょう。configがわかりにくく、プラグインのアンインストールに関しては多く人が一度はハマるところと思います。gitignoreがフレームワーク的に意識されていないのも、なにか心の中にひっかかったものを感じ続ける要因です。

また、UIのタッチレスポンスが遅い問題もあります。WebViewなので仕方がないでしょう。

こういった理由より、採用を渋っていました。結局のところ採用はしたのですが、上記の問題は杞憂ではありませんでした。

React Nativeの事例

React Native at Airbnbの記事を覚えているでしょうか。もし見ていなかった場合、ぜひ確認してみて下さい。

ちなみに僕はReactは良いものと思っています。disるつもりは毛頭ありません(ついでに髪の話でもありません!)。WebサイドではReactを少し使った経験があり、とても使いやすかったことを覚えています(React Native自体は使ったことがありません)。伝えたいのはionicと同じく、仕組みの話です。

React NativeはJavaScript Coreをバンドルして動作します(iOSはそうではないようですが)。それを使うことでJavaScriptでロジックを書くことを実現しています。JavaScriptはWebの進化によって多くの便利な仕組み(AltJSやテストツールなど)があり、高速に動作するので、とても良い言語と今でも思っています。

問題はUIの作り方です。React NativeはJavaScriptを経由して書くプラットフォームに存在するViewを利用してUIを描画します。つまり、同じコードでもプラットフォーム独自のUIの制約に縛られてしまうのです。例えば見た目を変えようとしても全く一緒にするには多くのコードを書くことになり、深いことをしようとするとネイティブプラグインを導入せざるを得なくなることもあるでしょう。この問題は、Airbnbの記事にも書いてあります("共通のデザイン言語システム(DLS)"の項目や"ジェスチャー"の項目)。

この問題はどうしても完全に解決はできないでしょう。Webの開発者がネイティブアプリを作るためのフレームワークなのに、結局JavaObjective-Cを覚えなければならなくなることが発生してしまう。これはアーキテクチャの問題です。

Xamarin

Xamarinもアーキテクチャとして、React Nativeと同じ問題を抱えていると考えています。C#よりXamarinの用意したインターフェイスの仕組みを通して、ネイティブのViewを生成して操作します。使用している言語やツールの問題ではありません。

Unity

React NativeやXamarinの問題がUIと言いました。UIを独自に作成する機能を持つ、Unityだったら問題ないのでは、と考えたこともあります。2Dだけでなく3Dも表現できる。表現力ではピカイチです。

しかしこの場合標準のUIコンポーネントが用意されていない、というのが問題です。全く同じ画面をAndroid/iOSで用意してあげる(まさにゲームのような)のであれば良いかもしれません。しかし、各OSを使用しているユーザは、ゲーム以外でその挙動を期待することはおそらく無いでしょう。また、dot-per-dotの美しいUIにしたい場合、viewportの設定など考えることが増えるのではないかという懸念もあります。

Flutter

話を戻します。僕はFlutterはここまでの各種問題をほとんど解決しているのではないかと思っています。 各問題に関して列挙しながら書きます。

  • Cordovaの懸念
    • Activityの復帰の問題
      • この記事を書きながら調べてみましたが、これは解決していませんでしたGoogle製なのに、このissueがfixになっていないのは残念でした。
      • ただし問題ではないかも、と思っています。このコメントで依頼されているように、常に今の状態を永続化しておけば、問題にはならないかもしれません。この問題は、僕は真っ先に調べるつもりです。
    • プラグインについて
      • Cordovaのプラグイン管理の仕組みは対応は半ば無理やりのようなものでした。まだ確認していませんが、問題がないことを祈っています。
    • タッチの遅さ
      • こちらも確認していませんが、そんな致命的な問題を残すとは考えにくいので、心配していません。
  • React Native, Xamarinの懸念
    • FlutterにはSkiaが入っており、UIを独自に描画する仕組みになっています。最悪、Widgetsを自分で作る場合でも、複数解像度を意識だけしておけば、DartだけできれいなUIが作れることでしょう。それぞれのOS向けに何かをしなければならない、といったことは起きないと確信しています。
  • Unity
    • FlutterにはUIコンポーネントが存在しているので、最初から独自にUIを作り上げる必要はありません。Material/Cupertinoが自動で振り分けられるという認識でいます。

Flutterについても、どうしても懸念として残ってしまう問題もあります。ionic以外に共通していますが、VMを内包しているのでフレームワーク側のバグでクラッシュしてしまうことがありえます。その場合、アプリ制作者である僕らは、issueに助けを求めるしか方法がありません。自分で直すのは、多くの場合人や時間的な都合で困難でしょう。

まとめ

いろいろ書きましたが、実はほとんどアーキテクチャしか意識しておらず、コードを書いていません。なので、面倒な部分も実は多いかもしれないな、と感じているところもあります。

もっとちゃんとFlutterのDocumentationを読んだ上で、業務でのこのフレームワークの使用を慎重に判断していこうと考えています!

モカエキスプレスを購入したので調べた内容のメモ

ふと、カリタのコーヒーミルを1年以上使ったなと思い出したので、また別の抽出方法を試したくて、モカエキスプレスを買った。買ってまだ数日だけど、調べたことメモしておく

名前について

モカエキスプレスという名前は商品名のようで、ビアレッティの公式ページにmoka expressの記述がある。ただ、一般名称は少し違って、英語だと モカポットになっている。日本だと、マキネッタ(macchinetta)という名前が一般名称の様子なんだけど、ググっててもこの名前使われたり使われなかったりしてて、いまいち統一されてない感じがする。海外サイト当たってみたけど、少なくともあんまり海外でよく使われている言葉ではなさそう。一応macchinetta - Wiktionaryとか伊英辞書には coffee maker と出てくるので、通じないものではないのかも?

関係ないけど、

  • オーストラリアメルボルンには、Macchinettaというお店もある様子。
  • 最近NTTが、Webアプリを作りやすくするMacchinettaフレームワークというのを出したらしく、語源探るのさらにややこしくなってる感はある…。多分日本向けの堅牢なフレームワークなので、大きな古き良き会社向けのものっていう雰囲気。

仕組み

http://www.bialetti.com/images/mokaillustration.jpg

ビアレッティの商品ページのMore Detailsに、上記の分解画像がある。簡単に言うと、⑧バスケット(Funnel)にコーヒーを入れ、⑨タンク(Heating Vessel)に水を入れた後、組み立てて直火で加熱すると、④上部(Coffee Collector)にコーヒーが入るようになってる。日本語名は説明書のものなので、半分公式名だと思ってはいる…ものの、発売元がストリックス デザインというところになってて、そこの説明書のようなのでよく分からない。(分かりやすいけど「上部」って…。)

https://upload.wikimedia.org/wikipedia/commons/d/dd/Moka_Animation.gif

Coffee Collectorに集まる仕組み自体は、Moka pot - Wikipediaにある上記の画像がめっちゃ分かりやすいw

細かい作り方についてメモ

なんか初めて買う時に知っておくことがあったので、それに関していろいろメモしておく。個人の感想です。

購入すべきもの

僕は下記を購入した。

ビアレッティのモカエキスプレスは、1, 3, 6, 9, 12カップがある。各カップ毎のml換算は、ビアレッティの商品ページのMore Detailsにある(3カップだと200ml)。僕は夫婦で飲むので、3カップにした。結果的には正解だったと思う。

気をつけないといけないのは、モカエキスプレスは直火式なので、IHには対応していない。説明書には 使える熱源は、ガスコンロ・電気コンロ・ハロゲンヒーター とある。オール電化だと買ってからガスバーナー買う必要が出てしまうかも。

あと、アルミかステンレスかは意見が分かれる様子だけど、アルミを買った。Amazonに「アルミは健康への害がある」というレビューが上がってたけど、安全の閾値の話で賛否両論のようで、一概には危険とは言えない様子(害ある派問題ない派)。個人的には害がある、というのは気にしすぎかなと。医学的に有害と認められた例がほぼ無いのでは。

ガスコンロの場合、ガスバーナープレートはほぼ必須。モカエキスプレス意外と直径が小さくて、ガスコンロには乗らない。お湯沸かすようの所でも乗らない。僕は東彼セラミックスのガスバーナープレートを買ったけど、どれでも良いかと思ってる。

安い コーヒー豆をリストアップしている理由は、最初モカエキスプレスを買った後は、説明書によると「コーヒーを入れて捨てる」工程を3回程度繰り返さなければならないため。説明書では「慣らし作業」としか書かれていないけど、これはどうやら、容器の金属臭を防ぐためらしい(モカエキスプレス - Wikipediaより)。良いコーヒーは高いので、慣らしで良いコーヒーを使いたくないなあ、というのが本音。ただ、余っても同じ豆でドリップとの違いを試したかったのもある。

コーヒーミルは、豆の粗さを調整するために使う。モカエキスプレスでは、基本的に極細挽きを使用する様子(UCCのサイトより)。ただ、極細挽きだと目詰りする(こことかこことか、他にも。)という情報があり、やらないほうが良いのか?

作り方

www.youtube.com

  • タンクに水を入れる
    • 安全弁(Valve)の下まで入れる。モカエキスプレスのタンク自体にも線が書かれているので、どこまで入れるべきかは分かる
  • コーヒーをバスケットに入れる
    • すりきり手前が基本
    • 押さえつけないほうが良いらしい?(使い方の項目)
    • 豆は細挽き。ただ、上記動画、極細挽きにも見えるんだけどどうなん?
    • 僕はコーヒーミルで、一番締めた状態から3目盛りくらいゆるくした状態で挽いているけど、いろいろ試すつもり
  • タンクと上部の間がネジのようになっているので、しっかりと締める
    • 一度締めすぎるのもアレかなと思ってちょっと緩めにしたらコーヒー一滴漏れてきて焦った
    • パッキン(Gasket)は消耗するので、半年目処に交換、とのこと(説明書より)
  • 火を付けて、コーヒーが上部に上がってくるまで待つ
    • コーヒー上がってきたらすぐ火は止めること
    • 大体3-4分くらい。時間は調べて、タイマーかけるようにしたら良いかも
    • 火の強さは弱。火は強くないほうがおいしい気がする
    • 一度中火程度でやったら、持ちての付け根の部分が若干溶けた…。
  • 終わったらコップに入れる
    • 中細挽きで入れた時、結構下に粉が溜まることがあったが、細挽きにしたらあまりわからなくなった。理由はまだ不明。これから調べる

いろいろ調べるの楽しい。美味しい淹れ方もっと調べたいな。

(2018-03-26: 誤字脱字及び推敲)

WebGLメモ

wgld.org | WebGL |を見ながら勉強中

  • OpenGLは手前に行くほどZの値はプラスになる
  • 座標変換は三種類ある
    • モデル変換
      • 位置
      • 拡大縮小
      • 回転
    • ビュー変換
      • カメラの位置
      • カメラの向き
    • プロジェクション変換
      • ディスプレイ縦横比率
      • 視野角
  • 固定機能パイプラインはない
    • 座標変換を行ってくれる仕組みのこと
  • シェーダは座標変換を記述するための仕組み
  • シェーダは2種類
    • 頂点シェーダ
    • フラグメントシェーダ(ピクセルシェーダ)
  • 行列(Matrix)
    • 正方行列
      • "行"と"列"が同じ要素数の行列
    • 掛ける順序によって結果が変わる
  • ポリゴン
    • 三点を結んでできた三角形のこと

仕様

Firefox Quantumで、「新しいタブ」の背景に好きな画像を使う

Chromeは仕事、趣味や調べ物のときはFirefox Quantum使うようにしてるんだけど、about:homeがシンプルで寂しいので壁紙付けたかった。ので調べた。

https://github.com/Aris-t2/CustomCSSforFx

…という素晴らしいプロジェクトがあるので、これのDocumentationとサンプルを読んで書く感じ。

  • about:support を開く
  • プロファイルフォルダーの行のFinderに表示を押す
  • プロファイルフォルダの中に入る
  • そのフォルダの中に chrome というフォルダを作り、その下を下記のような階層にする
.
├── css
│   └── aboutnewtab
│       └── appearance.css
├── img
│   └── mywallpaper.jpg
└── userContent.css
  • userContent.css
@import url(./css/aboutnewtab/appearance.css);
  • appearance.css
@-moz-document url(about:newtab), url(about:home) {
    body {
        background: url('../../img/mywallpaper.jpg') center/cover no-repeat fixed !important;
    }
}

f:id:esperia:20171216234025p:plain

さみしくない!ほくほく。