4 ポイント 投稿者 GN⁺ 2024-01-01 | 1件のコメント | WhatsAppで共有

偽のツリー: インデントを使ったシンプルなUI

  • UIでツリー形式の一覧が欲しいとき、親子関係を実装するには多くの作業と複雑なデータ構造が必要になる。
  • リレーショナルデータベースでは、再帰的CTE(Common Table Expressions)を使ってツリー構造のデータを取得できる。

データは本当にツリー構造である必要があるのか?

  • 項目が実際に親子関係を持つ必要があるのか、それとも単にそう見えればよいのかを考える必要がある。
  • 実際の関係が不要なら、idsortindentname フィールドを使ってツリーを簡単に保存できる。
  • この方法は画面に見えているものをそのまま表現するため、一覧をレンダリングして編集するインターフェースを作るのがはるかに簡単になる。

「ネームスペーシング」を使った別の例

  • HissScriptでは、項目名にドット(".")がある場合、最初の部分を切り落として項目をインデントすることでネームスペーシング機能を実装している。
  • ゲームエディタとプレイヤーにとってはネームスペーシングが重要だが、実際には単なる名前にすぎない。
  • 人はしばしば、実際のツリー構造そのものよりも、その見た目だけを必要としている。

おまけのツリー・リスト

  • 実際の木をまねて、パスと情報をフラットな一覧に保存し、深さ優先または幅優先の走査のためにパスをソートする。
  • フラットな一覧は一般に扱いやすく、コンピュータにも向いている。

物理的なたとえ

  • 個人のスクラップブックを整理するとき、人間にはグループの仕組みが明確でも、実際には床の上にそのような関係を強制する物理的なメカニズムは存在しない。

注意: あらゆる状況に当てはまる解決策はない

  • 特定のシナリオに合わせて技術を適用する必要があり、実際にツリー構造が必要な場合はツリーを使うべきである。
  • 項目間の実際の関係を把握する必要がある場合は、インデントや文字列中の記号を数えるようなハックを使ってはいけない。

GN⁺の意見:

  • この記事は、ソフトウェア開発において複雑なツリー構造の代わりに視覚的にシンプルなインデントを使い、ユーザーインターフェースを簡素化する方法を示している。
  • 開発者にとっては、データ構造を単純化して開発時間を節約し、保守を容易にする効果的な戦略を提供している。
  • この記事は、ツリー構造が常に必要とは限らず、ときにはユーザーにとって親しみやすい視覚的構造だけで十分だと強調することで、開発者がユーザー体験を改善するための新しい視点を提供している。

1件のコメント

 
GN⁺ 2024-01-01
Hacker Newsのコメント
  • 最初のアプローチである「隣接リスト(adjacency list)」は、「明らかに唯一の方法」と見なされがちである。

  • 2つ目の方式は「はるかに単純な方法」で、これまで見たことのないやり方であり、明白な欠点はあるものの、場合によっては十分に明快である。

  • 3つ目の方式である「名前空間化(namespacing)」は、「マテリアライズドパス(materialized path)」と呼ばれる。

  • ツリーを表現する別の方法として「ネスト集合(nested sets)」があり、これはリレーショナルデータベースを本格的に扱っていた時代によく知られていた手法である。

  • Postgres は ltree というデータ型と検索演算子を提供しており、ツリー構造を自然に扱える。たとえば、ltree を使ってテーブルを作成し、データを挿入したうえで、簡単な検索によりツリー構造を問い合わせることができる。

  • 構造内の値は、表示されているツリーそのものではなく、データの階層構造であることが多い。データを走査したり、関係を示したり、並べ替えたりといった作業をしたくなるだろう。データベース内のデータ構造に視覚的な情報を保存するのは、短期的な発想に見えることがある。

  • ツリー状データを扱う会社を創業した経験がある。ツリー構造を O(n) 時間でインデント付きリストに変換することは可能である。これは面接問題の1つでもあり、再帰クエリなしでもツリーの一部を高速に取得してレンダリングできる方法は SQL データベースにさまざま存在する。

  • SQL クエリを使ってリレーショナルデータベースからツリー構造データを取得する方法の1つは、再帰的な CTE(Common Table Expressions) を書くことである。CTE は実際かなり面白く、いったん慣れてしまえば恐れる必要はない。

  • 人はしばしば、本当にツリーを必要としているのではなく、単にツリーの見た目だけが必要なのだと経験から学んだ。HN と Reddit はこの点で異なる。HN では子コメントは親コメントの次の兄弟として置かれ、インデントを親のインデントに1つ足すことでツリーの見た目を模倣している。一方 Reddit では、子コメントは実際に親コメントの中にネストされている。

  • 記事の中心的なアイデアは、問題に適した構造を使うことにある。しかし、話の展開には欠陥がある。ツリーをデータベースから取り出すのに CTE は必須ではなく、フラットなリストを取得してローカルでツリーを構築できる。また、十分に大きなツリーでは、枝を移動したり深さを変えたりしたいときに線形コストが発生する可能性もある。

  • 分類体系やその他の階層構造を説明するとき、ローカルファイルシステムを使うシンプルで高速な方法を身につけた。mkdirtree コマンドを使い、その結果をメール、Slack、pastebin などに貼り付けて共有する。

  • 保存と読み込みだけが目的なら、データを望む形でシリアライズ(例: JSON)して文字列として保存するほうが、より単純な解決策かもしれない。ドット記法を使うやり方は、VsCode 拡張機能の Dendron が名前階層を扱う方法に似ている。

  • 数年前、OpenGL についても似たような気づきがあった。階層化された 3D オブジェクトの世界を描画する必要はなく、単に整列済みの三角形リストを描画すればよい。これにより、多くの最適化が非常に容易になる。