Refactoring English:1か月目
原文は Michael Lynch により に公開されました。 このブログを購読する
一言まとめ
本の最初の章を公開しました。
ハイライト
- 本の第1章を公開し、反響にも手応えを感じています。
- 表紙デザイナーへの依頼は失敗に終わりました。
- PicoShareで大容量ファイルを扱う方法に目処が立ったかもしれません。
目標の達成度
毎月の初めに、その月に達成したいことを宣言しています。目標に対してどうだったか振り返ります。
Refactoring Englishを2章仕上げる
- 結果:1章を完成させ、次の章は75%まで進みました。
- 評価:B
最初の章は書き直したい箇所が次々と見つかり、想定より時間がかかりました。途中で1週間ほど離れて別の章を書き、新鮮な気持ちで戻ってきたのは効果的でした。
デザイナーと協力してRefactoring Englishの表紙デザインを完成させる
- 結果:表紙は自分で作ることにしました。
- 評価:C
デザイナーと途中まで進めましたが、方向性が気に入らなかったのでこちらから打ち切りました。当面は自作の表紙でいくことにします。
Refactoring Englishの第1章を終えて考えたこと
著書Refactoring Englishの第1章を公開しました。章のタイトルは「Rules for Writing Software Tutorials」で、長年にわたってチュートリアルを読んできて、良い点や悪い点に気づいてきた経験をもとに書いたものです。
第1章は好意的に受け止められました
章の反響は、期待していた中でもかなり良い方でした。チュートリアルに関するルールを並べたものなので、インターネットで大バズりするとは思っていませんでしたが、相性が良さそうだと思っていたいくつかのサイトではそれなりの反応がありました。
- Hacker News:375ポイント、最高10位まで上昇
- /r/programming:159ポイント、その日の1位を獲得(たしか)
- Lobste.rs:27ポイント、2位まで上昇
私が主に追っている指標はメーリングリストの登録者数です。投稿後の1週間で245人が新たに登録し、書籍の登録者総数は31%増えました。

