お茶漬けびより

"あなたに教わったことを、噛んでいるのですよ" 五等分の花嫁 7巻 「最後の試験が五月の場合」より

Magic Keyboard の Eject ボタンを Karabiner を使って、フルスクリーンショートカットに割り当てる

f:id:pickles-ochazuke:20190112163941j:plain

Mac mini を買いました。初めての MacOS です。スペックは i5 でメモリ16GBです。 デフォルトで CUI の文字がキレイなのはかなりいいですね。まだ慣れていませんが徐々に使いこなせるようになりたいです。

Mac 用にキーボードは、MagicKeyboard を買いました。カーソルキーが右下にあって使いづらいですが、Karabiner というアプリを使ってちょっといじっています。 Magic Keyboard には右上に Eject ボタンがあるのですが、こいつはドライブを開くボタンです。いらない……。ショートカットでスリープしたりできるみたいですが、そんな頻繁にスリープしないのでやっぱりいらない。 なので、自分としてはよく使うフルスクーンのショートカットに割り当てることにしました。

~/.config/karabiner/karabiner.json を開いて、以下を追加。 追加場所は、rules の中。

"rules": [
{
  "description": "eject をフルスクリーンショートカットに変更",
  "manipulators": [
    {
      "type": "basic",
      "from": {
        "consumer_key_code": "eject"
      },
      "to": [
        {
          "key_code": "f",
          "modifiers": [
            "command",
            "control"
          ]
        }
      ]
    }
  ]
}
]

味噌は from のとこの key_code ではなく、consumer_key_code にしているところです。

超簡易な xUnit を Kotlin 入門しながら書く

f:id:pickles-ochazuke:20181202154024j:plain

Pixel 3 で写真撮るの楽しいです。久々の更新です(毎回言ってる気がする)。
Kotlin Advent Calendar 2018 5日目の記事です。

qiita.com

テスト駆動開発の本に書かれているプログラムを Kotlin で書いてみました。自分は Kotlin を触って日が浅いのですが、入門本を一冊読んでみたので何か書いてみようかと思ったのと、最近 「テスト駆動開発」という本を読んだので試しに xUnit 書いてみるかと。

クラスは、TestCaseTest, TestCase, WasRun, TestResult, TestSuite を作り、関数として getAttr 関数を作りました(機能的には getMethod という感じですが)。

Python では、オブジェクトの変数やメソッドを取り出す getAttr 関数があるのですが、Kotlin にはなさそうだったので、メソッドを取り出す関数を作りました。といってもただ Java のリフレクションを使っただけですが。以下のような感じです。

import java.lang.reflect.Method

fun getAttr(obj: Any, method_name: String): Method {
  return obj.javaClass.getMethod(method_name)
}

メソッドや関数の宣言の仕方はあとで書いてあるので飛ばしますが、上記のようにインポートすれば、Java のライブラリを使うことが出来ます。もっと上手いやり方がある気がするのですが本題じゃないので今回は上記のようにしました。

まず、基本クラスになる TestCase ですが、以下のようになります。

open class TestCase(var name: String) {
  open fun setUp() {
  }
  open fun tearDown() {
  }
  
  fun run(result: TestResult) {
    result.testStarted()
    setUp()
    try {
      val method = getAttr(this, this.name)
      method.invoke(this)
    }
    catch(e: Exception) {
      result.testFailed()
    }
    tearDown()
  } 
}

open class ですが、Kotlin はデフォルトで継承が禁止されています。なので、継承させるために open を指定あげます。class は察しの通りクラスの定義を意味します。

次の TestCase(var name: String) は、TestCase がクラスの名前で、括弧内はクラスの持つ変数の宣言とプライマリコンストラクタの仮引数を表します。このように書くことで引数の値が宣言されている変数内に格納されます。ちなみに name は、テストしたいメソッド名を持ちます。

理解しやすいように書くと以下と同じ意味になります。

