OneNoteがExcel方眼紙の代替となりうる7つの理由

私はSIer歴約5年ですが、現場では所謂「エクセル方眼紙」を扱うことが多いです。
エクセル方眼紙の任意の位置に文字列を配置できるメリットは大きく、
メモ書きや手順書、設計書等、あらゆる場面で活躍します。
この直感的な使いやすさはWordを凌駕していますし、
汎用性が高いです。
(もちろん、体裁の整ったマニュアルなどはWordで作成すべきですが・・・)

ところが、今の現場リーダーの趣味でOneNoteを多用するようになり、
このアプリこそが、エクセル方眼紙を凌駕する
「NGH(Next Generation Hoganshi!)」だと確信するようになりました。
その理由は以下のとおりになります。

1. 任意の位置に文字列を埋め込める
画面内の任意の位置に文字列を埋め込めます。
その自由度はエクセル方眼紙を凌駕し、しかも方眼紙の面倒な
制約(改行、折り返し、セル幅、セル結合 etc...)がありません。
ここまで自由度が高いと、本当に紙のメモのように扱えます。

2. メモ書きツールとしてよりリッチ
書式スタイルや、メタ情報(シール)埋め込み等の機能が強力で、
表現力、管理性が優れています。
手動での書式設定と、ルール化で頑張る必要のあるエクセルとは、
文章の表現力、管理性に大きな差があります。

3. Webページ等の取り込みにも対応
WebページをOneNoteに取り込むことで、Evernote的な
スクラップブックを作成できます。
しかも、表現力はEvernoteよりも上なので、
リッチなスクラップブックを作成できます。

4. よりリッチな変更履歴
過去の履歴一覧、差分表示などを実現しています。
エクセルでは、戻る/進むのみを選択でき、
履歴管理、差分表示が難しいので、
これも大きなアドバンテージです。

5. メモ書きの入力ソースが豊富
画像、動画、録音、手書きメモ等、情報のソースが豊富です。
また、任意のファイルを添付できます。
エクセルは画像の添付のみ可能なので、
メモ書きツールとしての幅がより広いです。

6. 検索性が高い
シェープ内の文字列を検索できます。
エクセルでシェープ内の文字列を検索できないのは、
非常に大きなネックなので、この差は大きいです。

7. 無料である
無料でインストールできます!
正直、有料でも使う価値のあるツールですが、
無料ならとりあえず入れるしかないでしょう。
http://www.onenote.com/

以上のことから、純粋な表計算用途から外れた使い方のエクセル汎用方眼紙と比べて、
OneNoteの方が圧倒的に使いやすく、用途が広いツールと言えるでしょう。
(もちろん、表計算がやりたいなら、エクセルを選択すべき)

2013年中に読んだ技術書のまとめ

2013年中に読んでためになった技術書をまとめたものです。
「広く(世間一般的な感覚ではなく、私の感覚で)浅く」「幅優先」で
進めてみました。

ミドルウェア

去年、最も力を入れたのはミドルウェア系の書籍です。ミドルウェアの経験のなさが私の弱点のうちの一つなので、色々読んでみました。

また、読書ではないですが、気合で未経験のままOracle MasterをBronze〜Goldまで2ヶ月ほどで取得してます。
(殆ど意地というか、気合ですね。ああいうの大好物なので・・・。早くGold取得前提の研修を受けないとorz)

WebSphere Application Server V7: Concepts, Planning and Design

世界的にシェアが高いIBMのAPサーバWASのバイブルです。
基本的なコンセプト、トポロジ、メッセージング、セキュリティ、クラスタリング等、WASの機能について網羅的に広く浅く解説しています。
かなり実践的なトポロジやクラスタリングの考え方、パターンを解説しているため、実際のシステムでの使われ方を想像できました。
※ちなみに最新のWAS8.5ではなくて、WAS7なのは、開発環境がWAS7で固定なためです。

WebSphere Application Server V7 Administration and Configuration Guide

WASに関して深く踏み込んだタスクベースのガイドブックです。インストールからクラスタの構成、Jythonによる操作等、現場ですぐに使える知識が盛り沢山です。
また、Concepts〜の方では薄かった、MonitoringやDatabaseアクセス、セッション管理、クラスローダ等も詳細に解説されており、WAS管理者なら必読です。

Solr In Action

