はじめに
みなさん、コードを書くのは得意ですか?
・・・はい、みんな得意ですよね!
じゃあ、文章を書くのは得意ですか?
・・・あれ?急に声が小さくなりましたね(苦笑)
たぶん、自信を持って「わかりやすい文章が書けます!」って言えるエンジニアの方は少ないんじゃないかと思います。
というわけで、この記事では実際の「編集リクエスト例」を使って、わかりやすい技術記事を書くポイントを説明します。
説明で使うQiita記事
説明で使うQiita記事はこちらです。
nested_form で子レコード間の関連を検証する - Qiita
内容としてはRailsでよく使われる nested_form というgemの応用的な使い方を説明しています。
編集リクエスト前の記事
上のリンクはすでに編集済みの状態になっていますが、編集リクエスト前の記事はこんな状態でした。(記事タイトルも変更しています)
親子関係のモデルを利用したフォームでのバリデーション例 - Qiita
これから元の記事のどの部分をどういう理由で変更したのかを解説していきます。
僕が送信した編集リクエスト
僕が送信した編集リクエストは以下のリンクから参照できます。
この記事の内容や、後述する解説動画を見るときに参考にしてみてください。
参考:編集リクエストを送ったきっかけ
元記事の投稿者で同僚の @Matsushin が「Qiita記事を書いたので、何かフィードバックがあれば教えてください」と連絡をくれたのがきっかけです。
全く見ず知らずの人の記事をピックアップして、好き勝手意見してるわけではありませんのでご安心ください(苦笑)。
また、この内容をQiitaに公開することも了承してもらっています。
解説動画
変更点の解説は動画(スクリーンキャスト)としてYouTubeに公開しています。
この記事は動画の内容を文章として書き起こしたものになります。
これであなたの記事もランキング入り!?@jnchitoによるQiita記事の改善例 - YouTube
それでは以下が本編です。
タイトルは記事の内容を具体的に表す言葉を選ぶ
まずは記事の入り口として非常に重要なタイトルを修正します。
この記事の元のタイトルは「親子関係のモデルを利用したフォームでのバリデーション例」でした。
しかし、本文を読むとこの記事の特徴は以下の部分にあると僕は感じました。
- nested_form というgemを使っている
- 親レコードにぶら下がる、子レコード同士の内容をチェックして、バリデーションエラーを表示する
というわけで、「nested_formを使っていますよ!」「バリデーションはバリデーションでも、子レコード同士の内容をチェックしてるんですよ!」ということを強調するタイトルに変更してみました。
- 親子関係のモデルを利用したフォームでのバリデーション例
+ nested_form で子レコード間の関連を検証する
メリハリを付けて書く / 文体を揃える
「はじめに」の部分はもともと以下のような文章になっていました。
1対多関連のデータをまとめて登録させたい時に親と子のデータもしくは子同士など複合でバリデーションをしたいケースがある。その際の例をいくつかまとめてみました。
最初の1文がかなり長く、読点(、)もないため、ぱっと意味をとらえにくいです。
また、1文目は「である調」で終わっているのに対し、2文目は「ですます調」になっています。
そこで次のように文章を改善してみました。
(注:スマホだとdiffが見にくいかもしれないので、PCで見ることをオススメします。)
- 1対多関連のデータをまとめて登録させたい時に親と子のデータもしくは子同士など複合でバリデーションをしたいケースがある。その際の例をいくつかまとめてみました。
+ 1対多で関連するデータを nested_form で登録する際、子レコード間の関連を検証したいときがある。
+ この記事ではそうしたユースケースに対応可能なバリデーションの実装例を紹介する。
1文目は読点(、)を使って文章を区切っています。
また、「親と子のデータもしくは子同士など複合でバリデーションをしたいケース」という少し冗長な表現を、「子レコード間の関連を検証したいとき」とざっくり短くまとめました。
また2文目も「ですます調」から「である調」に変更しています。(以下は全部「である調」で統一)
「である調」よりも「ですます調」で書くのがオススメ
ブログや技術記事を書くときは、「である調」よりも「ですます調」の方が書きやすい(文体を統一しやすい)です。
というのも、「である調」はどうしてもキツく聞こえてしまうため、つい「ですます調」で書きたくなる瞬間が出てくるからです。
よくあるのは最初は「である調」で書き始めたのに、「ここはである調だとキツいな」と感じると、つい「~してください」のように「ですます調」の文体が紛れ込んだりするケースです。
なので、「ですます調」で書いた方が、最初から最後まで「ですます調」で統一しやすいと僕は考えています。
もし「である調」で書くのであれば、「キツく聞こえるかも」と思った部分も「である調」で書くべきである。(←「である調」にしてみた)
ライブラリのGitHubリポジトリや公式ページへのリンクを付ける
この記事では simple_form や nested_form というgemが登場していますが、読者の中にはこれらのgemを初めて知った、という人がいるかもしれません。
そういった人たちのために、GitHubリポジトリや公式ページへのリンクを付けておいてあげると親切です。
- 今回は`gem`の`simple_form`と`nested_form`を利用している。
+ フォームの作成には [simple_form](https://github.com/plataformatec/simple_form) と [nested_form](https://github.com/ryanb/nested_form) を利用している。
長い文章を分割する
1文が長いと読みづらいので、長い文章は積極的に複数の文に分けていきましょう。
文章がPCの画面上で折り返して表示されるようになったら黄色信号です。
どうしても無理な場合は仕方ありませんが、可能であれば文章の分割を検討してください。
- 1対多のフォームを作成するときに子要素を動的に追加、削除ができるビューのヘルパーメソッドが利用が可能になる`gem`。
+ 1対多のフォームを作成するときに便利なgem。
+ 子要素を動的に追加、削除ができるビューのヘルパーメソッドが利用が可能になる。
見出しのあとは「ひとこと」添える
見出しの直後にコードや箇条書きがいきなり登場すると、読み手が一瞬「えっ、何の話?」と困惑する恐れがあります。
「今から~を説明しますよ~」ということが伝わるように、「ひとこと」添えてあげましょう。
「何も言わなくてもわかるだろ?こっちの意図をくみ取れよ」という態度で文章を書くのはNGです。
## モデル
- - `Project`
- - name(プロジェクト名)
+ モデルのコードは以下の通り。(nested_form関連の細かい設定は省略している)
文章だけでなく、コードを見せる
「百聞は一見にしかず」ではりませんが、プログラマにとっては「百の文章よりも一のコード」の方がわかりやすい場合が多いです。
技術記事であれば積極的にコードを載せていきましょう。
## モデル
-- `Project`
- - name(プロジェクト名)
- - published(公開フラグ 公開/非公開)
-- `Task`
- - name(タスク名)
- - priority(優先度 最優先/高い/低い)
+モデルのコードは以下の通り。(nested_form関連の細かい設定は省略している)
+```rb
+class Project < ActiveRecord::Base
+ has_many :tasks
+end
+
+class Task < ActiveRecord::Base
+ belongs_to :project
+end
+```
+ProjectとTaskにはそれぞれ以下のような属性がある。
+
+Project
+
+- name (プロジェクト名)
+- published (公開フラグ。公開 or 非公開)
+
+Task
+
+- name (タスク名)
+- priority (優先度。最優先 or 高い or 低い)
画像も積極的に使うとより効果的
元の内容が良かった点は以下のように画像を積極的に使っていた点です。
なので、説明用画像については今回特に指摘や変更を入れていません。(よくできました!)
「百の文章よりも一の画像」がわかりやすいケースも多々あるので、画像もどんどん使っていきましょう。
重要なセクションでは問題と解決策をハッキリさせる
元の内容では淡々とスクリーンショットやサンプルコードが並んでいる印象が強く、どこに問題があって、それをどう解決したのか、何が改善されたのか、といった点がわかりづらかったです。
以下で説明するセクションは元記事の中で一番のキモとなる部分と言っても良いので、しっかりと説明してあげましょう。
変更前
元の内容では淡々としすぎていて、さらっと読み飛ばしてしまいそうな感じでした。
エラーでひっかかるとこうなる
![qiita_02.png](https://qiita-image-store.s3.amazonaws.com/0/41362/f5a483a3-9bf4-449c-494f-bae71e649260.png "qiita_02.png")
# エラー表示を子レコードの指定フィールドにしたい場合
- 子レコード毎にチェックしてエラーを設定する。
- この際親にエラーを設定しないとエラーとならずに保管されてしまうことに注意
``models/project.rb
# 指定のフィールドにエラーを付与したい
validate :only_one_top_priority
def only_one_top_priority
top_priority_count = tasks.inject(0) do |count, task|
count += 1 if task.priority.top?
task.errors.add(:priority, :only_one_top_priority) if count > 1
count
end
# 親レコードにエラーを設定しないと保管されてしまうことに注意
errors.add(:base, :only_one_top_priority_for_project) if top_priority_count > 1
end
``
エラーでひっかかるとこうなる
![qiita_03.png](https://qiita-image-store.s3.amazonaws.com/0/41362/400b328a-83c9-84f1-9968-e97458305f67.png "qiita_03.png")
変更後
このセクションは読み飛ばしていい箇所ではなく、むしろしっかりと読んでもらうべき箇所なので、丁寧に説明した方が良いです。
## エラー時の表示例
バリデーションエラーが発生すると次のように表示される。
![qiita_02.png](https://qiita-image-store.s3.amazonaws.com/0/41362/f5a483a3-9bf4-449c-494f-bae71e649260.png "qiita_02.png")
# エラー表示を子レコードの指定フィールドにしたい場合
上の表示例だと、画面の上部にしかメッセージが表示されないため、フォームのどこでエラーが起きているのかわかりづらい。
そこで各フィールドにもエラーを表示できるようにした。
``models/project.rb
# 指定のフィールドにエラーを付与したい
validate :only_one_top_priority
def only_one_top_priority
top_priority_count = tasks.inject(0) do |count, task|
count += 1 if task.priority.top?
task.errors.add(:priority, :only_one_top_priority) if count > 1
count
end
# 親レコードにエラーを設定しないと保管されてしまうことに注意
errors.add(:base, :only_one_top_priority_for_project) if top_priority_count > 1
end
``
上のコードのポイントは次の通り。
- 子レコード毎にチェックしてエラーを設定する。
- このとき、親レコードにエラーを設定しないとバリデーションがパスして保存されてしまうので注意する。
## エラー時の表示例
問題が発生したタスク(フィールド)にエラーが表示されている。
![qiita_03.png](https://qiita-image-store.s3.amazonaws.com/0/41362/400b328a-83c9-84f1-9968-e97458305f67.png "qiita_03.png")
ムダに動詞を重ねない
「まとめ」の欄で「~できることがわかる」という表現がありました。
「できる」「わかる」と動詞を重ねてもあまり意味がないので、表現はできるだけ簡潔に持っていきましょう。
- 親モデルで子モデルのデータを全てチェックできるので柔軟にバリデーションできることがわかる。
+ 親モデル内で子モデルのデータを全てチェックできるので、柔軟にバリデーションが実装できる。
英語っぽく「なぜなら(because)」を後ろに書く
英語だと "Alice went out because it was a fine day." のように、理由を表す because 節を後ろに持ってきます。
日本語でも強調したいことを前に、その理由を後ろに持ってきた方が読みやすくて説得力のある文章が作れます。
- 子レコードのチェック時はまだデータの保管自体はされていない(配列にデータが入っている状態)ため`where`、`count`等のSQLが実行される方法で判定できないことに注意が必要
+ 子レコードをチェックする際は `where` や `count` 等のSQLを使う方法では判定できない。(レコードがまだ保存されていないため)
「まとめ」に書く内容は必ず本文に含めておく
元の内容では「まとめ」の欄に「where
、count
等のSQLが実行される方法で判定できない」という文章が入っていました。
しかし、これに対応する内容が本文に書かれていませんでした。
これだと読み手が「えっ、そんな話書いてたっけ?もしかして読み飛ばしてたかな!?」と困惑してしまいます。
なので、「まとめ」に書きたいのであれば、本文にもその内容を含めるようにしましょう。
+ 子レコードのチェック時はまだデータの保管自体はされていない(配列にデータが入っているだけの状態)。
+ そのため、 `where` や `count` 等のSQLを使う方法では判定できないことに注意する。
(中略)
## まとめ
- 子レコードのチェック時はまだデータの保管自体はされていない(配列にデータが入っている状態)ため`where`、`count`等のSQLが実行される方法で判定できないことに注意が必要
+ 子レコードをチェックする際は `where` や `count` 等のSQLを使う方法では判定できない。(レコードがまだ保存されていないため)
今回説明しない内容は「本文のまとめ」と分けて書く
元の内容では他にも「今回はサンプルのためモデルにコードを書いたがvalidateのメソッドは可読性/保守性を上げるためにconcernに切り分けた方が良い。」という文章が「まとめ」の箇条書きに含まれていました。
しかし、これは「今回はやっていないが」という内容なので、他の項目と明確に分けた方が良いです。
具体的には、本文で説明した内容は箇条書き欄に、本文で説明していない内容はそれ以外の場所にそれぞれ書くと良いでしょう。
## まとめ
- (他の箇条書き)
-- 今回はサンプルのためモデルにコードを書いたがvalidateのメソッドは可読性/保守性を上げるためにconcernに切り分けた方が良い。
+また、今回のサンプルアプリケーションでは採用しなかったが、可読性や保守性の観点からバリデーション部分を Concern に切り分けるのも良い。
(お好みで)コードをインライン表示する場合は前後にスペースを入れる
これは人によって好みがわかれると思いますが、僕はコードをインラインで書く場合に前後にスペースがないと字が詰まって読みづらいと感じる人です。
- スペースなし:
Project
が非公開の場合はTask
に最優先は設定してはいけない - スペースあり:
Project
が非公開の場合はTask
に最優先は設定してはいけない
なので、編集リクエストでもコードであれば前後にスペースを入れるようにしています。
ただし、特に読みにくさを感じないのであれば、スペースなしのままにしておくのもOKだと思います。
僕が送信した編集リクエストの主なポイントはだいたい以上です。
おさらい
さて、ここで改めてこの記事を書くために使った元記事や編集リクエストをおさらいしておきましょう。
改善前の記事は以下のリンクにあります。
改善後の記事は現在表示されている内容です。
僕が送信した編集リクエストは以下のリンクにあります。
また、僕が口頭でポイントを説明した解説動画はYouTubeにアップしています。
これであなたの記事もランキング入り!?@jnchitoによるQiita記事の改善例 - YouTube
まとめ
いかがだったでしょうか?
僕が文章を書くときはだいたいこういう点に気をつけながら書いています。
全体を通して大事なポイントは 「読み手の気持ちを想像しながら書く」 ということです。
「みんなこれぐらいわかるだろう」ではなく、「もしかしたら読者はここでつまづくかもしれない」という気持ちで文章を書いていくと、結果としてわかりやすい文章ができあがります(クルマの「だろう運転」と「かもしれない運転」みたいな感じですね)。
文章を書く側は当然ながら説明する内容やそこに至る背景を理解していますが、読む側はむしろそれを理解していない可能性の方が高いです。
「自分視点」で書くと往々にして「自分以外に伝わりにくい文章」になりがちなので、「読み手の視点」を忘れずに技術記事を書いてください。
そうすればあなたのQiita記事もランキング入りするかもしれませんよ!?
この記事の内容がみなさんの参考になれば幸いです。
あわせて読みたい
僕が過去に書いたQiita記事やブログ執筆のノウハウをまとめた記事の一覧です。
よかったらこちらもあわせて読んでみてください。