ファイラーを作って分かったこと
── Undo は嘘をつく。だから言語を選び直す
きっかけは単純だった。Windows のエクスプローラーは優秀だが、「考えながら操作する」には少し重い。ならば、自分の思考速度に合わせた TUI ファイルエクスプローラ を作ってみよう。そんな軽いノリで始めた。
Python と Textual を使い、移動・検索・コピー・ペースト・リネーム・削除・Undo・外部起動まで一通り実装した。動いた。それなりに快適だった。
そして最後に、致命的な違和感だけが残った。
Undo は「戻せるふり」をする
Undo は Command Pattern で実装した。execute() と undo() を対にし、スタックに積む。教科書的には正しい。
Command Pattern の実装
class Command:
def execute(self):
raise NotImplementedError
def undo(self):
raise NotImplementedError
class RenameCommand(Command):
def __init__(self, old_path: Path, new_path: Path):
self.old_path = old_path
self.new_path = new_path
def execute(self):
self.old_path.rename(self.new_path)
def undo(self):
self.new_path.rename(self.old_path)
class CopyCommand(Command):
def __init__(self, src: Path, dest: Path):
self.src = src
self.dest = dest
def execute(self):
if self.src.is_file():
shutil.copy2(str(self.src), str(self.dest))
else:
shutil.copytree(str(self.src), str(self.dest))
def undo(self):
if self.dest.is_file():
self.dest.unlink()
else:
shutil.rmtree(self.dest)
だが、実際に触ると分かる。
つまり Undo はこうなる。
「戻れる時だけ戻れる。でも UI はそれを教えてくれない」
これは UX の問題ではない。設計上の嘘だ。
Undo が壊れるのは、コードではなく "世界の状態"が変わるからだ。
Python は悪くない。ただ"黙認する"
今回の実装で Python が悪かったわけではない。むしろ良かった点は多い。
ただし、ある段階から気づく。
Python はこう言っている。
「それ、本当に考えた?まあ、動くなら止めないけど」
Undo実装の実際
def action_undo(self):
if not self.command_stack:
self.update_status("⚠️ Undoできる操作がありません")
return
cmd = self.command_stack.pop()
try:
cmd.undo()
self.reset_tree()
self.update_status("↩️ 操作を元に戻しました")
except Exception as e:
self.update_status(f"⚠️ Undo失敗: {e}")
例外は握り潰せる。状態はぐちゃっと持てる。Undo も「たぶん大丈夫」で通る。
Python は自由をくれる。ただし、責任を強制はしてくれない。
思考実験には最適だが、責任を持つ設計には沈黙する。
作って初めて見えた"設計の層"
このファイラーは、実は3層でできている。
1. OS直叩き層
- ファイル操作、クリップボード、フォーカス制御
- ここは OS の気分に左右される
2. UI / 状態管理層
- モード遷移、履歴、入力状態
- ここは Python と Textual が得意
3. 事故制御層
- 失敗、部分成功、Undo 不能、競合
- ここが最も重要で、最も軽視される
Undo が嘘をつくのは、この 「事故制御層」を設計していないからだ。
では、次に選ぶべき言語は何か
今回の経験で分かったのは、言語選択は性能ではなく 思想の選択だということ。
C#
Windows を母国語として扱える。例外と型で「失敗理由」を持てる。今回のコードを最短で"格上げ"するならこれ。
Rust
Undo が嘘をつく余地をコンパイル時に潰してくる。書くのは重いが、事故の設計から逃げられない。これはツールではなく、思想の実装。
TypeScript + Tauri/Electron
UI/UX は別次元。ただし低レイヤは Rust/C++ に戻る。「使う人の認知を支配したい」なら最強。
Go
無骨で、並行性が素直。内製ツールとしては非常に強い。
どの言語を選ぶかは、どの嘘を許容するかの選択でもある。
このプロジェクトの"役目"はもう終わった
この Python ファイラーを完成させるつもりはない。役目はもう果たした。
これらを 体感できる形で可視化してくれた。
次にやるなら、
そのどれか、あるいは全部だ。
おわりに
このファイラーは売り物ではない。だが、無駄でもない。
作った結果、「どこからが嘘になるか」が分かった。
それだけで十分に価値があった。
技術は、完成品よりも "完成できない理由"を教えてくれる時の方が、ずっと誠実だ。
📦 ソースコード
この記事で言及したファイラーの完全なソースコードは GitHub で公開しています。
View on GitHub →