OSS全文検索サーバApache Solrのガイドブックです。全文検索は様々なプロジェクトで必要なので、Solrに手を出しました。
内部の仕組みの概要が丹念に解説されて、全文検索の仕組みの概要をつかめます。また、Solrでできること、できないことがはっきり解説されており、Solr使いなら必読書でしょう。

テスト系

Pragmatic Software Testing: Becoming an Effective and Efficient Test Professional

テストの体系だった知識を学びたくて読んでみました。小手先のテクニック集ではなく、「テストとはなにか」「テスト戦略」から始まり、トップダウンで体系だった知識を身につけられます。
また「Pragmatic」のタイトルどおり実践寄りで、章末問題も相当な難易度で挑む価値があります。
テストと言って普通思い浮かべる「同値分割」や「デシジョンテーブル」といった現場で即使えるテクニックの解説もありますが、大分後に来るので、
著者としては、「ソフトウェアテストの世界観の理解」「テスト戦略の理解」の方が大事なんでしょうね・・・。
テクニックに関しては、ドキュメントレビューを「Static Testing」と位置づけ、複数変数の同値分割であるドメインテストは役に立ちました。

OS等

z/OS concepts

IBMメインフレーム用OS「z/OS」の解説書です。仕事でz/OSを扱うため、ひと通り読む必要がありました。
Unix系OSとの対比や、JES,JCL,データセット等のz/OS独特の概念の解説等、非常に読み応えがあります。
また、TSOパネルの操作方法等、実践的な解説もあり、これ一冊でひと通りz/OSの基本的な要素を網羅できます。
これ一冊でz/OSマイスターにはなれませんが、z/OS上で動く他のソフトウェアのオペレータになるには十分です。

開発プロセス

ユースケースの実践的なガイドラインを示している良書です。「実際のプロジェクトにおいて、限られたリソースで効果的な成果物を作成する」ことに
フォーカスしており、非常に実践的でとてもためになりました。かる〜く読める系の書籍だと思います。


Essential Scrum: A Practical Guide to the Most Popular Agile Process

有名なアジャイル開発プロセスの内の一つ、「スクラム」の解説書です。
スクラムのフレームワークはとてもシンプルでわかりやすく、正直だとは思うのですが、
あまりにもシンプル過ぎて属人的であると感じました。
大規模開発への適用は難しいかもしれませんが、顧客が納得いくまでイテレーションを
回せるので一品物のツールや、フィーリングが大事なGUIアプリには有効かもしれません。

Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation

SIの現場でも取り入れるのが当たり前になりつつある、CI(Continous Integration)のバイブルです。
冗長な記述が多い、筆者が好む専門用語を説明無しで多用する、節が1つ変わると内容が全く異なるなど、非常に読みづらいですが、
内容は充実しており、「ソフトウェアデリバリーの大切さ」が身に染みてわかる良い書籍です。
実際、この書籍のパターン、考え方等を初めから上手く適応できていれば、苦労はずっと少なく済むはずです。

ただし、デザインパターンの書籍と同じく、「ある程度蒸留されたコンセプト、ベスト・プラクティスの解説」がメインであるため、
実際のツールの使い方などは別の書籍で補完する必要があります。


Jenkins: The Definitive Guide

CIサーバの最も有名な実装である「Jenkins」の仕組み、使い方等を解説した書籍です。
Jenkinsは機能拡張が頻繁で、プラグインの流行り廃りも激しいためか、
この書籍ではJenkinsの基本的な概念、使い方等余り手が入らないところの解説に
重点が置かれているので、Jenkinsを初めて使う人にはだれにとっても役に立つ書籍に
仕上がっています。

ただし、Jenkinsはベスト・プラクティスやパターンを編み出し、様々なプラグインを組み込んでこそ効果を発揮するので、
googleで
slideshare Jenkins best practice
などと検索するとたくさんひっかるので、最近のトレンドを追いかけるべきかと思います。

デザイン等

Design Patterns: Elements of Reusable Object-Oriented Software

有名なGOFです。ちょっと説明不足だったり、適切で無い箇所もありますが、全体的に非常にクオリティが高く、オブジェクト指向プログラムを「まじめに」書くならマストバイな書籍です。
別の記事でそこそこ詳しいレビューを書いてます。
「Design Patterns: Elements of Reusable Object-Oriented Software」の私的レビュー

Designing Interfaces

GUIの設計パターンの書籍です。「インターフェースのデザインとはなにか?」から丹念に解説されており、単なる流行りもののライブラリの使い方とは
一線を画す内容です。逆に言えば、こういうバックグラウンド無しで快適なインターフェースをデザインすることは難しいでしょう。


