ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

【告知】 来週土曜日 「京都 Android 勉強会 2014.08」 開催 & Gradle のことを話します

来週土曜日 「京都 Android 勉強会 2014.08」 開催

来週土曜日 8 月 23 日の午後 3 時から 「京都 Android 勉強会 2014.08」 が開催されます! 株式会社はてな主催です。 タイトル通り Android アプリ開発に関する勉強会です。

きしださんがいらっしゃいますし、Android アプリ開発に関する実践的な話もいくつもありますので、興味深い勉強会になると思います! 関西圏で Android アプリ開発をしている方は是非いらしてください!

Gradle のことを話します

私も Gradle や Android Gradle plugin などの話をする予定です!

先日 beta 版がリリースされた Android Studio では、ビルドシステムとして Gradle が採用されています。 Android アプリ開発でも Gradle を触る機会が増えた今、Gradle に関する知識はある程度持っておく必要があります。 「Gradle のことはよくわかんないけど、Android Studio が自動生成してくれるビルドスクリプトにちょっと追記して使ってるよー」 という人向けの入門的な話から、「Gradle のことはそこそこわかってるけど、そろそろ自分でプラグイン書いたりしたいなー」 といった人向けのプラグインの作成周りなどの話まで、ある程度広い範囲の話をしようと思っています!

再度になりますが、是非是非いらしてくださいっ!

読んだ: アジャイル開発とスクラム 顧客・技術・経営をつなぐ協調的ソフトウェア開発マネジメント

開発手法としてスクラムを取り入れているチームに所属しているが、アジャイルスクラムといった手法についてあまり知識を持っていないソフトウェアエンジニア、という立場で本書を読んだ。 本書のカバー袖には 『企業の経営層に向けてソフトウェア開発手法の 「アジャイル」 とその手法の一つである 「スクラム」 を体系的に解説する』 とあるのだが、経営層に限らず、アジャイル的な開発手法を採用して開発プロセスを改善していこうとする人であれば、誰にとっても有益だと思う。

アジャイル開発については、ウォーターフォールとの比較として 「小さなサイクルを回して変化に柔軟に対応しながら開発を進める」 という程度の理解しかなかったので、本書を読んで 「人が知識を運ぶ」 とか 「人と人のコミュニケーションで知識を伝える」、「顧客と協調して開発を進める」 といった、どちらかというと社会的な活動やその意義についての部分が非常に参考になった。

アジャイル開発とスクラム 顧客・技術・経営をつなぐ協調的ソフトウェア開発マネジメント

アジャイル開発とスクラム 顧客・技術・経営をつなぐ協調的ソフトウェア開発マネジメント

本書は 3 部構成になっている。 第 1 部 「アジャイル開発とは何か、スクラムとは何か」 では、ソフトウェア開発手法であるアジャイル開発について、どういうものなのか、なぜそれが必要とされたのか、といったことが説明される。 そして、アジャイル開発の枠組として、スクラムについても詳しく説明される。

アジャイル開発については、「ウォーターフォールのように要件定義や設計、実装という各作業で開発プロセスを分断するのではなく、小さなサイクルを回して完成を目指す」 (すなわち、包括的なドキュメントより動くソフトウェアを重視し、計画に従うだけでなく変化に柔軟に対応していくことを重視する) というものだと思っていたのだけれど、それだけでなく、「個人と対話」 や 「顧客との協調」 といったことにも価値を置く価値観が根底にある、ということを知れたのが良かった。 この価値観は、「アジャイル宣言」 に述べられている。

また、朝会 (デイリースクラム) やプランニングポーカー、アジャイル開発の各種プラクティスについても説明される。 プラクティスとしてはアジャイルの右翼 (開発環境) に属するものと左翼 (チーム環境) に属するものがあり、それらをうまく組み合わせてアジャイル開発の目的である 「ビジネス価値」、「顧客満足」、「市場創造」 といったことを達成する。 ここら辺のプラクティスについては、軽く紹介されるだけという感じなので、実際に現場で実践するのであれば詳細は別の書籍などで学ぶと良いと思う。 次のようなスライドもある。

