トップ » 技術記事 » オリジナル Wiki を作ってみよう!(5) - 編集の衝突を検出する

オリジナル Wiki を作ってみよう!(5) - 編集の衝突を検出する

タグ: PHP Wiki

クジラ飛行机です。ここ数回に渡り、PHP で Wiki を作る手順を解説しています。今回は、編集の衝突について考えてみたいと思います。多人数でサイトの編集を行えるのがWikiの魅力ですが、その代償として同じページを複数人で同時に編集してしまうという問題が生じます。その時にどのような処理を行えばよいのかを考えてみます。

前回までのおさらい

PHPを利用して、Wiki アプリケーションをゼロから開発しています。この連載の成果は、「KonaWiki 」のサイトで公開しています。Wiki製作記事の第1回で壮大なアイデアを語ってみたのですが、まだまだ、シンプルで必要最低限の機能しか備えていません。作ってみて思うのですが、多くの人に使ってもらえるレベルにまでブラッシュアップするのには時間がかかりますね。

編集の衝突

Wiki には多くの素晴らしい特徴があるのですが、その中でも、多人数で同時にサイトの更新を行うことができるというのが特に大きいです。しかし、同時に編集できるからこその問題も多くあります。特に問題となるのが「編集の衝突」です。これは、自分がページを編集している間に、他の人がページを編集してしまったときに起きるトラブルです。

もし、編集の衝突をチェックしないWikiだったなら大変なことになります。AさんとBさんが同じカレー屋の口コミページを編集した時のことを考えてみます。ことの顛末は次の通りです。

・Aさん:Wikiの「カレー屋」に関するページを見る
・Bさん:Aさんと時を同じくして「カレー屋」に関するページを見る
・Aさん:自分の好きなカレー屋が書かれていないので、ページに追加しようと思う。
・Bさん:Aさんと時を同じくして、好きなカレー屋をページに書こうと思う。
・Aさん:Wikiの編集ボタンを押して、カレー屋のページを編集する
・Bさん:Aさんと時を同じくして、Wikiの編集ボタンを押す
・Aさん:カレー屋の記事に「湘南カレー」に関する記事を追記して保存。
・Bさん:カレー屋の記事に「B級カレー」に関する記事を追記して保存。
・Aさん:おやっ?!湘南カレーの記事が消えている・・・

Aさんの編集中に、Bさんも編集を行ってしまい、Aさんの書いた記事を、Bさんが上書きしてしまっているのです。これでは、せっかく文章を書いたAさんの苦労が水の泡です。多くのWikiでは、この問題に対処するために、編集が衝突している旨を画面に表示します。

画面: PukiWiki で編集の衝突が起きた時

PukiWiki で編集の衝突が起きた時

編集が衝突するのを回避するには?

多人数が同時にサイトを更新できるのが Wiki のウリなのですが、編集の衝突は頭の痛い問題です。これを回避するために、ぱっと思いつくのは、誰かがページを編集しているときには、他の人が編集できないようにロックしてしまう方法です。しかし、ページのロックは別の問題も引き起こします。それは、編集を開始した人が、編集を途中でやめてしまった場合どうするのかということです。HTTP通信の特性では、その人が編集をしているのか、それとも編集をやめてしまったのかを検出する方法がありません。そのため、編集ボタンを押されたら5分以内に編集してもらうことにして、最大5分間、他の人の編集をロックするようになど工夫することになるのでしょうが、どう考えても現実的ではありません。

そこで、多くの Wiki で採用している方法は、同時に編集がなされた場合、テキストを比較して、その差分を取り、編集が衝突している部分を画面に出力する方法です。ちょうどバージョン管理ツールの Subversion で複数の人が1つのソースファイルを編集してしまったときに、編集箇所が衝突してなければ、自動的に追加部分を反映させ、衝突していたらエラーとなる感じです。Wikiでエラーはつまり編集のやり直しです。

具体的に編集が行われているか調べる簡単な方法