The Art of Readable Code

コーディング力を高めるために読んでみました。ずっと仕事でコーディングしている人にとっては「何を今更」という内容かもしれませんが、
経験の浅い私にとっては、とてもためになりました。全体的に軽いノリで、挿絵が漫画なので、肩に力を入れずに読めるはずです。

CIとソフトウェアのデリバリーについて

ビルド、デプロイ、テスト、リリースのタスクの重要性

ソフトウェアのビルド、デプロイ、テスト、リリースはアドホックにマニュアルで行われることが多いが、実際にはこれらのタスクは極めて重要であり、設計や実装と同じく、顧客に価値を提供する「value stream」の一部である。そのため、これらのタスクは効率化、形式化されるべきである。

value streamのイメージ

また、マニュアルによる操作は、以下のような問題がある。

  • いざ不具合があったときの対応が難しい
  • ミスが起きやすく、時間がかかる
  • これらのタスクに時間がかかると、テスト結果や顧客からのフィードバックを得るのに時間がかかる
  • ビルド、デプロイ、テスト、リリースが大変だとその作業が先にばしにされてしまい、ますます自体を悪化させる
  • ソフトウェアのデリバリーの原則

    ビルド、デプロイ、テスト、リリースなど、あらゆるタスクを自動化する
    • タスクを繰り返し可能とする
    • ミスを減らす
    • 予想可能なタスクにする
    自動化したタスクを繰り返し小刻みに実施する
    • 一回のジャンプを小さくすることで、修正にかかるコストを減らす
    • フィードバックを得るのにかかる時間を短縮する
    デリバリープロセスをみんなで改善する
    • プロジェクトに関わるメンバ全員が、ソフトウェアのデリバリーに責任を持つ
    • プロジェクトに関わるメンバでデリバリープロセスを改善してく

    設定の管理

    ソフトウェアの設定、環境の設定はソースコードと同じようにVCSで管理されるべき
    ソフトウェア、環境の設定はソースコードと同様に一文字の違いでソフトウェアを破壊することが可能であるため、ソースコードと同様にVCSで管理し、テストしなければならない。
    環境の設定は自動化されるべき
    特に環境の設定は適当になりやすいが、非常に重要であるため、Puppetなどのツールを用いてVCSと同期すべき
    ライブラリの依存関係の管理
    ライブラリの依存関係は極めて重要なので、Maven, Ivy, Gradleなどのツールで自動化し、VCSで管理すべき

    CI(Continuous Integration)

    ソフトウェアの品質を高く保つためのExtreme Programmingのプラクティス。VCSに小刻みに成果物をコミットし、そのタイミングで一連の自動化されたビルド、テストを走らせることで、ソフトウェアの不具合を早期に洗い出し、修正することを可能とする。 前提条件
    あらゆるものをVCSで管理する
    ソースコード、設定、環境設定、開発環境、ドキュメントなど、開発に関わるものは何でも突っ込め!
    ビルド、テストを自動化する
    テスターは、探索的テスト、ユーザビリティのテストなどより付加価値の高い自動化できない試験を頑張ってもらう
    チーム内での合意を得る
    CIはツールではなくてプラクティスなので、チーム内での合意が得られなければ機能しない
    CIの原則
    小刻みにチェックインする
    一回のチェックインの修正規模が大きいと修正が大変なので小刻みにチェックインする
    自動化されたテストスイーツを用意する
    チェックインされた成果物が既存の成果物を壊していないかを確認する
    ビルド、テストが壊れたまま放置しない
    チェックインでビルド、テストが壊れたら、原因を調査し、治すことを最優先する
    実現方法 CIはプラクティスであって、ツールではないため、必ずしもこれらのツールを使う必要はないし、逆にこれらのツールを使っても手動操作が多かったり、一度のチェックインのでの修正量が膨大だったり、壊れたビルドが放置されていたらCIの意味が無いので要注意。
    CI Server
    Jenkins(他にもいっぱいあるっぽい)
    コードの品質チェック
    Checkstyle, FindBugs
    Build Script
    ANT, Maven, Gradle
    xUnit Test
    JUnit, NUnit

    Deployment Pipeline

    CIでは、ソースコードなどを弄る開発作業を対象としているが、CIの考え方を受け入れ試験、リリースなどのソフトウェアのコンセプト立案から顧客に価値を届けるまでのデリバリープロセス全体に拡大し、一連の流れを「Deployment Pipeline」としてモデル化する。「Deployment Pipeline」は、単一の流れに沿った開発からのパラダイムシフトであり、CPUのパイプライン処理のごとく、五月雨的にVCSへのチェックインを契機としてビルド、自動化されたテストを実行し、そのままテストチームでのマニュアルテストを実施し、ソフトウェアを「常に」リリース可能な状態にすることを可能とする。「Deployment Pipeline」をどのように実装するのかは、プロジェクトの要件ごとに大きくことなるので、プロジェクトごとに「Deployment Pipeline」を設計、実装し、改善していくことが必要となる。 こんな感じの流れがCPUのパイプライン実行の如く、五月雨的に動くことになります。 また、「Deployment Pipeline」では、「ビルド、デプロイ、テストなどをボタンひとつで実現できるように徹底的に自動化する」という、CIの考え方が基盤にあるので、特に何かを契機にすることなく、動くソフトウェアをいつでも、だれでもデプロイすることができ、テスターやユーザーが指示を待たなくても自発的にテストを実施できる、また、動くソフトウェアが常にデプロイ可能な状態なので、ソフトウェアのデリバリー作業を「見える化」し、開発関係者に安心感を与える効果もある。

    参考文献

    Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation (凄く美味しいけど、文章量多すぎ!)