2 部では、実際にアジャイル開発を導入した国内の 3 社 (リクルート楽天富士通) の事例が紹介される。

3 部では、現在のアジャイル開発では明示的に言及されないような、企業経営とリーダーシップの側面から、アジャイル開発の考察がなされる。

個人的に気になった内容

アジャイルの各種プラクティス

プランニングポーカーは 1 回やったことがあるけど、ちゃんとしたやり方を知らなかったので 「なるほどー」 という感じで読んだ。 他のプラクティスについては大体知ってたけれど、いくつか新しい発見があった。

  • プランニングポーカー
    • 最初にベースラインを決める。 メンバー全員が知っているあまり大きくないタスクを選ぶ。 → こないだプランニングポーカーやったとき、最初のタスクは適当に数字を出してて 「こんなんでいいのかなー」 と思ったりしてた。
    • 見解は一番大きい数字と小さい数字の人が言う。 → 数字が合わなかったら全員が言うものだと思ってたけど、確かにそれだと時間かかりすぎるし、最大と最小の人が言えば良さそう。
    • 3 回で切り上げ。 → まあそんなものか。
  • 朝会でプロジェクトの外部の人の発言するタイミングを制限する。 → 外部の人が、自分がリスクを取るわけでもないのに気軽に口出しする、というのを防ぐ意味。
    • プロジェクト内の人をブタ、外部の人をニワトリと呼ぶことがある話。 ハムエッグを作るのにブタは自分を生命をかけるが、ニワトリは自身の生命に関わらない貢献の仕方をする。
    • ブタとニワトリの話、会社の人もしてた。
  • タスクかんばんのタスクは 2、3 時間程度で終わる粒度が良い。
    • 今のプロジェクトでもタスク粒度には悩んでる。
    • タスクが動くことで進捗状況の共有。 さらに達成感にもつながる。 1 日で動くようなタスク粒度にすべきとのこと。
  • バーンダウンチャート
    • 進捗状況の確認のための質問は 「完了までにあと何ポイント (理想時間) 必要か」 にする。 「何パーセント完了したか」 や 「残り何パーセントか」 ではない。
    • 作業が進むにつれて、見積もりよりも実際に必要な作業が多いことがわかったりするので、残り作業時間を把握すべき。
  • スプリントで完了できたポイント数をベロシティとして、スプリントあたりに進めることができるタスク量の目安とする。
    • 工数をポイントで見積もった場合に、実時間とどう変換するのがいいんだろうなーと思っていたけれど、実時間と変換するよりはスプリントあたりに進めることができるポイント数を把握してれば良い、という感じか。
  • スプリントの成果物はリリース判断可能なもの。
  • ユーザーストーリーには詳細な仕様は書かない。
    • あえてコミュニケーションを発生させる意図がある。
    • これに限らず、アジャイル開発では文書などで伝えられる 「形式知」 だけでなく、「暗黙知」 というところにも焦点を当てている。 人と人とのかかわりで伝えられる知識。
  • ペアプログラミング
    • 15 分おきにぐらいでペアを交代する。 開発のメリハリやリズム。 → 15 分がいいのかどうかわからないけど、まあそれぐらいかなーという気はする。
    • リスクが大きい作業や、クリエイティブな作業はペアで行った方が効率的。 → 設計とかも、設計をきっちり書いてレビューしてもらって大きな直しが発生する、というような状況になるぐらいなら最初からペアでやった方が良さそう。

事例

各社、それぞれ課題があったり良い取り組むをしていたりして興味深い。 他社がやってるからといって表面的に真似ても意味はないけど、どういう考えで各取り組みをしたのかが書かれているので、そこら辺がだいぶ参考になる。