// open class TestCase constructor(name: String) でも同じ意味
open class TestCase(name: String) {
  var name: String

  init {
    this.name = name
  }
}

これでコンストラクタと変数の初期化の仕方が分かりました。次は、メソッドです。 open fun setUp(), open fun tearDown() ですが、open でオーバーライドを許可しているメソッドになります。

fun run() メソッドですが、仮引数の TestResultクラスは、テスト結果をカウントするクラスです。 run メソッドは、テストを実行するメソッドです。初めにテストの回数を増やし、テスト前に必要な初期化処理を行います(実際は継承先でオーバーライドされている処理が走ります)。その後、例外処理の try ブロック内でメソッドを実行します。失敗したときにプログラムが終了しないように catch 内で テストが失敗したことをカウントします。

Kotlin のアクセス修飾子ですが、デフォルトでは public です。Java とは異なるので要注意です。

こちらが参考になると思います。 qiita.com

次に WasRun クラスを見ていきます。

class WasRun(name: String): TestCase(name) {
  var log: String

  init {
    log = ""
  }

  override fun setUp(): Unit {
    log = "setUp"
  }
  fun testMethod(): Unit {
    log = "${log} testMethod"
  }
  override fun tearDown() {
    log = "${log} tearDown"
  }
  fun testBrokenMethod() {
    throw Exception()
  }
}

WasRun クラスは、テスト対象となるクラスです。ここでは、TestCase のテストを行いたいので、TestCase を継承しています。class WasRun(name: String): TestCase(name) で使われているコロン(:)は、それのあとに書かれているクラスを継承することを意味しています。そして、コンストラクタに渡す引数として、WasRunクラスの変数を渡しています。 残りのメソッドは、オーバーライドをしていたり、テストに必要なメソッドを追加しています。testBrokenMethod() 内の throw Exception() ですが、見ての通りエラーを発生させています。

また、"${log} testMethod" のように文字列テンプレートを書くことが出来ます。

最後に、TestSuite クラスを見ていきます。

class TestSuite(val tests: MutableList<TestCase> = arrayListOf<TestCase>()) {

  var result: TestResult
  
  init {
    result = TestResult()
  }

  fun add(test: TestCase) {
    tests.add(test)
  }

  fun run(result: TestResult) {
    tests.forEach{
      it.run(result)
    }
  }
}

TestSuite クラスは、テストをまとめて行うためのクラスです。class TestSuite(val tests: MutableList<TestCase> = arrayListOf<TestCase>()) は、変数 tests に引数がなければデフォルト引数として arrayListOf<TestCase>() を入れるようにしています。 Kotlin の List についてはまだ詳しくないのですが、 readOnly と mutable なリストの二種類があります。簡単に紹介すると readOnly なリストは、中身を変えることができないリストで、 mutable なリストは、中身を変えることができるリストです。ただし、readOnly は以下のように書くことで中身を変えることが出来ます。

var list = mutableListOf(10, 20, 30)
var list2: List<Int> = list
list[0] = 33

リストについては以下が参考になると思います。

qiita.com

qiita.com

TestSuite では、様々なテストを tests にまとめておきます。そして run メソッドによってリストの中身をすべて実行していきます。

fun run(result: TestResult) {
  tests.forEach{
    it.run(result)
  }
}

簡単ですが、以上で Kotlin で作った xUnit の紹介を終わります。

Kotlin を使ってみた感想

書いてて楽しい言語だなと思いましたね。セミコロン必要ないですし、デフォルトで public になっていたり、継承がコロンだけで済んだり、また、継承もデフォルトで禁止されているのは良いなと思いました。null を許容しないのもいいですね。

Kotlin は、短く書けるけど何でもかんでも短くはしないというか、書きやすいと読みやすいのバランスが良いという感じがしました。

ぜひ仕事で使ってみたいので、修得してサーバやスマフォ開発で使いたいですね。

参考

入門するために読んだ本です。これは何か言語を知っていれば短時間で Kotlin にどんな機能があるのか把握できるので、とてもよかったです(何か言語を使ったことある前提)。