JBehaveでBehaver Driven Developmentを体験してみる

Behaver Driven Developmentって何?

要するに、Domain Driven Designの「動くモデルをプロジェクトにおけるユビキタス言語にする」という発想と同じで、なんとか設計書、仕様書とテストケース、製品コードをばらばらに管理するのではなく、技術的詳細を隠蔽してビジネスユーザーと対話できるレベルにまで抽象化した「実行可能な仕様書」を作成することでコミュニケーションを円滑化し、ドキュメントや仕様と実際の成果物との乖離を防ぐという狙いがあるようです。

一枚の絵にするとだいたいこんな感じだと思われます。

「実行可能な仕様書」といっても、実際にプログラムとして実行可能なわけではなく、各ストーリーの一文=ステップに対応するテストケースプログラムを用意し、実行していくことになります。それだけただ単に各ステップに対応したテストケースを実行するだけになってしまいますが、そこは一工夫されています。SpringやJAX-RSからインスパイアされたのだと思われる「ステップから値をキャプチャする機能」があり、これを用いることで「○○の数は"10"個である」の「10個」の部分のような部分をテストケースへの入力としてキャプチャすることができます。

「複雑なAcceptance Testの自動化」というところに主眼が置かれていますが、この「実行可能な仕様書」の重要性は、CONTINUOUS DELIVERYでも「CHAPTER8 AUTOMATED ACCEPTANCE TESTING」で、丸々一章を割いて様々なテクニックと共に詳細に解説されています。JBehaveだけ見ているとあまりぴんと来ませんでしたが、プログラムで仕様を書いてJUnitから実行できる≒自動化できる
ということになりますね。

JUnitに組み込んで実行してみる

Github上に非常にシンプルなサンプルを置いておきました。
https://github.com/zyake/jbehave-hello-world

仕様書

仕様書は専用の文法にしたがって記述します。

calculation service stories

Scenario: calculates sum of two values (less than int max)

Given the system is ready
When I sum up the value "5" and the value "10"
Then the result should equal to 15

Scenario: calculates sum of two values (equal to int max)

Given the system is ready
When I sum up the value "1073741823" and the value "1073741824"
Then the result should equal to 2147483647

ステップの実装

仕様書にある各ステップの実装は以下のとおりになります。

public class CalculationSteps extends Steps {

    private Calculator calculator;

    private int result;

    @Given("the system is ready")
    public void theSystemIsReady() {
        this.calculator = new Calculator();
    }

    @When("I sum  up the value \"$var1\" and the value \"$var2\"")
    public void iSumVar1AndVar2(int var1, int var2) {
        result = calculator.sum(var1, var2);
    }

    @Then("the result should equal to $value")
    public void thenTheResultShouldEqualToTheValue(int value) {
        assertThat(result, is(value));
    }
}

テストケースクラス

仕様書とステップの実装をテストケースで関連付けして実行します。要注意なのは、JUnitから実行した場合、どのステップが実際に実行されたのか表示されないため、ステップ単位での実行結果を確認したい場合は、以下のライブラリを使用する必要があります。
https://github.com/codecentric/jbehave-junit-runner
使い方もシンプルで、実行対象のテストケースクラスに以下の1行を追加するだけです。
@RunWith(JUnitReportingRunner.class)

