ノータブルコード4 - NULLよりも名前付きの番兵オブジェクト - 2020-03-03 - ククログ

ククログ

株式会社クリアコード > ククログ > ノータブルコード4 - NULLよりも名前付きの番兵オブジェクト

ノータブルコード4 - NULLよりも名前付きの番兵オブジェクト

MroongaというMySQLのストレージエンジンを開発している須藤です。MySQLのAPIはよく変わるのでMroongaの開発をしているとMySQLのソースコードを読む機会がよくあります。今日、MySQLのコードを読んでいて「お!」と思うコードがあったので4回目のノータブルコードとして紹介します。

MySQLは基本的なデータ構造も独自に実装していることが多いです。今日紹介するListも独自に実装しています。

多くの場合、リストは次のように「要素データへのポインタ」と「次の要素へのポインタ」を持つ構造をつなげて実装します。

struct List {
  void *data;
  List *next;
};

そして、リストの終端にNULLを置いてリストの終わりを表現します。

if (list->next) {
  printf("have more elements\n");
} else {
  printf("no more elements\n");
}

MySQLのリストの実装はNULLではなくリストの終端を示す番兵オブジェクトを使っていました。

extern MYSQL_PLUGIN_IMPORT list_node end_of_list;

class base_list {
  inline void empty() {
    elements = 0;
    first = &end_of_list;
    last = &first;
  }
};

私が「お!」と思ったのはGDBでデバッグしていたときです。GDBではpで出力したアドレスが既知のグローバル変数や関数などの場合はその名前も出力してくれます。ここでend_of_listという名前が出てきたのです。

(gdb) p (((const Item_cond *)select_lex->where_cond())->argument_list()->first->next->next
$1 = (list_node *) 0x555557f77550 <end_of_list>
(gdb) p (list_node *)0x555557f77550
$2 = (list_node *) 0x555557f77550 <end_of_list>

->nextとしたらNULLが返ってきても「あぁ、ここでリストは終わりなんだな」ということはわかるのですが、end_of_listという名前が見えてもたしかにリストが終わりだとことがわかるなと思いました。リストのときはNULLで十分だとは思いますが、もう少し複雑なもののときはNULLよりもなにか名前が付いた番兵オブジェクトを使うとデバッグが捗るときがあるんじゃないかと思いました。このテクニックを使う機会を見つけることが楽しみです。

今回はMySQLのリスト実装のコードで「お!」と思った名前付きの番兵オブジェクトを紹介しました。みなさんもNULLではなく名前付きの番兵オブジェクトを使った方がよさそうなケースがないか考えてみてください。

ところで、そろそろみなさんも自分が「お!」と思ったコードを「ノータブルコード」として紹介してみたくなってきませんか?ということで、このブログへの寄稿も受け付けることにしました。まだ仕組みは整えていないのですが、とりあえず、 https://gitlab.com/clear-code/blog/issues にMarkdownっぽいマークアップで書いた原稿を投稿してもらえばいい感じに調整してここに載せます。寄稿したいという人がたくさんいるならもう少しちゃんとした仕組みを整えようと思っていますので、興味のある人はご連絡ください。寄稿してもらった記事の著作者は作者本人のままですが、ライセンスはCC BY-SA 4.0GFDL(バージョンなし、変更不可部分なし、表表紙テキストなし、裏表紙テキストなし)のデュアルライセンスにしてください。参考:ククログのライセンス

それでは、次のノータブルコードをお楽しみに!