第1章の公開をきっかけに、書籍のメーリングリスト登録者数が大きく跳ね上がりました。
公開した記事をどう改善していくのが正解か
数年前、Redisの作者であるサルバトーレ・サンフィリッポがプログラミングの仕事を中断してSF小説の執筆に取り組みました。小説を書く中で、彼はこんなことを述べています。
執筆とプログラミングの最も鋭い違いは、一度書かれ、編集され、完成した小説は、ほとんど不変のままであるということだと思う。
サルバトーレは続けて、プログラマーは小説家に学び、アプリが完成した後に中核的なロジックを書き換えたい衝動を抑えるべきだと述べています。私はむしろ逆の教訓を得ました。著者こそプログラマーのように、もっと反復的に本を書くべきだということです。
Refactoring Englishでは、章をほぼ完成した状態で公開しつつ、読者からのフィードバックを執筆に反映させたいと考えています。
章が流動的なまま公開されていることで、これまで経験したことのない問題が起きています。コメントスレッドを混乱させてしまっているのです。Hacker NewsやLobste.rs、redditで、コメントした人たちが私の「条件分岐の評価はコンピューターに任せる」という主張に反論していました。そして私も、彼らの言うとおりだと思います。あれは最も弱い論点だったので、削除しました。
問題は、それらの議論を読んだ人が、記事には存在しない論点になぜみんなが反論しているのか不思議に思ってしまうことです。
思いつく最善の策は、末尾に注記を入れることです。本はまだ改訂中であること、オリジナルへのリンク、そして主な修正点の一覧を載せておくという方法です。
フィードバックをくれる読者をどう見つけ続けるか
今のところ、読者のフィードバックをもとに反復していくという計画はうまくいっていると感じています。
公開した第1章の出来には満足していますが、同時に読者から多くの思慮深い指摘をもらい、改訂に活かせそうです。
「よし、このまま同じチャネルでプレビュー版の章を共有し続ければいいな」と思いました。
ところが、目次を見返してみると、最初に共有したチャネルに合う章は他にないことに気づきました。そうしたサイトの多くには「投稿にコードがなければ場違い」という明文化された、あるいは暗黙のルールがあります。たとえば、なぜ受動態が嫌いなのかを熱く語る章を/r/programmingの人たちが喜んで読むとは思えません。
一つのアイデアとして、フリーランスで他の書き手の編集を手伝い、そこで得た知見をRefactoring Englishに活かすという方法を考えています。
ただ、「編集」という言葉は、私が得意とすることが正確には伝わらない気がしています。「編集者」と聞くと、文章を代わりに磨いてくれる人を想像するでしょう。私が本当にやりたいのは、文章の問題点を見つけ、自分で改善できるように原則やテクニックを説明することです。これを何と呼べばいいのかわかりません。ライティングのメンタリングでしょうか、コーチングでしょうか。
いずれにせよ、興味があればぜひご連絡ください。ブログ記事やドキュメント、その他ソフトウェア関連の文章をお手伝いできます。より多くの読者を引きつけ、文章をより魅力的にする方法をお見せできます。端的に言えば、このブログの書き方が好きだと思ってくれたなら、ここで使っているテクニックをお伝えできます。
- 料金は2回のレビューで100ドルです。
- 初稿のレビューと、フィードバックを踏まえた修正のレビューが含まれます。
- 対象は最大2,500ワードまでです。
- 料金をいただくのは、あなたにも当事者意識を持ってもらうためです。もし100ドルが予算的に厳しければ、別の方法を相談できるかもしれません。
Reedsyで表紙デザイナーを雇って失敗した話
11月に本の執筆から気が散ってしまったことの一つに、プロがデザインした表紙が必要だと思い込んだことがあります。動き始めたのは11月でしたが、実際の作業は12月に行われました。
デザイナーはReedsyというプラットフォームで見つけました。Write Useful Booksコミュニティで何人かに勧められたサービスです。評判は「高いけど、それだけの価値はある」というものでした。
デザインの要件をまとめたブリーフを書き、Reedsy上の4人のデザイナーに送りました。予算は350〜650米ドルと記載しました。一人は上限の20%超で入札してきて、返信は「もちろんできますよ」というだけでブリーフを読んだ形跡はありませんでした。別の一人は予算が低すぎると辞退し、一人は返信すらありませんでした。
まともな入札はGary一人だけで、350ポンド(434米ドル)で引き受けるとのことでした。彼はブリーフの具体的な内容に触れた丁寧なメッセージをくれ、ポートフォリオには何十もの書籍カバーがあり、Reedsyでの評価は満点の5.0でした。期間は1か月、料金は3回に分けて支払うという提案で、特に問題なさそうだったので依頼することにしました。
Garyとのやり取り
1週間経ってもGaryから連絡がありませんでした。1回目の支払いが自動で引き落とされた後、初稿の目安を尋ねると、翌日にコンセプトを送るとのことで、実際に送ってきました。