@RunWith(JUnitReportingRunner.class)
public class CalculationStoriesTest extends JUnitStories {

    @Override
    public InjectableStepsFactory stepsFactory() {
        return new InstanceStepsFactory(new MostUsefulConfiguration(), new CalculationSteps());
    }

    @Override
    protected List<String> storyPaths() {
        // デフォルト設定ではクラスパスから検索する。
        return Arrays.asList("calculation.story");
    }
}

実際にアプリケーションを開発する場合は、データの初期化方法、非同期の処理の待ち合わせ、開発途中のシステムのスタブや外接システム、ドライバの作成などが必要になり、Seleniumなどを使ってWeb画面と戦う必要があるかもしれませんし、相当の経験と技術力が必要で、一筋縄では行かないと思われます。

BDDの効果は?

結局、テストケースに相当するプログラムは自力で作らなければならないので、どういった効果があるのか疑問に思う方もいると思いますが、
個人的には「意識を変える」「仕様書との乖離を防ぎ、維持メンテ性を高める」ことには、かなり効果があるのではないかと思います。

例えば、結合試験の仕様書を作成し、そのとおりテストケースを実装したとしても、仕様変更やバグ修正の影響でパラメータやテストのステップが変わる、あるいは仕様書からのコピペミスや実装ミスで仕様書と乖離した試験が実施されることは極普通に起こりえます。

しかし、JBehaveを使って仕様書とテストケースの結合度を高めることができれば、「仕様書に書いてある試験が全く実施されていない」「パラメータが途中で変わってしまった」「テストケースはあるが、仕様書のどの記述に対応しているのかわからない」などといった自体を起きづらくすることはできます。また、仕様書は技術的な詳細が隠蔽されているので、テスターが途中でパラメータやステップの順序を変える、
あるいはテストケースの作成とテストケースの実装の分離、本来の目的であるビジネスユーザーと開発者の対話の促進といった効果はあると思います。

参考資料

JBehave公式
http://jbehave.org/
AiL – Simplest JBehave Scenario - Software is too expensive to build cheaply….
http://twasink.net/2012/06/25/ail-simplest-jbehave-scenario/
CONTINUOUS DELIVERY
http://www.amazon.com/dp/0321601912?tag=contindelive-20

「Design Patterns: Elements of Reusable Object-Oriented Software」の私的レビュー

今更ながら、有名な「Design Patterns: Elements of Reusable Object-Oriented Software」をひと通り読んだのでレビューを書いてみます。

いいところ

デザインパターンの位置づけについて記述されている

第一章では、そもそもデザインパターンとはどういう世界観の中で、どういった位置づけで使われるものなのかを解説しており、ここが後半のデザインパターンと同じくらい重要で非常にためになった。また、自分が今まで頭の中に思い描いていた世界観とは違う使い方が主に想定されているようで、カルチャーショックを受けた(うわ、そうだったのかよ、的な)自分のOOPに対する理解が根本的に足りないことを実感・・・。

簡潔で読みやすい

非常に簡潔で、さらさら読める。特に後半のカタログは、全てのパターンで同じフォーマットで、簡単な概要が説明してから詳細に入っていくという書き方なので読みやすく、頭に入りやすい。

各パターンの解説が非常に実用的

各パターンの解説が、ソースコードベースで具体的に説明されており、実用性が高く、すぐに使える。

パターン間の関連の解説がとてもわかりやすく実用的

Creational, Structural, Behavioralの各パターンカテゴリの最後に書いてある、パターンの総まとめ的な解説がとてもわかりやすく、実用的で大変ためになった。個人的には、「オブジェクトの設計」や「レイヤ化」といったところにダイレクトに関わってくるStructural Patternの中の人達の総まとめは読み応えがあってよかった。

パターンのボキャブラリーが豊富かつ、汎用的

パターンのボキャブラリーが豊富かつ、非常に汎用的なので、知っていて損をするパターンは無いと言い切れるレベル。もちろん、使用頻度に違いはあるが、この本に登場するパターンはあらゆるところで頻繁に目にすると思われる。また、パターンの粒度もそこまで細かすぎず、アーキテクチャパターンまでスコープが広く無いが、小技で終わらない、そこそこ粒度が大きいパターンもある。(Bridge, Facade, Flyweightなど)

