Skip to content
This repository has been archived by the owner on Apr 13, 2020. It is now read-only.

Commit

Permalink
言い回し修正
Browse files Browse the repository at this point in the history
  • Loading branch information
arcage committed Mar 14, 2017
1 parent dc1f020 commit 6862374
Showing 1 changed file with 23 additions and 21 deletions.
44 changes: 23 additions & 21 deletions arcage/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ Author: ʕ•ᴥ•ʔAKJ / @arcage

# ShardsとShard

RubyにGemsがあるように、Crystalにも[Shards](https://github.com/crystal-lang/shards)というパッケージ管理の仕組みが用意されています。以前はShards単体をCrystal本体とは別にインストールしなければならない時期もありましたが、Crystal v0.8.0からコンパイラ標準のライブラリ依存関係の管理ツールとして採用されたこともあり、最近では(少なくともmacOS用のhomebrewやLinux向けに公式で用意しているパッケージからインストールされた場合には)Crystal本体をインストールすればShardsもセットで利用できるようになっています。
RubyにGemsがあるように、Crystalにも[Shards](https://github.com/crystal-lang/shards)(シャーズ)というパッケージ管理の仕組みが用意されています。以前はShards単体をCrystal本体とは別にインストールしなければならない時期もありましたが、Crystal v0.8.0からコンパイラ標準のライブラリ依存関係の管理ツールとして採用されたこともあり、最近では(少なくともmacOS用のhomebrewやLinux向けに公式で用意しているパッケージからインストールされた場合には)Crystal本体をインストールすればShardsもセットで利用できるようになっています。

ShardsもGemsと同様に、言語本体に標準添付されていないライブラリをインターネットなどから取得して使えるようにしてくれます。このときGemsによってインストールされる個々のライブラリがGemと呼ばれるように、Shardsによってインストールされる個々のライブラリをCrystalではShardと呼びます。ただし、CrystalにおけるShardsの役割は、Rubyに対するGemsのそれと完全に同一ではありません。例えば、Gemsが基本的にRubyインタプリタのグローバルな環境にGemをインストールするのに対して、Shardは個々のプロジェクトフォルダ内にShardをインストールします。インストールするShard特定のバージョンに限定したり、開発環境にだけインストールして本番環境にはインストールしないShardを指定することもできます。そうした点では、ShardsはRubyにおけるGems+Bundlerに相当する機能を担っていると言って良いかもしれません(注:Shards本体にはShardの検索機能は実装されていませんが、[CrystalShards](http://crystalshards.xyz)や[Awesome Crystal](https://github.com/veelenga/awesome-crystal)といったサイトで便利なShardを探すことができます。)。
ShardsもGemsと同様に、言語本体に標準添付されていないライブラリをインターネットなどから取得して使えるようにしてくれます。このときGemsによってインストールされる個々のライブラリがGemと呼ばれるように、Shardsによってインストールされる個々のライブラリをCrystalではShard(シャード)(注:「Shard」は「石や陶器などの破片/かけら」といった意味。)と呼びます。ただし、CrystalにおけるShardsの役割は、Rubyに対するGemsのそれと完全に同一ではありません。例えば、Gemsが基本的にRubyインタプリタのグローバルな環境にGemをインストールするのに対して、Shardは個々のプロジェクトフォルダ内にShardをインストールします。インストールするShard特定のバージョンに限定したり、開発環境にだけインストールして本番環境にはインストールしないShardを指定することもできます。そうした点では、ShardsはRubyにおけるGems+Bundlerに相当する機能を担っていると言って良いかもしれません(注:Shards本体にはShardの検索機能は実装されていませんが、Shardを検索できる[CrystalShards](http://crystalshards.xyz)や、有用なShardへのリンクを集めた[Awesome Crystal](https://github.com/veelenga/awesome-crystal)といったサイトが利用可能です。)。

## なぜShardを公開するの?

Expand Down Expand Up @@ -55,7 +55,7 @@ ShardsもGemsと同様に、言語本体に標準添付されていないライ

ちなみに、同コーディングスタイルでは、型名(クラス名、モジュール名、構造体名)として複数の単語を先頭文字のみ大文字にしてそのまま連結したキャメルケース(アッパーキャメルケース)を使用することが推奨されています(注:`HTTP`のような略語は全て大文字を使用する。)。次項で紹介するプロジェクト雛形の自動生成では、指定されたプロジェクト名がShard名であると想定して、プロジェクト名をキャメルケースへ変換した名前でモジュール等が定義されます。この点からもShard名はスネークケースで付けておくと便利です。

さて、ここでは「相手の名前を与えると簡単な挨拶文を返す」だけの`Greeting`モジュールを提供する`greeting` Shardを作ってみることにしましょう。以降はプロジェクト名(Shard名)として`greeting`が指定されたものとして説明しますので、自身のライブラリを作る際は`greeting``Greeting`といった単語を適当に読み替えてください。
さて、ここでは「相手の名前を与えると簡単な挨拶文を返す」だけの機能を持った`Greeting`モジュールを提供するShard `greeting`を作ってみることにしましょう。以降はプロジェクト名(Shard名)として`greeting`が指定されたものとして説明しますので、自身のライブラリを作る際は`greeting``Greeting`といった単語を適当に読み替えてください。

## ライブラリの雛形を作る

Expand All @@ -77,23 +77,21 @@ Crystalのソースコードをコンパイルするのに使用する`crystal`
$ cd greeting
(greeting)$

なお、以降に登場する操作やファイルパスは、ここで作成されたプロジェクトディレクトリ`greeting`の直下にいること想定して記述していきます
なお、以降に登場する操作やファイルパスは、ここで作成されたプロジェクトディレクトリ`greeting`の直下にいることを想定して説明していきます

## ライブラリの機能を実装する

何はともあれ、まずはライブラリ本体の機能を実装しなければいけませんが、最近ではテスト駆動開発(test-driven development; TDD)や振舞駆動開発(behavior driven development; BDD)が流行りのようです。プロジェクトの雛形に予めspecファイルが含まれていたり、specファイルを基にしたテスト実行機能がコンパイラに標準で用意されていたり`crystal spec`コマンド)するところからして、Crystalの流儀としてはこうした開発方式が推奨されているようにも思えます。
何はともあれ、まずはライブラリ本体の機能を実装しなければいけませんが、最近ではテスト駆動開発(test-driven development; TDD)や振舞駆動開発(behavior driven development; BDD)が流行りのようです。プロジェクトの雛形に予めユニットテスト用の雛形が含まれていたり、ユニットテスト実行機能`crystal spec`コマンド)がコンパイラに標準で用意されていたりするところからして、Crystalの流儀としてはこうした開発方式が推奨されているようにも思えます。

この文書を書いている人間自身、Crystalに触れるまであまりちゃんとテストを意識したことがなかったりしますが、ここではひとまずその流れに沿って`Greeting`モジュールの実装をしてみましょう。

### テスト用のspecファイルを書く
### ユニットテスト用のテストケースを書く

BDDでは、まず実装しようとするライブラリが外部に公開するインタフェース(パブリックなメソッドの引数、返り値など)をspecファイル内に定義してから、specファイルを元にしたテストが通るようにソースコードを記述する、という流れで開発を行います
ユニットテストの基本的な考え方は、予め「このメソッドがこういう呼び出され方をしたら、出力はこうなるはず」という条件(テストケース)を列記しておき、実装されたコードが実際にそのような動きをするかを逐一チェックするイメージです

基本的な考え方としては、「このメソッドがこういう呼び出され方をしたら、こうなるはず」という条件(テストケース)を列記しておけば、実装されたコードが実際にそのような動きをするかを逐一チェックしてくれるイメージです。いわゆる「printf()デバッグ(注:ソースコード中に変数や関数の結果を出力するデバッグコードを記述する方法)」をソースコードとは切り離して自動で行うための仕組み、といった感じでしょうか
BDDでは、まず実装しようとするライブラリが外部に公開するインタフェース(パブリックなメソッドの引数、返り値など)の入出力条件をテストケースとして定義してから、そのテストケースを使用したユニットテストが通るようにソースコードを記述する、という流れで開発を行います。ですので、最初にすべきはテストケースの記述、ということになります

ですので、最初にすべきはテストケースの記述、ということになります。

ちなみに、`Greeting`モジュール用のテストを記述するspecファイルは、`spec/greeting_spec.cr`ですが、雛形生成時のこのファイルの内容は以下の通りです。
先ほど`greeting`用のプロジェクトを生成時に用意された`spec/greeting_spec.cr`には以下のようなテストケースが記述されていました。

(注:spec/greeting_spec.cr(雛形生成時))
require "./spec_helper"
Expand All @@ -102,11 +100,15 @@ BDDでは、まず実装しようとするライブラリが外部に公開す
# TODO: Write tests

it "works" do
false.should eq(true)
false.should eq(true) (注:「`fales`は`true`と等しい」)
end
end

ここで定義されているテストケースは「`fales``true` と等しい」というもので、当然ながらこのspecファイル元にしたテストは必ず失敗します。まずは、`Greeting.hello("John")``"Hello, John!"`を返す、というテストケースを書いてみましょう。
ただし、ここで定義されているテストケースは「`fales``true`と等しい」というものなので、当然ながらこの状態でユニットテスト(`crystal spec`コマンド)を実行しても必ず失敗します。ですので、まずは`spec/greeting_spec.cr`内に必要なテストケースを記述してみましょう。

テストケースの書き方についてはあまりまとまったドキュメントがないのが実態ですが、ユニットテスト実行時には全てのオブジェクトに`#should``#should_not`メソッドがインクルードされており、[`Spec::Expectations`モジュールのインスタンスメソッド](https://crystal-lang.org/api/Spec/Expectations.html)を引数として与えると、与えられた条件にしたがって結果のチェックが行われるようなイメージです。

で、「`Greeting.hello("John")``"Hello, John!"`を返す」というだけのテストケースはこんな感じ(注:この時点ではまだライブラリ本体に`Greeting.hello`が実装されていないため、ユニットテストを実行しても「そんなメソッドは無ぇ!!」と怒られます。)。

(注:spec/greeting_spec.cr(テスト内容記述後))
require "./spec_helper"
Expand All @@ -119,11 +121,11 @@ BDDでは、まず実装しようとするライブラリが外部に公開す
end
end

なお、この時点ではまだライブラリ本体に`Greeting.hello`自体が実装されていませんので、`crystal spec`を実行しても「そんなメソッドは無ぇ!!」と怒られてしまいます。必要なテストケースが書けたら、次はライブラリ本体の実装です。
必要なテストケースが書けたら、次はライブラリ本体の実装です。

### ライブラリ本体のコードを書く

ライブラリの本体機能は`src/`ディレクトリ以下に記述します。`greeting`シャードを利用する際に最初に読み込まれる`src/greeting.cr`はプロジェクト雛形の生成時に用意されています。
ライブラリの本体機能は`src/`ディレクトリ以下に記述します。`greeting`を利用する際に最初に読み込まれるソースコード`src/greeting.cr`はプロジェクト雛形の生成時に用意されています。

(注:src/greeting.cr(雛形生成時))
require "./greeting/*"
Expand Down Expand Up @@ -199,7 +201,7 @@ BDDでは、まず実装しようとするライブラリが外部に公開す
(greeting)$


こうして、全ての(といっても1つだけですが)テストケースを通過できたことで、`greeting` Shardが当初の設計通りに実装されていることを確認できました
こうして、全ての(といっても1つだけですが)テストケースを通過できたことで、`greeting`が当初の設計通りに実装されていることを確認できました

## Shardとしての体裁を整える

Expand Down Expand Up @@ -291,9 +293,9 @@ GitHubにリポジトリが公開されれば、Shardとして利用するため

# Shardの使い方

さて、`greeting` Shardは無事に公開されました
さて、`greeting`は無事に公開されました

では次に、簡単なコマンドラインアプリケーションを例に、他のプロジェクトから`greeting` Shardを使用する手順をみてみましょう
では次に、簡単なコマンドラインアプリケーションを例に、他のプロジェクトから`greeting`を使用する手順をみてみましょう

ここでは、標準入力から1行に付き1つずつ受け取る名前に対して標準出力へ挨拶文を出力する`hello`コマンドを作ってみます。

Expand All @@ -305,9 +307,9 @@ GitHubにリポジトリが公開されれば、Shardとして利用するため

## `shard.yml`に使いたいShardの記述を追加

`hello`プロジェクトで`greeting` Shardを使用することを明示するためには、`greeting` ShardのREADMEで指示されている以下の内容を`hello`プロジェクト側の`shard.yml`に追加する必要があります。
`hello`プロジェクトで`greeting` Shardを使用することを明示するためには、`greeting`のREADMEで指示されている以下の内容を`hello`プロジェクト側の`shard.yml`に追加する必要があります。

(注:greeting Shardを使うための記述)
(注:greetingを使うための記述)
dependencies:
greeting:
github: arcage/greeting
Expand Down Expand Up @@ -415,7 +417,7 @@ Shardのバージョンを表す情報として、プロジェクトファイル

Shard側がバージョンタグをつけてくれていれば、使用する側のプロジェクトで特定のバージョンを指定してインストールすることができます。

(注:greeting Shardのv0.1.0を使うための記述)
(注:greeting v0.1.0を使うための記述)
dependencies:
greeting:
github: arcage/greeting
Expand Down

0 comments on commit 6862374

Please sign in to comment.