Reedsyで雇ったデザイナーから送られてきた表紙の初期案
サンプル1は良さそうに見えましたが、ブリーフで引用していたBeautiful Codeの露骨な模倣でした。残りは物足りない出来でしたが、ブリーフにもっと時間をかけなかった自分が悪いと思いました。
コンセプトを見返す中で、自分が本当に伝えたいのは「丁寧で、慎重な仕事」というイメージだと気づきました。禅庭のサンプル6と、粘土の型のサンプル5が方向性としては近いと感じ、そちらを掘り下げてほしいと頼みました。石を彫る彫刻家のイメージを提案しました。
また1週間が経ち、Garyからは禅庭のアイデアを少し変えただけのものが送られてきました。彫刻家のコンセプトも試してくれましたが、ノミと原石が写った写真で、石はまったく彫られていなかったため、丁寧な仕事というイメージは伝わってきませんでした。
翌週はクリスマスで、プロジェクトが12月30日の完了予定に間に合うのか不安になってきました。クリスマス前の月曜日にGaryからメールがあり、12月27日に仕事に戻るので予定どおり進んでいるとのことでした。
27日の終業時刻になってもGaryから連絡はなく、まずい状況だと気づきました。
私のいる米国東部時間では金曜の午後4時でしたが、Garyは英国にいるので彼の営業日はとっくに終わっていました。Reedsyは月曜の東部時間正午に自動で請求する予定でした。Reedsyで請求に異議を申し立てられるのは請求の24時間前までなので、完成品を受け取るための営業日はもう残っていませんでした。
Reedsyのカスタマーサポートに、Garyが成果物を納品していないので最終支払いを1週間遅らせてほしいと頼みました。ReedsyからはGary本人と話してくれと言われました。次の営業日までGaryの返事を待っていたら支払いの移動が手遅れになると説明しましたが、サポートはそれでもまずGaryと解決するようにと主張しました。
金曜の東部時間午後5時にGaryにメールすると、「会社員のような時間では働いていない」ので週末に作業して予定どおり終えられると返事がありました。彼は好意で支払いを遅らせてくれましたが、Reedsyに苦情を入れたことに少し苛立っているようでした。
一方の私は、なるべく通常の勤務時間内で働くようにしており、週末をGaryと一緒に慌ててプロジェクトを仕上げるのに費やしたくはありませんでした。月曜に確認すると、Garyは2つのコンセプトの更新版を送ってきていましたが、どちらもかなり平凡でした。一つは明らかにAI生成で非現実的に見え、もう一つは私が求めていたトーンをまったく捉えていませんでした。
画像がAI生成かどうか、ブリーフで指定したライセンス要件を満たしているかをGaryに尋ねると、彼ははぐらかすような態度を取りました。そこでプロジェクトの中止を申し出ました。すでに支払った231ポンド(287米ドル)はそのまま渡すので、最終支払いをキャンセルしてプロジェクトを終了させてほしいと提案すると、彼は同意し、それで終わりとなりました。
Garyには全項目で星3つのレビューを付けました。ひどいとは思いませんでしたが、可もなく不可もなく、スケジュールの連絡が下手だったという印象です。私のレビューは公開されていますが、Reedsyでは私が3.0を付けたにもかかわらず、Garyは依然として5.0の満点評価と表示されており、他のレビューは4件しかありません。

Garyに星3つのレビューを付けたにもかかわらず、5件のレビューでいまだに満点の5.0と表示されている。
自作した表紙
Garyとの話がなくなったので、自分で表紙を作ってみることにしました。Unsplashで見つけたロイヤリティフリーの画像が、静かで丁寧な仕事という雰囲気をよく捉えていたので、それにテキストを加えました。