リクルート
  • バーンダウンチャートに上限線を引く。
    • 予めバッファを持たせて、上限線を引いておく。 実績線が上限線を超えそうになったら要件の調整を行う。
    • 上限線を引いておくことで、要件の調整に対して事業部側の理解を得やすい。
  • 出世魚型のドキュメント。
    • ドキュメントは開発フェーズをまたいで使いまわし、更新していく。
    • ドキュメント作成の工数削減と、ドキュメントが分散して齟齬が発生することを防ぐ。
    • 言葉で聞いたら、さもありなん、という気はするけど、実際のところドキュメントどうするかって結構難しい問題ではある。
  • 最初はワンチームマインドの醸成に苦戦した。
    • 見積もりのずれに対する認識。 事業部側は見積もりは初期から変わらないという認識。
    • 意識の変革と共有。 地道な啓蒙や説得。
  • 会議からの持ち帰りの禁止。
    • 「持ち帰って検討」 が開発スピードを遅らせる。
    • 持ち帰って 100 % の精度で回答するのではなく、80 % の精度でいいのでその場で回答する。
    • 残り 20 % に起因する手戻りが発生しても、お互いに怒らないように。
    • 精度を求めすぎて時間がかかる、というのは避けるように自分も意識してはいるけど、それでも時間をかけて検討することは結構多いので、もうちょっとスピード重視に振ってもいいかもなーとか思ったり。
楽天
  • 割り込み作業が多いという問題。
    • スクラムマスター経由で依頼してもらうようにして、優先度などをスクラムマスターが調整。
    • こういうのはスクラムマスターの仕事として重要なものの一つなのだなー、と今のプロジェクトでも感じてる。
  • 新撰組の旗を立ててチームの共通認識にする。 目に見える形になっていることの重要性。
    • 「俺たち新撰組みたいだよな」 というような話をチームでしていて、そこから旗を立てたらしい。
    • こういう、チームの結束を高めるための取り組みの事例はいろいろ聞くけど、じゃあ自分のところは何かできるか、っていうと難しいよね。 旗立てればいいってものでもないし。
  • 横やり作業もタスク化する。
    • 必ずしもそれがいいかどうかはわからないけど、自分が何しているのか共有するためにプロジェクト外のことをタスクかんばんに乗せるのは一つの手ではあるなー。
富士通
  • チーム内は完全ペア作業。 教育効果。
    • 人数が多く人の出入りも激しいので、教育効果の高いことをする必要がある、という感じみたい。
    • ある程度少人数で固定のメンバーでやるなら、いい感じのところでペア作業すれば良さそう。
  • チーム間の Try 共有。
    • 振り返りで出てきた Try をチーム間で共有することで、チームとしての成長を共有する。
    • こういう取り組みはいいなーと思った。
  • 文書で伝えたつもりが伝わってないということもある。 文書ではなく人が情報を運ぶという意識。
    • 後でも出てくるけど、こういう 「暗黙知」 も重視する姿勢がアジャイルっぽい感じだなーと思った。

アジャイル開発とスクラム

アジャイル開発で重要そうなトピック。

  • 多層学習と多能力学習。
    • 個人、チーム、部、会社、という様々な層で学習が起こる。
    • チーム内にエンジニアやデザイナ、営業、といった様々な専門スキルを持つ人間がいるので、自分の専門外のことも学習する。
  • 暗黙知形式知、両方の形式が重要。
    • SECI モデル。 暗黙知形式知にする (文書化) ことで複数形式知をまとめたりできるし、さらにそうしてできた形式知暗黙知として人が取り込む、みたいな感じのモデル。
    • 自転車に乗る乗り方、みたいな体でわかることが暗黙知
    • 暗黙知は人と人が直接やり取りすることで伝えられる。 アジャイル開発ではこういう人と人のやり取りが重要視されていると感じる。
  • 実践知リーダー。
  • PDCA (計画、実行、検査、適応) サイクルの前に共同化。
    • 計画は形式知からくるもの。 イノベーションにはもっと主観的な動機が伴っているはず。 それを共同化 (チームメンバーとの共有) する。
    • 何を作るか、ではなく、なぜ作るか、という思い。
    • 合宿の意義もここにある。

アジャイル開発とスクラム 顧客・技術・経営をつなぐ協調的ソフトウェア開発マネジメント

アジャイル開発とスクラム 顧客・技術・経営をつなぐ協調的ソフトウェア開発マネジメント

OnEditorActionListener を使って EditText への Enter キー入力やアクション入力をハンドルする

EditText への Enter キー入力を検知して何か処理をしたい、ということを調べてみると、TextView.OnEditorActionListenerTextView#setOnEditorActionListener メソッド で設定すればよいというようなブログ記事がいくつか見つかる。

editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        // ... 処理 ...
        return false;
    }
});

ただ、ここら辺の記事を読んでも (一番下の記事以外は) onEditorAction メソッドの第 2 引数 actionId が何であるかや、第 3 引数 eventnull になりうることについての言及がなかったりして情報として不十分だったので、調べたことを書き残しておく。

TextView#setOnEditorActionListener メソッドとは

Javadoc には次のように書かれている。

Set a special listener to be called when an action is performed on the text view. This will be called when the enter key is pressed, or when an action supplied to the IME is selected by the user.

TextView | Android Developers

すなわち、Enter キーが入力されたときや IME に提供されているアクションが選択されたときに呼ばれるコールバック処理を設定するものである。 アクションについては後述する。 コールバック処理は TextView.OnEditorActionListener#onEditorAction(TextView v, int actionId, KeyEvent event) メソッド として記述される。

引数の actionId は、選択されたアクションを識別するための ID である。 Enter キー入力の場合は EditorInfo.IME_NULL になる。

第 3 引数 event には、Enter キー入力の場合にのみ null でない値が渡される。

また、Enter キー入力の場合には、キーダウン時とキーアップ時の 2 回 onEditorAction メソッドが呼ばれるようである。

アクションとは

IME に提供されるアクションについては、次のドキュメントに書かれている。

EditText複数行を受け付けない場合に、多くのソフトウェアキーボードでは Enter キーの代わりにアクションボタンが表示されるようである。 デフォルトでは 「Next」 や 「Done」 が表示される。 EditText 要素の android:imeOptions 属性を使って、「Next」 や 「Done」 ではなく 「Go」 や検索ボタンを表示させることもできる。

上で説明した TextView#setOnEditorActionListener メソッドを使うことで、次のような感じでアクションをハンドルできる。

editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        boolean handled = false;
        if (actionId == EditorInfo.IME_ACTION_DONE) {
            // ... なんかの処理 ...
            handled = true;
        }
        return handled; // このメソッド中でアクションを消化したら true を返す。
    }
});

IME については詳しくないのでわからないのだけれど、『Most soft input methods provide a user action button in the bottom corner』 って書かれているので、おそらく IME の実装次第ではアクションボタンが提供されないこともある気がする。

あと、当然ながらハードウェアキーボードしかない場合はユーザーがアクションを実行することはできない。

OnEditorActionListener#onEditorAction メソッドについてのプラクティス

  • Enter キー入力以外では、第 3 引数 eventnull になるので、気を付ける必要がある。
    • アプリケーション側でアクションを指定していなくても (例えば android:imeOptions="actionNone" を指定していても)、IME の実装によっては勝手にアクションをユーザーに提供することもある *1 ので、eventnull になり得ないつもりでコードを書いてはいけない。
  • ソフトウェアキーボードの Enter キー入力では OnEditorActionListener#onEditorAction メソッドが呼ばれないことがある。
  • 結論として、「EditText での Enter 入力時に (改行させずに) 何か処理をするようにしたい」 という場合、次のようにすべきだと思われる。 *3
    • EditText 要素の android:inputType 属性を設定し、複数行入力をできないようにする。
    • EditText 要素の android:imeOptions 属性に actionNone 以外の値を設定し、IME にアクションを提供する。 (あるいは独自のアクションを指定するとか。)
    • onEditorAction メソッドでは、アクションを受け取った場合の処理 (ソフトウェアキーボード用) と Enter キー入力を受け取った場合 (ハードウェアキーボード用) の両方の処理を書いておく。
      • このとき、Enter キー入力については onEditorAction メソッドが 2 回 (action=ACTION_DOWN と action=ACTION_UP) 呼ばれる可能性を考慮してコードを書いた方が良さそう。 (どういう条件でそうなるかはわかってないけど、1 回しか呼ばれないこともあれば 2 回呼ばれることもあるっぽい。)
    • IME の実装次第ではアクションボタンが表示されず、Enter キー入力では onEditorAction メソッドが呼ばれないということもありうると思うので、onEditorAction メソッドが呼ばれなくても次に進むための方法をユーザーに与えておくべき。 (「検索」 ボタンを配置しておく、とか。)