わるいところ

一章の説明があまりにも簡潔すぎ

一章のデザインパターンを適用する領域についての話は、とても重要なのに、さらさら書き過ぎていて相当読み込まないと何を言いたいのか、どういった世界観なのかわからない。読者がOOPのコンセプトやオブジェクト抽出のポイント、OOADなどをある程度知っていることを
前提に書いてるとしか思えません。

そのため、「デザインパターンとは、オブジェクト指向分析設計だけでは抽出できない、プログラムを機能させるための抽象的なオブジェクトの抽出の指針となり、かつ、オブジェクト指向プログラミングという、手続き型とはパラダイムが異なるプログラミングモデルで最も難しい、オブジェクトの粒度や関連などを決めて抽出するという作業の指針になるパターンカタログである」点の重要度がぼけている気がします。

この「パラダイムが異なる」という点がわかりづらいためか、この本を元にしているらしい、他の本では色々前提知識がなくても理解しやすい「特定の問題を解決する」というところにばかり焦点が当てられていて、まるで手続き型プログラムの山のごく一部をデザインパターンで置き換えるために使う的な風に思われている気がします。

デザインパターンの例が適切でない気がする

OOPでオブジェクトを抽出する上で、よくあるパターンのカタログ集」のはずなのに、何故かデザインパターンの例があまりにも具体的かつ、GUIプログラミングに寄っていて、抽象的で再利用可能なデザインパターンの例に見えない。Flyweightとか、Bridgeとか、非常に良くある設計パターンのはずのに、例のせいでむしろわかりづらくなっている気がする。どうせ書くなら、同じパターンを領域の異なるプログラミングに適用できることを例で示すべきだった。

POSAのデザインパターンと比べた場合、汎用的なところに寄り過ぎ

汎用的でどこでも使えそうなパターン達が紹介されている一方で、POSAにあるような特定の領域での問題を解決するパターンはほぼない(Interpreterだけ浮いてる気がする)

まとめ

この本からいきなり入っても理解するのが難しいので、事前にOOPオブジェクト指向設計についてある程度知識をつけた上で読むことが前提ではあるものの、記述が簡潔でわかりやすく、マストバイな本です。特にJavaや.NETなどのライブラリではこの本に書かれたパターンがありとあらゆるところで頻出するし、本格的なプログラムを作るときには、この本のパターンたちが(意識せずとも、似たようなことを考えるはずなので)大活躍すると思われます。

個人的には、この本を読む前に「The Art and Science of Smalltalk」を一読して、オブジェクト指向プログラミングのなんたるかをしっかり頭に入れて、「Head First Object-Oriented Analysis and Design」などのオブジェクト指向分析設計をかる〜く扱った本で、オブジェクト指向プログラミングがどれだけ難しいのかを「体感」してからこの本に進むべきかなと思います。(「Head First Object-Oriented Analysis and Design」の後半の練習問題とか、デザインパターンのような体系だった考え方が身についてないとまともに解けないのでは・・・)

2012年中に読んだ技術書のまとめ

2012年中に読んでためになった技術書をまとめてみました。一応、順番はおおまかな重要度(お役たち度)のつもりです。

OOP/OOD

The Art and Science of Smalltalk


Smalltalkだけでなく、オブジェクト指向プログラミング全般について解説しています。Smalltalkに興味が無くとも、MVCオブジェクト指向プログラミングに関する記述は一見の価値があります。別に記事を作成しています。
The Art and Science of Smalltalkでオブジェクト指向を理解する - zyake_mk2の日記

Head First Object-Oriented Analysis and Design



オブジェクト指向分析設計、開発のやり方を、実際に手を動かしながら学べるオライリーのシリーズものです。ページ数の割に絵が多く文字数が少ないですが、わかりやすく、絵や派手な文字、大量の練習問題で基本を徹底的に脳みそに刷り込むのには適していると思います。ただし、「基本を徹底的に脳みそに刷り込む」ことに特化しているので、ページ数の割に情報が少なく、幅はあってもそこまで深いわけではなく、他の本に進む前のウォーミングアップ用といった印象です
(まだ先に進めていないですが・・・)

Pattern Oriented Software Architecture Volume2