素人っぽい出来なのは自覚していますが、Garyに頼んだ場合に期待していた満足度の8割くらいには達しています。しかも無料で、1時間でできました。ひとまず仮の表紙として扱っています。いつでも誰かを雇い直したり、時間をかけて作り直したりできます。
サイドプロジェクト
PicoShareで大容量ファイルを扱えるようにする
PicoShareは、インターネット経由でファイルを共有するための、私が作ったミニマルでホスティングが簡単なウェブアプリです。数年前に作って以来、毎週のように使っています。
PicoShareについて少し引け目を感じているのは、大容量ファイルでスケールしにくいことです。共有CPUと256MBのRAMを搭載したVMでは、1GB程度までのファイルなら快適に動作します。1GBを超えるファイルをアップロードしようとすると、たいていRAMを使い果たしてクラッシュします。ハードウェアを増強すれば解決はできますが、できればPicoShareが容量を問わず大きなファイルをアップロードできるようにしたいところです。
何度か問題を掘り下げてみて、このパフォーマンス問題はPicoShareがファイルデータをすべてSQLiteに保存しているせいだという強い確信があります。変わった選択ではありますが、これによりSQLiteのデータにファイルデータを含むアプリの状態全体が収まることになります。おそらく、PicoShareが大量のデータをSQLiteに書き込もうとしてRAMを使い果たし、落ちているのだと思います。
SQLiteのストリーミングI/O APIを使えば、もっと効率的にデータベースへ書き込めるのではないかと気になっていました。ただ、PicoShareはGoで書いており、当時使っていたGo用のSQLiteドライバはストリーミングI/O APIをサポートしていませんでした。
幸い、Nuno Cruces氏がストリーミングI/OをサポートするGo用の新しいSQLiteドライバを公開し、PicoShareを彼のライブラリに移植するのを手伝うと申し出てくれました。9月に少し一緒に作業して前進はあったのですが、ストリーミングI/Oを使っても、PicoShareはやはり大容量ファイルでメモリを使い果たすことがわかりました。
Nuno氏は、ファイルを分割してチャンク単位でSQLiteに書き込めばRAM消費を抑えられるかもしれないと提案してくれました。実は現在の実装でもすでにそうしていますが、ストリーミングI/Oではセマンティクスが異なるため、繊細なコードを大量に書き直す必要がありました。そこで力尽きて、一旦作業を棚上げしました。
12月に、改めて新鮮な気持ちでストリーミングI/Oの問題に戻ってきました。チャンク分割の問題は思ったより簡単だと気づきました。PicoShareは大容量ファイルの読み込み時ではなく、書き込み時にRAMを使い果たしていたのです。つまり、書き込み側だけをより効率的なストリーミングAPIで実装し直せばよかったのです。
ストリーミングI/Oでチャンク単位にファイルを書き込む方法は、SQLiteのデフォルトAPIで実装したものよりシンプルでした。当初は、SQLiteデータベースをio.Writerオブジェクトで抽象化して、io.Copyでデータを流し込むのが一番簡単だと思っていました。しかし今回は、io.Copyを使わずに直接すべて書き込む方が簡単だとわかりました。
ストリーミングI/O版は限定的なテストでは安定していますが、まださらに広範なテストが必要です。ネックになっているのは自宅のアップロード速度がひどく遅いことで、対策としてfly.io上でデスクトップOSを動かし、VNCでリモートアクセスできる環境を作ろうとしています。
まとめ
何ができたか
- 「Rules for Writing Software Tutorials」を公開しました
- 「if got, want: A Simple Way to Write Better Go Tests」を公開しました
- 新しいNixOS環境をセットアップし、この1か月まったくWindowsを使わずに過ごしました。
- offlineimapでメールのローカルコピーを保持するようにし、日次のスナップショットでバックアップしています。
- 気に入っているオープンソースのRSSリーダーfusion(GoとSQLite製)にいくつかコントリビュートしました。
学んだこと
- グラフィックデザイナーを雇う際の教訓
- プロに頼む前に、自分で仮のバージョンを作ってみることを検討する。
- 支払いは日付ではなく、プロジェクトのマイルストーンに紐づける。
- AI生成画像やAI支援による画像合成の使用可否を明示する。
- 写真やフォントなどのサードパーティ素材について、ライセンス情報をきちんと確認する。
- 私はブリーフで、すべての素材はライセンス的に適合している必要があると書いていました。
- より良かったのは、素材がライセンスに準拠しているという口約束ではなく、ライセンス情報そのものを納品物として提出させることでした。
- クリスマス直後に終わるようなスケジュールでプロジェクトを組まない。
- Reedsyはクライアントよりもコントラクターを大幅に優遇する仕組みになっている。
来月の目標
- 2024年の年次レビューブログ記事を公開する。
- 本の次の章を完成させる。
- 読者からのフィードバックをもとに、チュートリアルの章を改訂する。
お願い
- 文章作成のサポートに興味があれば、ぜひご連絡ください。
記事をランダムに読む
コメント
ログインしてコメントする