挙動については確証がない部分もあるけど、上のような感じで実装すれば問題はないはず。

Android Pattern Cookbook マーケットで埋もれないための差別化戦略

Android Pattern Cookbook マーケットで埋もれないための差別化戦略

*1:Nexus 7 (2013 年版) の 「英語 (米国) Google キーボード」 で確認した。

*2:Nexus 7 (2013 年版) の 「英語 (米国) Google キーボード」 を使っている場合、Enter キー入力ではコールバックメソッドが呼ばれないことを確認した。

*3:以下ではレイアウト XML 中に属性として記述する方法を書いているが、Java 上で同様のことをするようにしても良い。

「うらがみが Java まわりの ORM を知りたい会」 に参加してきた

Java の O/R マッパーまわりの話を知りたかったので、6/14 に行われた勉強会 「うらがみが Java まわりの ORM を知りたい会」 に参加してきました。 会場は和室でした。

Java まわりの O/R マッパー、あんまり詳しくないのでいろいろ知れて良かったです。 メモを残しておきます。

発表内容

Java の ORM、Doma の話 +α (@backpaper0 さん)

いろんな O/R マッパーについての簡単な紹介と、Doma の紹介。

  • 紹介された O/R マッパーのうち、使うとしたら JPA か Iciql か Doma かなーという気持ちになった。 (個人の感想です。)
    • ちなみに紹介されてる O/R マッパーのうち私がちゃんと知ってるのは JPA だけ。
  • Iciql と H2 Database を組み合わせて Android アプリで使うことができる (実際に製品開発に用いた) とのこと。
    • H2 Database は Android 用のビルド (?) があるらしい。
    • Java DB (Derby) を Android アプリで使おうとして挫折したことがあるので、今度は H2 Database を試してみたい。
Doma について
  • 公式サイト: Welcome to Doma — Doma 2.0 ドキュメント
  • 2 系は Java 8 以降。 1 系は Java 7 までらしい。
  • Doma、なんのライブラリにも依存してないらしい。
  • Pluggable Annotation Processing API を使ってる。
    • その仕組み上他の言語で使えない。
  • 原則としてクエリは SQL ファイルに書かないといけない。 (クエリビルダもあるが使わない方が良いらしい。)
    • SQL には if とか書ける。 ほぼ Java のコードを書けるっぽい。
  • コンパイル時にいろいろ検出。 (対応する SQL ファイルがなかったり中身が空だったり、アノテーションがなかったりすると)
  • DAO の引数や戻り値、エンティティのプロパティ (?) などにドメインクラスを使用できる。 (良い!!!)
  • 自動生成されるのはエンティティの補助クラスと DAO の実装クラスと、ドメインクラスの補助クラス。
議論
  • SQL で書くか Criteria API か?
    • Criteria API の方が IDE の補助があったりするけど、コードが膨らんだりするし、Doma だとコンパイル時に検証してくれたりするし SQL が良いと思ってる。
    • みたいな議論もあった。

F 社乙女チームの ORM (黒) 歴史 (@daiksy さん)

  • Scala でサーバーサイドを書くにあたっての O/R マッパー選択の歴史。
  • Play framework。
  • 今は Slick か ScalikeJDBC が良さそうだけど、昔は悩ましかった。
  • 最初: Squeryl
    • Implicit conversion を駆使するから IDE の補完が微妙だったりしてしっくりこなかったらしい。
  • 2 個目: ScalaQuery (のちの Slick)。
    • 使いやすいし、後々デファクトスタンダードになるのは理解できる。
    • Scala 2.9 → 2.10 のバージョンアップ時に Slick と名を変えて 2.9 系は切り捨てられた。
    • ScalaQuery を使っていた web アプリケーションはあえなくレガシー化...。
    • Scala はバイナリ互換性がないのがつらいよね。
  • 最後: MapperDao を採用。 (現在も。)
    • Squeryl, Slick, Activate, Circumflex-ORM, MapperDao, SORM, Scala ActiveRecord などを検討して、結果的に MapperDao。
    • DSL が結構良い。 普通の SQL っぽい感じで書ける。
    • ドキュメントの量とかは少ないので、今からなら Slick とか ScalikeJDBC のが良さそうな気がする。