速習 Kotlin: Javaより簡単!新Android開発言語を今すぐマスター 速習シリーズ

速習 Kotlin: Javaより簡単!新Android開発言語を今すぐマスター 速習シリーズ

テスト駆動開発の本です。改訂版ですが、とても翻訳のクオリティが高く、言語も今に合わせて翻訳者が書き直してくれています。しかも付録として歴史的な話も載っています。さらに値段も安いです。すごいです…。

テスト駆動開発

テスト駆動開発

以下もおすすめらしいです。

Kotlinイン・アクション

Kotlinイン・アクション

記事内のコード

github.com

おれ、今の仕事納めたら Kotlin 勉強するんだ……

NgModule について

今回は、ngModule について説明していきます。 といってもまだ理解しきれていないので、簡単な説明ですが……。

NgModule

ng コマンドでプロジェクトを作成すると、app フォルダの中に、app.module.ts というファイルが作られます。 例えば以下のような感じです。

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

この app.module.ts は、AppModule と呼ばれ、ルートモジュールとも呼ばれます。アプリの起動時は、初めにこのモジュールが読まれることになります。また、NgModule は一つだけではなく、FeatureModule を利用して、このルートモジュールの子として含めることができるようです。

アプリを起動するときに必要な情報を @NgModule に記述していきます。@NgModule を使えるようにするには、import { NgModule } from '@angular/core' を記述する必要があります。

@NgModule 内には、メタデータを定義していきます。

  • declaratons は、アプリに必要なコンポーネント、ディレクティブ、パイプを登録します。ng generate [component | directive | pipe] で作成した場合、自動で追加されます。
  • imports は、使いたい他のモジュールをインポートします(よく利用するものはこちらです)。
  • providers は、シングルトンにしたいサービスを登録します。
  • bootstrap は、アプリのルートとなるコンポーネントを登録します。

Angular は、JavaScriptimport と Angular の imports を使って、一部のモジュールを扱えるようにしています。最初は紛らわしいのですが、使っているうちに慣れていきます(それでいいのか……)。

モジュールのイントロダクション

簡単になりましたが今回はこのへんで。公式のドキュメントは充実してるので、一度目を通すことをオススメします。

NgModule

Angular を始める

comic-girls.com

アニメのこみっくがーるずが好きです。

仕事で Angular を使っていて、その仕事が一息ついたので学んだことをまとめていこうと思います。 Angualr の簡単な紹介は公式に任せます。

一つだけ補足しておくと、過去にAngularJS というものがありました。バージョン的には 1 扱いですが、2 以降との後方互換性はありません。AngularJS については、知る必要がありません。また、Angular(2 以上) について調べるとき、AngularJS の記事がよく引っかかります。参考にならないので、-angularjs を検索ワードにつけることをオススメします。

環境

  • Windows 10
  • Node.js 10.8.0
  • npm 6.2.0
  • Angular CLI 6.2.3
  • TypeScript 2.9.2

ここですること

  • Node.js のインストール
  • Angular プロジェクトの作成
  • 簡単なコンポーネントの構成紹介

Node.js のインストール

Angular を使うためには、Node.js を入れないといけません。 Node.js は、こちらからダウンロードしてください。 推奨版と最新版どちらでも好きなほうをダウンロードしてください。

Node.js のインストール方法は特に設定を変更することはないので、省略します。

Angular プロジェクトの作成

作成する前に、Angular をインストールする必要があります。 まずは、ちゃんと Node.js がインストールされているか確認しましょう。

> npm -v
6.2.0
> node -v
v10.8.0

次に、Angular CLI をインストールします(プロキシ環境下だとうまくいかないかもしれません。プロキシの設定をしてください)。

> npm install -g @angular/cli

インストールが完了したら、バージョンを確認して、ちゃんと入っているか確認します。

> ng -v

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/


Angular CLI: 6.2.3
Node: 10.8.0
OS: win32 x64
Angular:
...

