mysqldを読んでみる
仕事でmysqlを使ってる影響で何となくソースを読んでみたくなってきた。 C言語の勉強がてらちょっと読んでみることを試みる。 今回は読み始めるまでの記録。
※後で知りましたがCじゃなくてC++でした。
ソースコードの場所
mysql githubでぐぐったら出てきた。 色々あるけど読みたいのはmysqldなのでこれ: https://github.com/mysql/mysql-server
第一歩
とりあえずいくつか眺めたけど、さっぱり分からん。 マクロがいっぱいだったり、cmakeが1000行超えてたり中々素敵。 C言語だからmain関数があるだろうと当たりを付けて探してみる。
main
パラパラと適当に眺めても何もわからないので検索機能を使うも100ページぐらい候補が出てきて焦る。 一瞬戸惑ったけど、まぁ3桁で済むならいいか、高々有限だし。
そんな感じで頭から見始めると数ページにてsql/main.ccファイルにてmain関数を発見。 何でsqlフォルダなんだろう…
main関数は別の関数(mysqld_main)を呼んでるだけなんで次はそっちを見に行くことにする。 ここらへんで疲れ果てたので一日目終了。
収穫
PageObjectパターンについてちょっと考える
概要
- PageObjectパターンのざっくり解説
- 考えたこと試してみたこと
- 感想
PageObjectパターン
PageObjectパターンはデザインパターンの一つ。Seleniumを使っての自動化テストで再利用性の高いテストスクリプトを構築するのが主な目的 (別にSeleniumに限った話ではないと思うし、WrapperとかAdaptorっていう考え方かな?)
解説見るとこんな感じの説明をよく見る
- Webページ(HTMLのコーディング)の実装詳細を隠蔽する。
- 機能を表す言葉に変換する。
- テストを記述しやすくする。
どうやるかってーと
- 実装詳細の隠蔽: Seleniumを使うときに書かれるcssセレクタ―やxpath等といったhtmlの情報はPageObject内でだけ持たせる。これで外から隠す。
- 言葉の変換: PageObjectに書かれたSeleniumを使ったコードを機能由来の名前名を付けることで機能仕様を記述する。
- テストの記述しやすさ: PageObjectのメソッドの返却値に別のPageObjectにする。こうすることでメソッドチェーンでテストコードを記述でき見やすくなる。
考えたこと試してみたこと
「記述しやすくする」と「HTMLの詳細隠蔽・機能記述」はどうも両立させるとPageObjectが重くなり過ぎない?(単一責務の法則に違反する)とかちょっと思った。 そこで次のように一つのページを2層に分けてみることを考えてみた。
- 詳細隠蔽用のクラス(仮にPageCoreクラスと呼ぶ)
- Coreクラスを利用してテスト記述に求められる機能を実装する。(こっちPageFacadeクラスと呼ぶ)
PageCoreクラスはロケータとページの機能を表現するメソッドを持つ。あくまでページとそのコマンド群という位置づけのため各メソッドの返却値はvoidとした。
PageFacadeクラスはテストで利用されることを前提に高級な機能を持たせた。 例えばロードされるのを待つとかいう制御に関するコードとか。書きやすくするためのFacadeクラスには別のFacadeクラスを返すとか。
感想
当初の目的から考えるこの実装は失敗があったように感じる。何が起きたかっていうと、PageCoreクラスが画面を表現しきれていない。
画面同士は遷移元・遷移先という繋がりがあるはずなのにPageCoreクラスにそれが書かれていない。つまり画面機能の情報がPageFacade側とPageCore側で分けられちゃった。(各画面の機能ができるかはCoreクラスに書けたんだけどね)
ただ、画面の機能を2クラスに分けるという考え方自体はありかなぁとも思う。 その場合、例えば何らかのログインページ(ユーザーID入力欄、パスワード入力欄、ログインボタンを持つとする)を表現する場合 PageCoreクラスが持つメソッドは
- public void putId(String)
- public void putPassword(String)
- public void pushLoginButton(String)
みたいな構成する部品の機能を由来とする名前のメソッド名を持って、 PageFacadeクラスは
- public AfterPage login(String, String)
みたいなその画面の機能を由来として名前のメソッドを持つことになるのかな。 画面遷移図と画面機能の説明に対応するようなイメージ。
後、PageObjectパターンがPageObjectパターンを返却するってのはその画面についての機能の一部である「画面遷移先」の情報を表すためであってメソッドチェーンで書きやすくなるのはおまけ的な効果かなと思う。
javascriptで思ったこと
動機
最近javascriptを書き始めた。
他の言語との違いとか、注意点とか個人的に気になったことを備忘録としてまとめておく。
他の言語との違い
- 動的型付け
- 手続き型
- オブジェクト指向(プロトタイプ)
- 関数が第一級の扱い
- 変数のスコープ
- シングルスレッド
といったところ。一つ一つ考えてみる。
動的型付け
phpの様に型付けは動的に行われる。なので変数の宣言の際に型名を指定する必要はない。静的解析の恩恵が受けやすい静的型付けのほうが個人的には好み。
数学でも割としっかり証明書く人は静的付けのほうが好きそうという勝手な偏見。
手続き型
言うことは特になし。
オブジェクト指向(プロトタイプ)
クラスがあってそこからインスタンスが作られるのではなく元になるインスタンスがあってそれをコピーして新しいインスタンスを得る。オブジェクトの量と種類が少量多種みたいな状況だと書き易いのかな?
関数が第一級
よく使うのは関数を変数に代入する機能。なので関数を引数にする関数が出来たりする。数学的に言えばは双対空間とか汎関数みたいな感じ。便利。
関数の処理の中でちょっとだけ変えたい部分について引数として関数を渡してそれを起動したり出来る。
代入をクロージャで記述して変数の評価を遅らせたりできるみたい。
シングルスレッド
本質的にシングルスレッドらしい。内部の機構は、
- 処理するタスクをキューに登録される
- その時のキューの先頭のタスク処理する
- タスクは関数単位である
という感じらしい。タスクを途中で止めての割り込みとかはできないみたい。なので中々終わらない処理を書くと何も反応しなくなる。
これを知っておかないと、一定時間毎に処理を行うsetInterval関数とか一定時間後に処理を行うsetTimeoutの挙動の理解を誤りそう。
equalメソッド
equalメソッド
JavaのObjectクラスにはequalsというインスタンスメソッドがある。役割としてはインスタンスが「同じ」であるかを判定するメソッド。「同じ」場合はtrue、「同じでない」場合はfalseを返すようにする。つまり、実質的には二つのインスタンスに対しての「同じ」を定義する役割を担ってることになる。
ただし単にtrue、falseを返せば良い訳でなく「同じ」という概念をきっちり表現するように実装には要件がある。一言で表せば同値関係になっていることを求められる。詳細な解説はJavadocに任せる。
必要性
参照型の場合"=="演算子は「参照が同一であるか」を判定する。"=="演算子が興味あるのはオブジェクトが表現する意味じゃない。だから、そのまま使うには厳しすぎる。
例えば、"=="を基準に考えると、
Pair<String, String>a = new Pair<>("hoge", "fuga"), b= new Pair<>("hoge", "fuga");
って書いたとき、aとbは「違う」ことになる。いくらなんでも、そんな基準の「同じ」は使う上で困る。やっぱこの二つは「同じ」になって欲しい。そこでもっと緩い意味での「同じ」が必要になる。でも、そんなPairの意味なんてJava言語は知らん訳で、何でequalsメソッドを適切に定義して使ってね。と。
クラスの意味をはっきりさせるためにもequalsはオーバーライドしましょうと。これがあるとSetやMapも使えるしね(java.utilパッケージのSetはインスタンスの集合をequalsで割った商集合みたいな存在、Mapはその商集合の上の写像みたいな存在だし)
オマケ
hashCodeメソッドはequalsで割った商の上でwell-definedってのが要件に入っているので注意と。
委譲のユニットテスト
こんな感じのクラスとメソッドがあるとする。
public class Model() implements Editor, Writer { @Override public edit() { //Editorの実装 } @Override public write() { //Writerの実装 } }
public class Facade() { private Editor editor; private Writer writer; public Facade(Model model) { this.editor = model; this.writer = model; } public Edit() { editor.edit(); } public Write() { writer.write(); } }
意図としては、こんな役割分担。
- Facadeクラスの役割は、あくまで「Modelに処理をさせる」という内容
- 実際の編集はModelクラスが行う
さて、こんな時Facade.Editのテストをどうしよう。
- Modelクラス→Facadeクラスと作ってテストする。検証はModelを比較することで行う。
ってしたいけどこれだと「Facadeは依頼するだけ」という立場であることを検証できていない気がする。それにこの検証はModelクラスのEditメソッドのテストと同じことをする破目になりそう。EditorやWriterのダミー的なものを使えるようにしてそれで検証するのがいいのかな?
-
-
-
-
- 2015/08/19追記
-
-
-
結局、テスト実行クラスの内部クラスとしてModelを継承して、メソッドをオーバーライドするテストコードにしてみた。テスト対象メソッドがオーバーライドされたものを起動することで委譲を確認するって感じ。classがfinal修飾されてる場合は考えないことにしよう。
@Test public testEdit() { public class TestingModel extends Model { @Override public Edit() { System.out.println("テスト用メソッド"); } } TestingModel model = new TestingModel(); Facade fcade = facade(model); facade.edit(); }
テスト対象クラスの設計を見直したほうがいいというのはもっともだけどそっちは諦めた。
他に考えたアイディアは、
- リフレクションでオブジェクトを弄ってしまう
- テスト対象クラスにテスト専用機能を作る
- テスト対象クラスのフィールドのアクセス修飾子を弄る
それぞれ次のような理由で却下。
- 使い方分からない
- わざわざそれを作るのも何か違う気がするっていうのと、他の場所での制限する手が分からない
- 元の機能を変更するのはどうかと思う
テスト対象にテスト用の機能を作るのはありかなと思う。適切に量を制限できるなら。テスト側からだけ使えるよってのは専用のアノテーション作ってで表現するとかかな。ただ、コレって実質的に裏口を作るようなものだしどうなんだろうなぁ……。