Scala 周りの文化は全然知らないので、そんな感じなのかーと思いながら聞いてた。 Scala 便利だけど互換性とか大変そう。

JOOQ の紹介 (@chipstar_light さん)

  • 使ったことないけど紹介。
  • O/R マッパーというより DB アクセスライブラリ。
  • テーブルから Java コードを生成して、型安全な SQLJava 上で書ける、て感じ??
  • 既存の O/R マッパーでいい感じのがないけど JDBC をそのまま使うのも微妙、って感じの時に効果的に使えそう。

ORM 初心者が使おうとした (@KYON_MM さん)

3 つの O/R マッパー紹介
  • JOOQ
    • 機能的には使いやすい。 大体揃っているしユーザー数も多そう。
    • QueryDSL を駆逐してやるという勢いを感じる。
  • Iciql
    • とても薄いラッパー。 手軽で良さそう。
  • Slick
    • Play Framework のデフォルトになる予定。
    • 型型しすぎてる雰囲気。
      • Scalaz と同じ雰囲気。
    • ScalikeJDBC の方が好きな人が多いのでは?
議論的な話
  • ロックやリトライのサポートの話。
    • O/R マッパーでいい感じにサポートされているものは少ない。
    • ロックはともかくリトライは O/R マッパーがサポートすべきものではない気がするなーと思ったりした。
  • コネクションプールなどが O/R マッパーの内部で実装されていて不便なことが多い、とか。
    • テスト時にコネクションプールに手を入れられると便利。
    • BoneCP 使いたい、とか。
    • ScalikeJDBC では HikariCP が使えるようになった。 素晴らしい。

MyBatis (@s_kozake さん)

  • 大規模な案件に MyBatis で挑んだ。
  • MyBatis
    • 以前は iBatis という名前。
    • レガシーな環境、非正規化されたデータベース、SQL 文の実行を完全に制御したい場合によい選択肢となる。
    • 自動生成されるソースは?
  • MyBatis のラッパーをこざけさんが頑張って作っていい感じに使えるようになってた。 (すごい。)
  • Proxy クラス というのを初めて知った。
    • めっちゃ便利やん。

GORM めっさゆるい (@kazuhito_m さん)

  • リファレンス: 7 Object Relational Mapping (GORM) 2.4.0
  • Grails 用の O/R マッパー。
    • Grails とは独立させて使おうとすると大変っぽい?
  • GORM、Groovy らしさがあふれてるなーと思った。
  • ゆるい感じで使いたいならいいけど、まじめに大規模開発に使うと死にそう。

Unicode のサロゲートペアとは何か

こないだ同僚に Unicodeサロゲートペアについて説明する機会があって、それで Unicode の話をブログ記事に書きたくなったのでサロゲートペアについて書いておこうと思う。

この記事は Unicode Standard version 6.3.0 を見ながら書いた。

文字とコードポイント

抽象文字 (abstract character) を計算機上で扱うためには、符号化する必要がある。 Unicode では、文字の符号化のために使用できる整数の範囲を コード空間 (Codespace; 符号空間) と呼んでいる。 0 から 0x10FFFF がその範囲である。 そして、その空間に属する値を コードポイント (Code Point; 符号位置) と呼ぶ。

次の図は、抽象的な 「Å」 という文字と、対応する 符号化文字 (Encoded Character) を表現するコードポイントの関係を表すものである。 (Unicode Standard 6.2 より。) 下の図を見るとわかるように、1 つの抽象文字が複数の符号化文字に結び付けられることがある。 また、1 つの抽象文字が複数の符号化文字により構成されることもある。

f:id:nobuoka:20140604222944p:plain

Unicode コードポイントを参照する際は、「U+」 という接頭辞を付けて、16 進数表記の数字を続けて記述するのが Unicode Standard での表記法である。 また、符号化文字も単にコードポイントだけで参照することができる。

つまり、上の図における 00C5 という符号化文字を参照するために、「U+00C5」 という表記を使用できる。