Package                      Version
------------------------------------------------------
@angular-devkit/architect    0.8.3
@angular-devkit/core         0.8.3
@angular-devkit/schematics   0.8.3
@schematics/angular          0.8.3
@schematics/update           0.8.3
rxjs                         6.2.2
typescript                   2.9.2

以上のような感じで表示されると思います。 では、プロジェクトを作成するので、作成したい場所に移動してから下記のコマンドを入力してください。

ng new my-app

実行が完了すると、プロジェクト(my-app)が作成されます。 my-app > src > app この下に必要なソースや html, css を作成していきます。 作業を始める前に、サーバを立ち上げて、Webブラウザで動作確認をしましょう。

> cd my-app
> ng serve
...
i  「wdm」: Compiled successfully.

最後の一行が表示されたら、Webブラウザを開き、http://localhost:4200 にアクセスします。 Welcome to my-app! という文字と Angular の画像が出たページが表示されると思います。 次に、簡単な変更をしてみましょう。

app.component.ts を開き、AppComponent クラスの title の中身を書き換えます。 自分は、以下のように書き換えました。

export class AppComponent {
+  title = 'The World';
-  title = 'my-app';
}

Webブラウザを確認しましょう。先に開いたタブを見ると文字が変わっているのが分かると思います。 何が起きたのかというと、変更を加えて保存をしたときにサーバ側が勝手に再度ビルドし、画面の更新を行ってくれます。 つまり、サーバを立ち上げ直す必要がなく、リアルタイムに動作の確認が出来ます。

簡単なコンポーネントの説明

最後に、コンポーネントを軽く紹介しておきます。 Angular は、一つのコンポーネントにつき、3 つのファイルが必要です(厳密には1つでもいけますが)。 それは、

  • TypeScript ファイル(.component.ts)
  • HTML ファイル(.component.html)
  • CSS ファイル(.component.css

の 3 つです。HTML と CSS は、TypeScript のファイルの中に直接書くことができるので、ファイルが必ず必要というわけではありませんが、現実的ではないでしょう。HTML と CSS は、Pug や SCSS のようなものも使えます(自分は書けないので使ったことがありませんが)。

.component.spec.ts は、コンポーネント単体テストのファイルです。そのコンポーネントのテストはここに書くことになります。

Angular では、ルートコンポーネントがあり、そのコンポーネントの中に別のコンポーネントを埋め込んでいくように作ります。 ルートのコンポーネントは、app.component です。例えば、hero というコンポーネントがあり、それを app コンポーネントに埋め込むとします。この場合、app コンポーネントの HTML ファイル(app.component.html)に以下を追加したい場所に記載します。

<app-hero></app-hero>

するとこの <app-hero></app-hero> の場所に hero コンポーネントの内容が追加されるようになります。 ここらへんは、話を聞くより実際に動かしたほうが理解できると思うので、Angular のチュートリアルをすることをオススメします。

Angular 日本語ドキュメンテーション

Visual Studio Code で Java 8 に対応する

全く更新してなかったけど、小さいことでも更新しようと思います。 苺ましまろ面白いです。アナ・コッポラちゃん可愛いよ。

最近、Java 8 を勉強中です。VSCode でStreamAPIを書くためにラムダ式を練習しようとしたら以下のような赤い波線が……。

f:id:pickles-ochazuke:20180731215430p:plain

ちなみに拡張機能として、Java Extension Pack を入れています。プロジェクトは、Maven で作りました。 で、先の問題を調べると以下を見つけました。

github.com

どうやらMavenによって作成される .settings/org.eclipse.jdt.core.prefs の中身が問題のようです。 自分のファイルは以下のようになっていました。

eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.processAnnotations=disabled
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.7

1.7 を 1.8 に書き換えます。

eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.processAnnotations=disabled
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8

VSCode を再起動すると、以下のように消えました。

f:id:pickles-ochazuke:20180731215527p:plain