汎用的なパターンについて扱ったPOSA Vol1に対し、主に並行性、分散処理のパターンについて詳細に扱っています。情報量は圧倒的で、各パターンの解説もさることながら、各パターンのバリエーション、実装のポイント、各パターン同士の関連、パターンを組み合わせた「パターン言語」などなど、「そこまでするか!」ってレベルでぎっちり記述されてます。また、本編中にもあるように各パターンはどれも汎用性がそこそこ高いので、知っていると「あのライブラリ/APIはこういう考え方に基づいて作られていたのか!」というのがわかって、ちゃんと正しい使い方を考えられたり、「ここぞ」という時にパターンの考え方を適用して問題解決に役立てられるのでお勧めです(実際、今やってるテストケース作成でも、Active Objectパターンの考え方を上手く使って、テストの実行時間を削減できました)ただ、Vol1の時もその傾向があったのですが、Vol2はVol1にも増して1パターンに色々詰め込み過ぎです。ものにもよりますが、1パターンがあまりにも巨大でかつ、他のパターンと関連していたりして全体像がつかみにくいし、パターンのバリエーションでは、「そもそもこのパターンは何の問題を解決してくれるの?」というところすらぶれていることがあるので、読んでいて混乱するかもしれません。
(使えるという意味での重要度では、Smalltalk本のほうが上だと思いますが、個人的には物凄く好きです)

Database

Beginning Database Design



データベース設計の入門書です。データベース、関係代数の基本から、設計の手法、設計パターンから、仮想プロジェクトで実際にDB設計をしてみる、プロジェクトでの立ち回り方(!!!)など、内容のバラエティーは豊かで、かつ大量の練習問題があってとてもためになりました。ただ、本編中にも「DB設計に正解は無いから、他のDB設計の本も読んだ方が良い」と書かれているとおり、この本の知識だけでDB設計するのは難しい気がします。(実際はどうやって設計してるんだろう・・・)

The Art Of SQL



RDBMS製品の使い方や、SQLの構文を知っているレベルから一歩先に進んだ、RDBMSを扱うときのセオリーを具体例を交えながら解説している濃い書籍です。1節ごとが短く、具体的なエピソードを元にセオリーを解説し、最後にまとめが書いてあるスタイルなので印象に残りやすいです(進捗度70%くらい。だんだん内容が高度というか、複雑なRDBMSの機能の使い方になって興味が薄れてきたのと、自分の英語力ではちょっと辛いorz)

SEのためのOracleチューニングハンドブック



チューニングハンドブックといいつつ、実際はRDBMSを扱うための知識全般について、非常に幅広く簡潔に扱った良書です。カバー範囲が非常に広く、Oracleの仕組みから設計、
保守運用までカバーしているので、一読するとDBを扱う時に考える必要のあることを網羅できる気がします。

Java Transaction Design Strategies

リンク


Javaトランザクションを扱うときの知識やパターンについて解説したWeb上の無料の書籍です。ACID特性やJTA,JTSから、JDBCを生で扱うときのポイント、EJBやSpringでのトランザクションの扱い方、トランザクション境界に関するパターンなどがわかりやすく解説されています。(さりげなくSpringの公式ドキュメントからもリンクが張られていたりします)

Head First SQL



オライリーのHead FirstシリーズのSQL版です。「Head First Design Pattern」「Head First Object-Oriented Analysis and Design」よりも切れが悪いというか、内容の踏み込みが足りず、浅いところでHead Firstシリーズのテンプレートを使っているだけな雰囲気がしますが、「SQLをわかりやすく、お手軽に再入門」するには良い本だと思います。

SQL and Relational Theory: How to Write Accurate SQL Code



DB2の中の人がSQLとRelational Modelについてねちっこく、どこまでも深く解説した本です。重要度がめちゃめちゃ高いのはわかるのですが、自分には色々難しすぎて、途中で挫折しましたorz

その他

The Art of Unit Testing: With Examples in .net



ユニットテスト全般について扱ったわかりやすい本です。ユニットテストを作るときのテクニック、考え方についてわかりやすく解説しています。別に記事を書いてます。
「The Art of Unit Testing with Examples in .NET」を読んでみた - zyake_mk2の日記

ソート対象が動的に変わる場合PriorityQueueが期待通りに動作しない


Javaアルゴリズムの練習用プログラムを作成したところ、PriorityQueueが期待どおりに動作せず、盛大にハマってしまったので、自分用のメモを残しておきます。


状況


以下のようにキューからオブジェクトを取り出すごとに、キュー内オブジェクトの
ソートに使う値が動的に変わるプログラムを作成していました。