なお、コードポイントは、必ずしも符号化文字に割り当てられているとは限らない。 (後で説明するが、サロゲートコードポイント (Surrogate Code Point) がその一例である。)

符号化文字と文字符号化形式

さて、上で述べたように Unicode 文字にはそれぞれコードポイントが与えられているわけであるが、そのコードポイントを計算機上でどのように表現するか、という意味でさらに符号化する必要がある。

Unicode Standard では、UTF-8UTF-16UTF-32 という 文字符号化形式 (Character Encoding Form) が提供されている。 それぞれ 8 ビット、16 ビット、32 ビットを 符号単位 (Code Unit) とする符号化方式である。

f:id:nobuoka:20140604234845p:plain

上の図は、いくつかのコードポイントが各文字符号化方式でどのように表現されるかを表した例である。 (Unicode Standard 6.2 より。)

任意のコードポイントは単一の 32 ビット符号単位で表現できるため、UTF-32 では常に 1 符号単位が 1 コードポイントを表す。 UTF-16 では、U+0000 から U+FFFF までのコードポイントは 1 符号単位で表現され、U+10000 以降のコードポイントは後述するサロゲートペアで表現される。 UTF-8 では、1 コードポイントを表現するために 1 個から 4 個の符号単位が使用される。

サロゲートペアについて

さて、いよいよ サロゲートペア (Surrogate Pair; 代用対) の説明を行う。 サロゲートペアとは、一言で言ってしまうと 16 ビット符号単位の組による単一の抽象文字の表現である。 UTF-16 でのみ用いられる。

UTF-16 は、16 ビットを符号単位とする文字符号化形式なので、任意のコードポイントを 1 符号単位で表現することができない。 16 ビットで表現可能な U+0000 から U+FFFF までのコードポイントについては、そのままコードポイントの数値を 16 ビットで表現するようになっている。 残りの U+10000 から U+10FFFF までのコードポイントは 16 ビットの符号単位の組で表現されるようになっていて、この組のことをサロゲートペアと呼ぶ。 例えば、先の図では U+10384 というコードポイントを表現するために、0xD800 と 0xDF84 の 2 つの符号単位の組が用いられていた。

上で 「U+0000 から U+FFFF までのコードポイントについては、コードポイントをそのまま 16 ビットで表現するようになっている」 と述べたが、それだとサロゲートペアのために使用できる符号単位がなくなってしまう。 そこで、Unicode では U+D800 から U+DFFF までのコードポイントをUnicode 文字に割り当てないようにし、0xD800 から 0xDFFF までの 16 ビット符号単位をサロゲートペアに使用できるようにしている。 これらのコードポイントはサロゲートコードポイントと呼ばれる。

つまり、より正確にいうと、UTF-16 では 「U+0000 から U+D7FF までと U+E000 から U+FFFF までのコードポイントについては 16 ビットの 1 符号単位であらわされ、U+10000 から U+10FFFF までのコードポイントは 2 つの符号単位の組で表現される」 ということになる。

文字符号化形式のためにコードポイントが使用されるのは奇妙な感じがするが、このような形になっているのは、もともと UTF-16 が固定長の文字符号化方式として設計されていたという歴史的な理由らしい。 (あんまり詳しくない。)

備考

U+0000 から U+FFFF までのコードポイント (文字符号化形式 UTF-16 において、単一の符号単位で表現できるコードポイント) は BMP コードポイント (BMP Code Point; BMP符号位置) と呼ばれる。 U+10000 から U+10FFFF までのコードポイントは 補助コードポイント (Supplementary Code Point; 補助符号位置) と呼ばれる。

ややこしいと思うこと

サロゲートペアはあくまで UTF-16 という文字符号化形式でのみ使用されるものであるが、UTF-16サロゲートペアが使用されるために U+D800 から U+DFFF のコードポイントがサロゲートコードポイントとして予約されていたりするあたりがややこしいと思う。 歴史的経緯...。

参考文献

ソフトウェア開発をするうえで最低限身につけておかなければならない文字エンコーディングに関する知識は次の書籍を読めば身につくと思う。 文字エンコーディング周りについて不安がある人は読むといい。

プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)

プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)