Skip to content

Commit

Permalink
refactor(textlint): 敬体(ですます調)と常体(である調)の使い分けを厳密に (#94)
Browse files Browse the repository at this point in the history
https://github.com/azu/textlint-rule-no-mix-dearu-desumasu @ 2 でpreferオプションが導入されて、
本文は"ですます"、箇条書きは"である"で書くように設定したので、それに合わせてリファクタリング。
  • Loading branch information
azu committed May 6, 2016
1 parent b6101aa commit b5f4779
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 62 deletions.
6 changes: 5 additions & 1 deletion .textlintrc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@
"interval": 2
},
"spellcheck-tech-word": true,
"no-mix-dearu-desumasu": true,
"no-mix-dearu-desumasu": {
"preferInHeader": "",
"preferInBody": "ですます",
"preferInList": "である"
},
"prh": {
"rulePaths": [
"test/prh.yml"
Expand Down
9 changes: 8 additions & 1 deletion coverage.textlintrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
"strict": true
},
"unexpanded-acronym": true,
"no-nfd": true,
"no-doubled-conjunctive-particle-ga": true,
"no-doubled-conjunction": true,
"no-double-negative-ja": true,
"no-doubled-joshi": {
"min_interval": 1,
Expand All @@ -18,7 +21,11 @@
"interval": 3
},
"spellcheck-tech-word": true,
"no-mix-dearu-desumasu": true,
"no-mix-dearu-desumasu": {
"preferInHeader": "",
"preferInBody": "ですます",
"preferInList": "である"
},
"prh": {
"rulePaths": [
"test/prh.yml"
Expand Down
17 changes: 8 additions & 9 deletions ja/ESLint/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ console.log("Hello!");

- [JavaScript AST explorer](http://felix-kling.de/esprima_ast_explorer/#/FNrLHi8ngW "JavaScript AST explorer")

ESLintではこのASTを使って、変数が未使用であるとか[no-console.js](#no-console.js)のように
`console.log`などがコードに残ってないかなどをルールを元にチェックすることができます。
ESLintではこのASTを使って、[no-console.js](#no-console.js)のように`console.log`などがコードに残ってないかなどをルールを元にチェックすることができます。

ルールをどう書けるかという話に戻すと、`context`というオブジェクトはただのユーティリティ関数と考えて問題ありません。
ルールの本体は関数が`return`してるメソッドをもったオブジェクトです。
Expand All @@ -99,7 +98,7 @@ ESLintではこのASTを使って、変数が未使用であるとか[no-console
}
```

[no-console.js](#no-console.js)のルールを見ると`MemberExpression` typeのNodeが `node.object.name === "console"` であるなら
[no-console.js](#no-console.js)のルールを見ると`MemberExpression` typeのNodeが `node.object.name === "console"` となった場合に、
`console`が残ってると判断してエラーレポートすると読めてくると思います。

ASTの探索がイメージしにくい場合は以下のルールで探索の動作を見てみると分かりやすいかもしれません。
Expand Down Expand Up @@ -184,8 +183,8 @@ function lint(code){
}
```

Pub/Subパターンを上手く使うことで、ASTをtraverseするのが一巡のみでそれぞれのルールに対して
どういうコードであるかという情報が`emit`で通知できていることがわかります。
Pub/Subパターンを上手く使うことで、ASTを走査するのが一度のみで、
それぞれのルールに対してどういうコードかという情報が`emit`で通知できていることがわかります。

もう少し具体的にするため、実装して動かせるようなものを作ってこの仕組みについて見ていきます。

Expand Down Expand Up @@ -234,8 +233,8 @@ add(1, 3);
この`RuleContext`はルールから使えるユーティリティメソッドをまとめたものです。
今回は`RuleContext#report`というエラーメッセージをルールからMyLinterへ通知するものだけを実装しています。

ルールの実装の方を見てみると、直接オブジェクトをexportしてるわけではなく
`context` つまり`RuleContext`のインスタンスを受け取っていることが分かると思います。
ルールの実装の方を見てみると、直接オブジェクトをexportしないで
`context`として`RuleContext`のインスタンスを受け取っていることが分かると思います。

[import, no-console.js](../../src/ESLint/no-console.js)

Expand All @@ -258,7 +257,7 @@ ESLintのように与えられたコードを読み取ってチェックする

そのため、この仕組みに加えてもう1つ抽象レイヤーを設けないと対応は難しいです。

つまり、read-writeなプラグインアーキテクチャとしては単純にこのパターンだけでは難しい部分が出てくるでしょう
つまり、read-writeなプラグインアーキテクチャとしては単純にこのパターンだけでは難しい部分が出てくると思います

> **NOTE** ESLint 2.0でautofixing、つまり書き換えの機能の導入が予定されています。
> これはルールからの書き換えのコマンドを`SourceCode`というオブジェクトに集約して、最後に実際の書き換えを行うという抽象レイヤーを設けています。
Expand All @@ -271,7 +270,7 @@ ESLintのように与えられたコードを読み取ってチェックする

## エコシステム

ESLintのルールは関数を公開したただのJavaScriptモジュールであるため
ESLintのルールはただのJavaScriptモジュールなので
ルール自体を[npm](https://www.npmjs.com/ "npm")で公開することができます。

また、ESLintはデフォルトで有効なルールはありません。
Expand Down
76 changes: 38 additions & 38 deletions ja/connect/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
> この文章は[Connect](https://github.com/senchalabs/connect "Connect") 3.4.0を元に書かれています。
[Connect](https://github.com/senchalabs/connect "Connect")はNode.jsで動くHTTPサーバーフレームワークです。
_middleware_という拡張する仕組みを持ち、Connectが持つ機能自体はとても少ないです。
_middleware_ という拡張する仕組みを持ち、Connectが持つ機能自体はとても少ないです。

この章ではConnectの_middleware_の仕組みについて見て行きましょう
この章ではConnectの _middleware_ の仕組みについて見て行きましょう

## どう書ける?

Expand All @@ -22,19 +22,19 @@ Echoサーバとは、送られてきたリクエストの内容をそのまま
}
```

`app.use(middleware)` という形で、_middleware_と呼ばれる関数には`request``response`といったオブジェクトが渡されます。
この`request``response`を_middleware_で処理してログを取ったり、任意のレスポンスを返しことができるようになっています。
`app.use(middleware)` という形で、 _middleware_ と呼ばれる関数には`request``response`といったオブジェクトが渡されます。
この`request``response`_middleware_ で処理してログを取ったり、任意のレスポンスを返しことができるようになっています。

Echoサーバでは `req.pipe(res);` という形でリクエストをそのままレスポンスとして流す事で実現されています。

### middlewareをモジュールとして実装

もう少し_middleware_をプラグインらしくモジュールとして実装したものを見てみます
もう少し _middleware_ をプラグインらしくモジュールとして実装したものを見てみます

次の[connect-example.js](#connect-example.js)は、あらゆるリクエストに対して、
`"response text"`というレスポンスを`"X-Content-Type-Options"`ヘッダを付けて返すだけのサーバです。

それぞれの処理を_middleware_としてファイルを分けて実装し`app.use(middleware)`で処理を追加しています。
それぞれの処理を _middleware_ としてファイルを分けて実装し`app.use(middleware)`で処理を追加しています。


[import nosniff.js](../../src/connect/nosniff.js)
Expand All @@ -45,46 +45,46 @@ Echoサーバでは `req.pipe(res);` という形でリクエストをそのま

[import connect-example.js](../../src/connect/connect-example.js)

基本的にどの_middleware_も`app.use(middleware)`という形で拡張でき、
基本的にどの _middleware_`app.use(middleware)`という形で拡張でき、
モジュールとして実装すれば再利用もしやすい形となっています。

> **Note** _middleware_となる関数の引数が4つであると、それはエラーハンドリングの_middleware_とするという、Connect独自のルールがあります。
> **Note** _middleware_ となる関数の引数が4つであると、それはエラーハンドリングの _middleware_ とするという、Connect独自のルールがあります。
## どういう仕組み

Connectの_middleware_がどのような仕組みで動いているのかを見ていきます
Connectの _middleware_ がどのような仕組みで動いているのかを見ていきます

`app`に登録した_middleware_は、リクエスト時に呼び出されています。
そのため、`app`のどこかに利用する_middleware_を保持していることは推測できると思います
`app`に登録した _middleware_、リクエスト時に呼び出されています。
そのため、`app`のどこかに利用する _middleware_ を保持していることは推測できると思います

Connectでは`app.stack`に_middleware_を配列として保持しています
次のようにして`app.stack`の中身を表示してみると、_middleware_が登録順で保持されていることがわかります
Connectでは`app.stack`_middleware_ を配列として保持しています
次のようにして`app.stack`の中身を表示してみると、 _middleware_ が登録順で保持されていることがわかります

[import connect-trace-example.js](../../src/connect/connect-trace-example.js)

Connectは登録された_middleware_を、サーバがリクエストを受け取りそれぞれ順番に呼び出しています。
Connectは登録された _middleware_、サーバがリクエストを受け取りそれぞれ順番に呼び出しています。

上記の例だと以下の順番で_middleware_が呼び出されることになります
上記の例だと以下の順番で _middleware_ が呼び出されることになります

- nosniff
- hello
- errorHandler

エラーハンドリングの_middleware_は処理中にエラーが起きた時のみ呼ばれます
エラーハンドリングの _middleware_ は処理中にエラーが起きた時のみ呼ばれます

そのため、通常は [nosniff.js](#nosniff.js)[hello.js](#hello.js) の順で呼び出されます。

[import nosniff.js](../../src/connect/nosniff.js)

`nosniff.js`は、HTTPヘッダを設定し終わったら`next()`を呼び出し、
この`next()`が次の_middleware_へ行くという意味になります
この`next()`が次の _middleware_ へ行くという意味になります

次に、`hello.js`を見てみると、`next()`がありません。

[import hello.js](../../src/connect/hello.js)

`next()`がないということは`hello.js`がこの連続する_middleware_の最後となっていることがわかります
仮に、これより先に_middleware_が登録されていたとしても無視されます
`next()`がないということは`hello.js`がこの連続する _middleware_ の最後となっていることがわかります
仮に、これより先に _middleware_ が登録されていたとしても無視されます

つまり、処理的には以下のようにstackを先頭から一個づつ取り出し、処理していくという方法が取られています。

Expand All @@ -102,10 +102,10 @@ next();// 初回
```


このような_middleware_を繋げたものを_middleware stack_と呼ぶことがあります。
このような _middleware_ を繋げたものを_middleware stack_と呼ぶことがあります。

_middleware stack_で構成されるHTTPサーバとして、PythonのWSGI MiddlewareやRubyのRackなどがあります。
ConnectはRackと同じく`use`で_middleware_を指定することからも分かりますが
_middleware stack_ で構成されるHTTPサーバとして、PythonのWSGI MiddlewareやRubyのRackなどがあります。
ConnectはRackと同じく`use`_middleware_ を指定することからも分かりますが
Rackを参考にした実装となっています。

- [Ruby - Rack解説 - Rackの構造とRack DSL - Qiita](http://qiita.com/higuma/items/838f4f58bc4a0645950a#2-5 "Ruby - Rack解説 - Rackの構造とRack DSL - Qiita")
Expand All @@ -114,16 +114,16 @@ Rackを参考にした実装となっています。

## 実装してみよう

Connectライクな_middleware_をサポートしたJunctionというクラスを作成してみます
Connectライクな _middleware_ をサポートしたJunctionというクラスを作成してみます

Junctionは、`use(middleware)``process(value, (error, result) => { });`を持っているシンプルなクラスです。

[import junction.js](../../src/connect/junction.js)

実装を見てみると、`use`で_middleware_を登録して`process`で登録した_middleware_を順番に実行していきます
そのため、`Junction`自体は渡されたデータの処理をせずに、_middleware_の中継のみをしています
実装を見てみると、`use`_middleware_ を登録して`process`で登録した _middleware_ を順番に実行していきます
そのため、`Junction`自体は渡されたデータの処理をせずに、 _middleware_ の中継のみをしています

登録する_middleware_はConnectと同じで、処理をしたら`next`を呼んで、次の_middleware_が処理するというのを繰り返しています
登録する _middleware_ はConnectと同じもので、処理をしたら`next`を呼んで、次の _middleware_ が処理するというのを繰り返しています

使い方はConnectと引数の違いはありますが、ほぼ同じような形で利用できます。

Expand All @@ -132,11 +132,11 @@ Junctionは、`use(middleware)` と `process(value, (error, result) => { });`を

## どういう用途に向いている?

ConnectやJunctionの実装を見てみると分かりますが、このアーキテクチャでは機能の詳細を_middleware_で実装できます
そのため、本体の実装は_middleware_に提供するインタフェースの決定、エラーハンドリングの手段の提供するだけでとても小さいものとなっています。
ConnectやJunctionの実装を見てみると分かりますが、このアーキテクチャでは機能の詳細を _middleware_ で実装できます
そのため、本体の実装は _middleware_ に提供するインタフェースの決定、エラーハンドリングの手段の提供するだけでとても小さいものとなっています。

今回は紹介していませんが、Connectにはルーティングに関する機能があります。
しかし、この機能も「与えられたパスにマッチした場合のみに反応する_middleware_を登録する」という単純なものです。
しかし、この機能も「与えられたパスにマッチした場合のみに反応する _middleware_ を登録する」という単純なものです。

```js
app.use("/foo", function fooMiddleware(req, res, next) {
Expand All @@ -152,26 +152,26 @@ app.use("/foo", function fooMiddleware(req, res, next) {

## どういう用途に向いていない?

このアーキテクチャでは機能の詳細が_middleware_で実装できます
その中で多くの機能を_middleware_で実装していくと、_middleware_間に依存関係を作ってしまう事があります
このアーキテクチャでは機能の詳細が _middleware_ で実装できます
しかし、多くの機能を _middleware_ で実装していくと、 _middleware_ 間に依存関係を作ってしまう事があります

この場合、`use(middleware)` で登録する順番により挙動が変わります。
_middleware_の利用者が、間で起きる前提の解決を行う必要があります。
_middleware_ の利用者が、間で起きる前提の解決を行う必要があります。

そのため、プラグイン同士の強い独立性や明確な依存関係を扱いたい場合には不向きといえるでしょう。

これらを解消するためにコアはそのままにして、最初から幾つかの_middleware stack_を作ったものが提供されるケースもあります。

## エコシステム

Connect自体の機能は少ないですが、その分_middleware_の種類が多くあります
Connect自体の機能は少ないですが、その分 _middleware_ の種類が多くあります

- [github.com/senchalabs/connect#middleware](https://github.com/senchalabs/connect#middleware)
- [Express middleware](http://expressjs.com/resources/middleware.html "Express middleware")

また、それぞれの_middleware_が小さな単機能であり、それを組み合わせて使うように作られているケースが多いです。
また、それぞれの _middleware_ が小さな単機能となっていて、それを組み合わせて使うように作られているケースが多いです。

これは、_middleware_が層として重なっている作り、つまり_middleware stack_の形を取ることが多いからであるとも言えます
これは、 _middleware_ が層として重なっている作り、つまり _middleware stack_ の形を取ることが多いだと言えます

![pylons_as_onion](img/pylons_as_onion.png)

Expand All @@ -182,7 +182,7 @@ Connect自体の機能は少ないですが、その分_middleware_の種類が
## この仕組みを使っているもの

- [Express](http://expressjs.com/ "Express")
- Connectと_middleware_の互換性がある
- Connectと _middleware_ の互換性がある
- 元々はConnectを利用していたが[4.0.0](https://github.com/strongloop/express/blob/4.0.0/History.md "4.0.0")で自前の実装に変更
- [wooorm/retext](https://github.com/wooorm/retext "wooorm/retext")
- `use`でプラグイン登録していくテキスト処理ライブラリ
Expand All @@ -193,9 +193,9 @@ Connect自体の機能は少ないですが、その分_middleware_の種類が

ここではConnectのプラグインアーキテクチャについて学びました。

- Connectは_middleware_を使ったHTTPサーバーライブラリである
- Connectは _middleware_ を使ったHTTPサーバーライブラリである
- Connect自体の機能は少ない
- 複数の_middleware_を組み合わせることでHTTPサーバを作ることができる
- 複数の _middleware_ を組み合わせることでHTTPサーバを作ることができる

## 参考資料

Expand Down
Loading

0 comments on commit b5f4779

Please sign in to comment.