package my.algorithm.prim;

import my.algorithm.Vertex;
import my.algorithm.VertexConnection;

import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;

/**
 * {@link PriorityQueue}って、実はpoll対象の要素はソート対象から除外されてるのね・・・。
 * つまり、動的にソートに使用するキーが変わるようなオブジェクトの管理には向いていないっぽい。
 */
public class InvalidPrim {

    private static final Comparator<Vertex> VERTEX_COMPARATOR = new Comparator<Vertex>() {
        @Override
        public int compare(Vertex o1, Vertex o2) {
            System.out.println("compare: " + o1 + ", " + o2);
            return o1.getDistance() - o2.getDistance();
        }
    };

    void calculate(List<Vertex> vertices) {
        System.out.println("creation start");
        PriorityQueue<Vertex> unvisitVertices = new PriorityQueue<>(vertices.size(), VERTEX_COMPARATOR);
        for ( Vertex vertex : vertices ) {
            unvisitVertices.add(vertex);
        }
        System.out.println(unvisitVertices);

        System.out.println("iteration start");
        while ( ! unvisitVertices.isEmpty() ) {
            System.out.println("iteration...");
            System.out.println(unvisitVertices);

            Vertex target = unvisitVertices.poll();
            for (VertexConnection connection : target.getConnections() ) {
                Vertex toVertex = connection.getToVertex();
                boolean isAlreadyVisited = ! unvisitVertices.contains(toVertex);
                if ( isAlreadyVisited ) {
                    continue;
                }

                boolean smallerWeightFound = connection.getWeight() < toVertex.getDistance();
                if ( smallerWeightFound ) {
                    toVertex.setDistance(connection.getWeight());
                    toVertex.setPrev(target.getNumber());
                }
            }
        }
    }
}


しかし、実際に上記のプログラムを動かした時に表示されるprintlnの結果は以下のとおりでした。


creation start
compare: {number=1, distance=2147483647, prev=-1}, {number=0, distance=0, prev=-1}
compare: {number=2, distance=2147483647, prev=-1}, {number=0, distance=0, prev=-1}
compare: {number=3, distance=2147483647, prev=-1}, {number=1, distance=2147483647, prev=-1}
compare: {number=4, distance=2147483647, prev=-1}, {number=1, distance=2147483647, prev=-1}
[{number=0, distance=0, prev=-1}, {number=1, distance=2147483647, prev=-1}, {number=2, distance=2147483647, prev=-1}, {number=3, distance=2147483647, prev=-1}, {number=4, distance=2147483647, prev=-1}]
iteration start
iteration...
[{number=0, distance=0, prev=-1}, {number=1, distance=2147483647, prev=-1}, {number=2, distance=2147483647, prev=-1}, {number=3, distance=2147483647, prev=-1}, {number=4, distance=2147483647, prev=-1}]
compare: {number=1, distance=2147483647, prev=-1}, {number=2, distance=2147483647, prev=-1}
compare: {number=4, distance=2147483647, prev=-1}, {number=1, distance=2147483647, prev=-1}
iteration...
[{number=4, distance=4, prev=0}, {number=1, distance=2, prev=0}, {number=2, distance=2147483647, prev=-1}, {number=3, distance=8, prev=0}]
compare: {number=1, distance=2, prev=0}, {number=2, distance=2147483647, prev=-1}
compare: {number=3, distance=8, prev=0}, {number=1, distance=2, prev=0}
iteration...
[{number=1, distance=2, prev=0}, {number=3, distance=7, prev=4}, {number=2, distance=1, prev=4}]
compare: {number=2, distance=1, prev=4}, {number=3, distance=7, prev=4}
iteration...
[{number=2, distance=1, prev=4}, {number=3, distance=7, prev=4}]
iteration...
[{number=3, distance=5, prev=2}]

解説


上記の例では、「iteration...」の行が、pollの直前のキューの状態であり、その後の「compare: ...」の行が、pollした時にComparatorが出力するログになります。ログの内容を見ればわかりますが、pollされる先頭のオブジェクトはソート対象になっておらず、pollされた後のキュー内部のオブジェクトしかソートしないようです。ソートに使う項目が静的という過程ならば、上記の動作でソート回数を減らせますが、ソートに使う項目が動的に変わるとなると、先頭のオブジェクトをソートに使わない上記の動きには困ってしまいますね・・・。

参考情報


github上に上記のソースがおいてあります。

zyake/algorithm github