それでは、次に、編集が行われたかどうかを調べる方法について考えてみます。これは、自分が編集ボタンを押して編集を始めてから、編集を終えて書き込みを行うまでに、誰かが編集を行ったかどうかをチェックするのです。

この処理も、普通に考えてしまうと、編集ボタンが押されるたびに、そのクリックされたことを覚えておけば良い気がしますが、これではうまくいきません。編集ボタンが押されたことは、編集が行われることと関係がないからです。つまり、自分が編集ボタンを押してから、別の人が編集ボタンを押したとしても、どちらが先にページを更新するのか分かりませんし、編集ボタンを押しただけで、そのまま編集せずブラウザを閉じてしまう可能性もあります。

そこで、編集画面を表示するときに、どのテキストを編集したのかというタグを付加情報に与えておきます。そして、ページを更新するときに、このタグとデータベースにあるテキストのタグを比較して、一致しなければ、編集している間に他の人が編集してしまったということになります。

どのテキストを編集したのかというタグには、そのテキストが編集された日時でも良いですし、MD5などで、テキストのハッシュ値を計算して、それをタグにしても良いでしょう。KonaWiki では、MD5 のハッシュをタグとして渡すことにしています。(もちろん、日時でも良いのですが、何もテキストを変更せずに更新した場合も、テキストの比較をすることになってしまいます。)

Wiki で編集の衝突を検出する方法

テキストの差分を求める方法

テキストを比較して差分を求めるのは若干複雑です。テキスト比較のアルゴリズムがいろいろあります。そこで、PEARのテキスト比較ライブラリ「Text_Diff」を利用することもできます。

ただ、現時点のKonaWikiでは、単純に各行を比較してその差分を表示するようにしています。(将来的には、PEARの「Text_Diff」を利用したいと思っています。)

KonaWikiでのテキスト比較は次のような手順で行っています。

  • 1.元になるテキスト、新しいテキストを行ごとに区切る
  • 2.新しいテキストを以下のように一行ずつ調べる
  • 元のテキストと一致していれば次の行を調査
  • 一致していなければ、テキストが追加か削除されている可能性がある。
  • 元のテキストに新しいテキストの調査行があれば、そこまでのテキストが削除されている、そうでなければ、テキストが追加されている

編集差分のバックアップ

多くのWikiでは、誰かがページを更新したとしても、それ以前のテキスト内容をバックアップしておきます。こうすることで、いつでも元の状態に戻すことができるようになっています。また、いたずらなどでページが書き換えられてしまってもすぐに元に戻すことができます。安心してページを更新できるのです。

ただし、編集差分のバックアップは、頻繁に利用されるものではないので、データベースのメインテーブルに入れるのではなく専用にバックアップ用のテーブルを作って分けておくのが良いでしょう。

まとめ

今回は、Wikiを作る上で避けて通れない「編集の衝突」の問題を考えてみました。衝突の起きる仕組みと検出方法、そして、衝突した時のアクションをどうするかについて考えてみました。そういえば、直接衝突が起きるわけではありませんが、Wikipediaで編集合戦が行われているという話もよく聞きます。調べてみると、「編集合戦」という項目もあり、苦労の様子が伺えます。

今回で、Wikiを作る連載はひとまず終わろうと思いますが、「KonaWiki 」の開発は継続していく予定です。今後、面白い機能がつく度にご報告しようと思っていますのでお楽しみに。

Series Navigation«URLを工夫しよう

執筆者紹介

クジラ飛行机

クジラ飛行机

くじらはんど(http://kujirahand/)にて、日本語プログラミング言語「なでしこ」(IPA未踏ユース採択)、テキスト音楽「サクラ」(OSPオンラインソフト大賞入賞)など多くのオンラインソフトを開発。著書に「Flexプロフェッショナルガイド」「なでしこ公式バイブル」、「一週間でマスターするActionScript3.0」など。

TrackBack URL :