493
353

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

「よいサンプルコード」ってどんなサンプルコード? 〜Qiitaや技術ブログを書くときに気を付けること〜

Last updated at Posted at 2020-01-09

はじめに

Qiitaやブログに技術記事を書く場合は多かれ少なかれ、サンプルコードを書くと思います。
たかがサンプルコード、されどサンプルコード。
技術記事に書くサンプルコードはどうあるべきなのでしょうか?

いろいろな観点があると思いますが、この記事では僕が考える「よいサンプルコード」について語ってみようと思います。

なお、この記事のサンプルコードはRubyで書いていますが、記事の内容自体はRubyに限らずどんな言語にも適用できるものです。

どういったサンプルコードが理想的なのか(大雑把なレベルで)

細かいポイントの説明に入る前に、大雑把なレベルで理想的なサンプルコードについて確認しておきましょう。
以下は僕が考える理想的なサンプルコードです。

  • 読み手(=見知らぬ第三者)のことを一番に考えて書かれている
  • 読み手がすっと理解できるコードになっている
  • 読み手(特に初心者)を正しい方向に導くコードになっている

上の条件をひっくり返すと、あまり望ましくないサンプルコードの定義が浮かび上がります。

  • 自分のことしか考えていないコードになっている
  • 読み手が首をかしげたり、理解するのに時間がかかったりするコードになっている
  • 初心者がそのコードを何も考えずコピペすることで、バッドプラクティスやセキュリティ的に問題があるコードを広めてしまう恐れがある

では、以下で「理想的なサンプルコード」を満たすための条件を具体的に見ていきます。

「当たり前品質」を満たしていること

サンプルコードは「当たり前品質」を当たり前に満たしておくべきです。
具体的には以下のような要件を満たしておく必要があります。

インデントが正しいこと

# ifに対応するendのインデントがおかしい
def some_method
  if foo?
    # ...
end
end
# OK(インデントが正しい)
def some_method
  if foo?
    # ...
  end
end

また、インデントさせるときはタブ文字よりも半角スペースを使う方が良いです。

適切な場所で改行したり半角スペースを挟んだりすること

# 半角スペースの使い方に一貫性がない
a= [1,2 ,3]
# OK(半角スペースの使い方に一貫性がある)
a = [1, 2, 3]

その言語の一般的な命名規則に従っていること

# Rubyのメソッド名をアッパーキャメルケースで定義することはめったにない
def SomeMethod
  # ...
end
# OK(Rubyのメソッド名はスネークケースで書くことが一般的)
def some_method
  # ...
end

文法的に正しいこと

コピペするだけで動くサンプルコードになっていることが理想です。

# ifに対応するendがない
def some_method
  if foo?
    # ...
end
# OK
def some_method
  if foo?
    # ...
  end
end

ついうっかりコードコメントを違う言語の形式で書いてしまったりする人も見かけるので注意してください。

// NG!! (JavaScriptの行コメントはシャープではなくスラッシュ2つ) 
function add(a, b) {
  # 2つの数字を加算する
  return a + b;
}

しれっと全角文字を混在させないこと

考え方としては先ほどの「文法的に正しいこと」の一種になります。
ときどき全角文字が紛れ込んでいるサンプルコードを見かけますが、こうしたコードは良くないです。

以下は文字列を囲むシングルクオートと、インデントのためのスペースが全角スペースになっている例です。(Qiitaで表示すると全角の部分が赤い下線で警告されます)

# シングルクオートとインデントのスペースが全角になっている
if name == Alice
 # ...
end

当然コピペしても動かないですし、読み手も「言いたいことはわかるけど、なんか気持ち悪い」と強い違和感を抱くので、全角半角を正しく使い分けましょう。

# OK
if name == 'Alice'
  # ...
end

ここで挙げたような「当たり前品質」を満たしているかどうか自信がない初心者の人は、その言語に対応したLintツールを通すことを検討してみてください。

嘘をつかないこと

サンプルコードをコピペして実行したときに、説明している内容と同じ結果になっていることを確認しましょう。
そうならないサンプルコードは嘘をついているサンプルコードになります。

たとえば、下のコードは掛け算をしているのにaddというメソッド名になっています。
なので、add(2, 3)で5が返ってくることはありません。

# addなのに掛け算?
def add(a, b)
  a * b
end

add(2, 3)
#=> 5

a * bではなく、a + bにすれば正しいコードになります。

# OK(+にすれば正しい)
def add(a, b)
  a + b
end

add(2, 3)
#=> 5

紛らわしい嘘コードを書かないこと

上に書いた「嘘をつかないこと」の一種ですが、このようなパターンもあります。
たとえば、以下のようなサンプルコードがあったとします。

# 一見問題なく見えるコードですが・・・
def update
  if @ticket.update(ticket_update_params)
    redirect root_path, notice: '降車しました。'
  else
    render :edit
  end
end

おそらくRuby on Railsのサンプルコードだと思うのですが、よく見るとRailsプログラマが「そんなメソッドあったっけ?」と思うようなコードが紛れ込んでいます。

# ん、redirectメソッドって何??
redirect root_path, notice: '降車しました。'

これは次のようにredirect_toと書くのが正解です。

# OK(redirect_toが正しい)
redirect_to root_path, notice: '降車しました。'

サンプルコードをいろいろ編集しているうちにうっかり間違えてしまったのだと思いますが、読み手は「あれあれ??」と混乱してしまうので、なるべくこういうミスは避けるようにしたいものです。

ブラウザのテキストエリア内でサンプルコードをいじくるとこういったミスが発生しやすいので、なるべく「実際に動くコード」を編集するようにして、最後に「ちゃんと動いたコード」をエディタやIDEからテキストエリアにコピペするのがお勧めです。

実行結果も一緒に載せること

コードだけ見せても、読み手は実行結果がぱっと予想できないことがあります。
(予想はついても確信が持てないこともあります)
ですので、実行結果も一緒に載せるようにしましょう。

たとえば、「10進数のRGBカラーコードを16進数の文字列に変換するメソッドを作りました」という説明とともに下のコードだけを見せられても、読み手は「🤔」となってしまいます。

# このメソッドの使い方や実行結果がぱっとわかりますか?
def to_hex(r, g, b)
  [r, g, b].inject('#') do |hex, n|
    hex + n.to_s(16).rjust(2, '0')
  end
end

実行結果も一緒に示せば、「ほうほう、なるほど😄」と読み手もすぐに納得してくれます。

to_hex(0, 0, 0)       #=> #000000
to_hex(255, 255, 255) #=> #ffffff
to_hex(4, 60, 120)    #=> #043c78

もし画面上の見た目や動きが重要なサンプルコードであれば、以下のようにそのコードを実行したときのスクリーンショットを載せるのも有効です。

Screen Shot 2020-01-24 at 9.43.26.png

さらに、画面の動きをわかりやすく説明するために、アニメーションGIFを貼り付けておくのもひとつの手です。
僕はアニメーションGIFの作成にRecorditというツールを愛用しています。
以下はRecorditを使って作成したアニメーションGIFの例です。
OeXTaZPsSp.gif

コラム:参考にしたコードがあれば出典を明記すること

コードのわかりやすさと直結する話ではありませんが、書籍やネットからコードをコピペした(または一部改変した)場合は出典を明記しましょう。

# 以下のコードは「プロを目指す人のためのRuby入門」4.6.2項からの引用です
def to_hex(r, g, b)
  [r, g, b].inject('#') do |hex, n|
    hex + n.to_s(16).rjust(2, '0')
  end
end

参考:Qiitaで記事を公開するときに気を付けるべきマナーについて 〜無断でネットや書籍の内容を丸写しするのはやめよう〜 - Qiita

コードブロックやシンタックスハイライトを有効活用すること

Qiitaをはじめ、技術記事の執筆を支援しているブログサイトやWebサービスはコードブロックやシンタックスハイライトが使えるようになっています。
コードブロックやシンタックスハイライトを活用することで読みやすさが格段に変わってくるので、上手に活用しましょう。

以下はコードブロックもシンタックスハイライトも使わない例です。
(インデントは無視されます)

def to_hex(r, g, b)
[r, g, b].inject('#') do |hex, n|
hex + n.to_s(16).rjust(2, '0')
end
end

以下はコードブロックを使った例です。(シンタックスハイライトは無し)

def to_hex(r, g, b)
  [r, g, b].inject('#') do |hex, n|
    hex + n.to_s(16).rjust(2, '0')
  end
end

以下はさらにRubyのシンタックスハイライトを加えた例です。

def to_hex(r, g, b)
  [r, g, b].inject('#') do |hex, n|
    hex + n.to_s(16).rjust(2, '0')
  end
end

コードブロックの左上にファイル名を表示させることもできます。

lib/rgb.rb
def to_hex(r, g, b)
  [r, g, b].inject('#') do |hex, n|
    hex + n.to_s(16).rjust(2, '0')
  end
end

Qiitaであれば、以下のページにMarkdown記法の使い方がまとまっているので、必ずチェックしておきましょう。

Markdown記法 チートシート - Qiita

なお、技術記事の執筆を支援しているブログサイトやWebサービスではMarkdownを使って書けるようになっていることが多いですが、サイトごとに微妙に異なる「方言」を持っているので、各サイトのヘルプページを確認しておく方が良いです。

補足1:コードやエラーメッセージをスクショ(画像)にしないこと

たまにサンプルコードをスクリーンショットにして載せる人がいますが、画像だと他の人がそのコードをコピーできないですし、スマホで見たときに極端に見にくくなったりすることがあります。
ですので、サンプルコードは必ずテキスト(とコードブロック)で書くようにしましょう。

↓ 画像にすると他の人がさっとコピーできないのでダメ!!🙅🏻‍♂️
Screen Shot 2020-01-13 at 7.51.54.png

スクショを使う理由として「強調のための下線や赤丸を入れたいから」という理由があるのかもしれませんが、そこはコメントをうまく活用してください。

def to_hex(r, g, b)
  [r, g, b].inject('#') do |hex, n|
    # 強調したいことがあれば、コメントで書こう!!
    hex + n.to_s(16).rjust(2, '0')
  end
end

これに似た話として、エラーの説明をするためにエラー画面をスクショで載せる人もよく見かけます。
ですが、これも他の人が情報をコピーしたり、画面上で内容を確認したりすることを難しくします。

↓ エラー画面も画像にするといろいろ不便!!🙅🏻‍♂️
Screen Shot 2020-01-13 at 8.08.04.png

ですので、エラーメッセージやスタックトレースもテキストとして載せるようにしてください。
(もしくはエラー画面のスクショと併用してください)

ちなみにRuby on Railsであれば通常、logs/development.logにエラー内容がログ出力されているはずなので、この内容をコピペして貼り付けるのがベストです。

logs/development.log
Started GET "/" for 127.0.0.1 at 2020-01-13 08:09:44 +0900
Processing by HomeController#index as HTML
Completed 500 Internal Server Error in 0ms

ZeroDivisionError (divided by 0):
  
app/controllers/home_controller.rb:6:in `/'
app/controllers/home_controller.rb:6:in `index'

また、エラーメッセージと一緒にエラーが発生したコードも載せておきましょう。
エラーに関する情報は、「エラーメッセージとスタックトレースと原因となったコード」の3点セットになっていないと役に立たないことが多いです。

class HomeController < ApplicationController

  skip_before_action :authenticate_user!

  def index
    a = 1 / 0
  end
end

補足2:本文中の一部にコードを登場させるときはバッククオートで囲むこと

本文中の一部にコードを登場させるときは、バッククオートで囲むようにしましょう。
バッククオートで囲むとフォントが等幅フォントになり、文字背景もグレーになってコードが読みやすくなります。

Rubyで変数に値を代入する場合は`a = 0`のように書きます。

また、@jnchitoのようにアットマーク付きのコードをバッククオートで囲まずに本文に載せると、「Qiitaのjnchitoさん」にメンションを飛ばしたり、本文に「jnchitoさん」へのリンクを貼ったりすることになってしまいます。
必ずバッククオートで囲むようにしましょう。

以下のコードに出てくる`@jnchito`はRubyのインスタンス変数です。

補足3:長いコードはバッククオートで囲まずコードブロックを使うこと

ただし、バッククオートで囲むのは変数名やメソッド名、単純なコマンドなど、ごく短い場合だけにしましょう。
こんなふうに CONFIGURE_OPTS="--with-readline-dir=`brew --prefix readline` --with-openssl-dir=`brew --prefix openssl` --with-iconv-dir=`brew --prefix libiconv`" rbenv install 2.2.1 長すぎるコマンドだと、行の折り返しが発生して読みにくくなります。

1行に収まらないような長いサンプルコードやサンプルコマンドは、次のようにコードブロックを使うようにしてください。

# OK(長いサンプルコマンドはコードブロックを使う)
CONFIGURE_OPTS="--with-readline-dir=`brew --prefix readline` --with-openssl-dir=`brew --prefix openssl` --with-iconv-dir=`brew --prefix libiconv`" rbenv install 2.2.1

とはいえ、コードブロック内で横スクロールが発生するのも読みづらいので、本来は1行で書いて良いコードを、あえてコードブロック内で改行させるのもありです。

# OK(読みやすさを考えて、あえて改行させる。ただし、コピペして動く形式で)
CONFIGURE_OPTS="\
  --with-readline-dir=`brew --prefix readline` \
  --with-openssl-dir=`brew --prefix openssl` \
  --with-iconv-dir=`brew --prefix libiconv`" \
  rbenv install 2.2.1

補足4:言語を正しく指定すること

シンタックスハイライトを利用する場合、言語を正しく指定しましょう。
たとえば以下はerbのコードですが、言語で"html"を指定しているため、「文法的におかしい」という意味の赤線が表示されています。

<p><%= @user.name %></p>

適切に"erb"を指定すれば赤線は表示されなくなります。

<p><%= @user.name %></p>

文章とコードの比率に気を付けること(理想は50:50)

記事内の文章とコードの比率も意識しましょう。

文章ばかりでコードがほとんどない技術記事は、読み手が頭の中でコードをイメージしなければならないので、読み手が苦労します。
また、具体的なコードを見せないと、筆者の意図が読み手に正しく伝わらない可能性もあります。

反対に、コードばかりで文章がほとんどない技術記事は、そのコードが何を意味しているのか、筆者がそのコードからどんなことを伝えようとしているのか、といったことを読み手が想像しなければなりません。
これもまた読み手に負担を強いることになります。

僕個人が考える、理想的な文章とコードの比率は50:50です。
つまり、文章とコードの分量が半々になっている技術記事が、読み手が最も理解しやすいのではないかと考えています。

言語やライブラリのバージョンを明記すること

プログラミングの世界は移り変わりが激しいので、時間が経つと「以前は正しかったが、今はそうではない」ということがありえます。
もしくは実行環境に強く依存する技術情報だと「自分の環境では動くが、他の人の環境では動かない」ということも発生します。

ですので、技術記事には以下のような情報も載せておくことが望ましいです。

  • 言語のバージョン
  • フレームワークのバージョン
  • ライブラリのバージョン
  • OSのバージョン
  • RDBMSの種類(MySQL、PostgreSQL、Oracle等)とバージョン

特にSQLはRDBMSごとの方言や独自関数がたくさんあるので、どのRDBMSを使っているか明記しないと「記事の通りSQLを書いてみたが、エラーになった」という問題が発生しやすいです。

大文字小文字の使い分けや、スペルミスにも気を付ける

言語やライブラリ、サービス名・社名等の大文字小文字の使い分け、スペルミスといった表記ミスにも気を遣いましょう。
表記があまりにもおかしいと、記事の説得力が弱まったり、当事者(ライブラリの開発者や、サービスを運営している企業の社員さんたち)の心象を悪くしたりします。

  • × JAVA / ○ Java
  • × Rspec / ○ RSpec
  • × Device / ○ Devise (Ruby用の認証ライブラリ)

確信がないときは公式ドキュメントや会社のホームページを見に行って、正しい表記を確認しましょう。

説明に必要なコードやスタックトレースを一通り載せること

あるテーマを説明するために必要なコードは一通り載せましょう。
関連するファイルが複数あるなら、そのファイルは全部載せてください。
エラーの解決策を載せる場合はスタックトレースも載せた方が良いです。

特に、エラーの解決策を説明する記事でよく見かけるのが、「そのコードだけ見せられても因果関係がよくわからない」というパターンです。

たとえばこんな感じです。

(タイトル)RSpecでNoMethodErrorが出た場合の対処法

RSpecを実行したらNoMethodErrorが出ました。
この場合はletをlet!に変えると直ります。

let!(:book) { FactoryBot.create(:book) } 

上のようなサンプルコード(というか記事そのもの)だと、どこでどういうエラーが起きたのかわかりません。
なぜletlet!に変えるとエラーが出なくなるのかもわかりません。
そもそも発生した問題と解決策が飛躍しすぎているため、読者に因果関係が伝わらず、読者はその記事を活用しようにも活用できません。

ですので、次のように因果関係を明確にし、必要なコードやスタックトレースを一通り載せた記事を書くようにしましょう。

(タイトル)RSpecでletを使うとNoMethodErrorが出るケース

RSpecを実行したらNoMethodErrorが出ました。

(発生したエラーのスタックトレースを載せる)

エラーが発生していたのはviewのこの行です。

(エラーが発生していた周辺のコードを載せる)

今回、僕はRSpecでこんなテストを書いていました。

(エラーが発生したテストコードを載せる)

なぜエラーが起きていたのかというと、(その原因を説明する)からです。
なので、letをlet!に変更するとこのエラーを解決できました。

let!(:book) { FactoryBot.create(:book) } 

因果関係はとっても大事

その記事を書いた本人が因果関係を理解できていない場合、かえって状況を悪化させるような内容を書いてしまう恐れもあります。
そうならないように、問題を解決するタイプの記事は必ず因果関係を明確にしておきましょう。

ブラウン管でできた昔のテレビで例えるなら、

テレビが映らなくなりました
 ↓
よくわからないけど、3回強く叩いたら直りました!
(ちょっと待って、最悪本当に壊れちゃうよ?)

・・・ではなく、

テレビが映らなくなりました
 ↓
いろいろ調べた結果、テレビ本体に取り付けたアンテナ線の接触が悪いことがわかりました(原因)
 ↓
アンテナ線をしっかり差し込んだら直りました!(解決策)

こういう記事を書いた方が良い、ということです。

コラム:仕事で書いたコードをコピペしないこと

仕事で書くコードは通常、社外秘になっているはずです。
ですので、仕事で書いたコードはそのままコピペせず、自分なりにアレンジしてうまくボカしましょう。
その際はできるだけこの記事に書いたチェックポイントに注意しながら執筆することをお勧めします。
(ボカそうとした結果、誰の役にも立たないサンプルコードを書いてた、ということがないように)

コラム:デタラメなドメインをメアドに使わないこと

test@hoge.comaaaa@bbb.comのようなメアドはデタラメに書いたつもりでも実在するドメインだったりすることがよくあります。
無用なトラブルを避けるために、サンプルコード中のメアドは@hoge.com@bbb.comではなく、@example.comで統一しましょう。

詳しくは以下の記事をご覧ください。

思わぬ事故防止!開発時やテスト時に使用するメアドのドメインは example.com に統一しよう - Qiita

続いて、ここから下のセクションでは「言うは易く行うは難し」で、場合によってはクリアするのが少し難しいかもしれないチェックポイントを書いていきます。

【やや難】コピペすれば動くコードになっていること

理想は「コピペすればすぐ動く」状態のサンプルコードになっていることです。
もし、別のライブラリをrequireしたりimportしたりする必要があるなら、それもコードに載せておきましょう。

# Ruby(Rails環境ではない素のRuby)はいきなりDateクラスを使おうとするとエラーになる
Date.today
#=> NameError (uninitialized constant Date)
# OK(dateライブラリをrequireすれば動く)
require 'date'
Date.today
#=> #<Date: 2020-01-13 ((2458862j,0s,0n),+0s,2299161j)>

ただし、大きなプログラムのごく一部を切り出した場合など、説明する内容によってはコピペするだけで動くサンプルコードにすることは難しい場合があります。
ですので、これは「可能ならそうする」という努力目標で構いません。

コード全体を載せられない場合は省略されていることがわかるようにすること

しかし、コード全体を載せられない場合でも省略したことがわかるようにしたり、省略した内容をコメントで補足したりすると、より読み手に優しいサンプルコードになります。

# ...を使って前後に省略した行があることをほのめかす
RSpec.configure do |config|
  # ...
  config.include FactoryBot::Syntax::Methods
  # ...
end
# ↓架空のメソッドをコメントで説明する例

# call_apiは外部APIを呼びだして結果をハッシュで返す架空のメソッド
result = call_api
case result
in {status: :success}
  "Success!"
in {status: :error, message: message}
  "Error: #{message}"
end

【やや難】意味のあるコードや実践的なコードを書くこと

foo、barやhoge、piyoといった用語しか並んでいないサンプルコードは、「そのコードでいったい何をしようとしているのか」「そのコードがどういうときに役立つのか」ということを理解しづらくなります。

以下はfoo、barみたいなクラス名や変数名しか出てこないサンプルコードの例です。
(ここではインスタンス変数の使い方を説明するコード例と仮定します)

class Foo
  attr_accessor :bar

  def initialize(bar)
    @bar = bar
  end

  def hoge(s)
    puts @bar + "\n" + s
  end
end

Foo.new('abc').hoge('xyz')
#=> abc
#   xyz

以下はfooやbarを使わずに、上のコードを多少意味のある形にしたサンプルコードの例です。

class Printer
  attr_accessor :header

  def initialize(header)
    @header = header
  end

  def print(s)
    puts @header + "\n" + s
  end
end

Printer.new('Page 1').print('Hello, world!')
#=> Page 1
#   Hello, world!

fooやbarしか使わないコードに比べれば、後者の方がまだコードの意図が理解しやすいのではないでしょうか。

理想としては、読み手が「なるほど、そりゃ便利だわ!」とか「あー、そういうこと、よくあるよね!」と思ってくれるようなサンプルコードを提供することです。

が、そういったサンプルコードを考えるのはなかなか骨が折れるのも確かです。

ごく単純なサンプルコードであればfooやbarを使うのもアリ

fooやbarのような意味のないサンプルコードはなるべく避けるべきですが、ごく単純なサンプルコードであれば使っても問題ありません。

たとえば、以下は「Rubyのメソッド定義は値を返す」ということを説明するサンプルコードです。

name = def foo; end
name #=> :foo

上のコードにはfooが出てきますが、このサンプルコードは「メソッド定義が値を返す(その値は別に何でもよい)」ということを説明したいだけなので、fooを登場させても問題ありません。

この記事の冒頭でも書いたように「読み手がすっと理解できるコードになっていること」がサンプルコードの目的なので、fooを使っても理解のしやすさに悪影響がないと思ったときはfooやbarを登場させるのもアリです。

【やや難】できるだけシンプルなコードで説明すること

難しい内容を難しいまま提示しても、読み手はなかなか理解できません。
理想的なサンプルコードは、難しい内容を筆者が頭の中で上手に噛み砕き、説明したいトピックを最もシンプルな形で読み手に提示することです。

ですが、"Simple is not easy"とよく言われるように、シンプルさを追求することもまた、非常に骨が折れます。

簡単な内容から徐々に高度な内容へ発展させていくアプローチ

こういう場合は、すべての概念を1つのシンプルなコードで表現するのは至難の業なので、シンプルなコードを徐々に進化させていき、最終的に必要な知識を読み手に与える、というのがアプローチの1つです。

以下は以前執筆した「使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」」という記事からの抜粋です。

一番最初は以下のように最も単純なサンプルコードを使ってRSpecの構文を説明します。

RSpec.describe '四則演算' do
  it '1 + 1 は 2 になること' do
    expect(1 + 1).to eq 2
  end
end

これを徐々に進化させていき、以下のような構文を理解できるような説明の仕方をしました。

RSpec.describe '四則演算' do
  describe '足し算' do
    it '1 + 1 は 2 になること' do
      expect(1 + 1).to eq 2
    end
  end
  describe '引き算' do
    it '10 - 1 は 9 になること' do
      expect(10 - 1).to eq 9
    end
  end
end

より詳しく知りたい場合は元記事を参照してください。

使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」 - Qiita

【やや難】バッドプラクティスやセキュリティ的に問題があるコードを書かないこと

自分の書いた技術記事はどこの誰が読むかわかりません。
熟練者から「ほとんど○○のことを知らない初心者さん」まで、いろんな人が自分の記事を読みに来ることが予想されます。

このとき、熟練者の人はまだ良いのですが、初心者さんは何も考えずに記事に載っているサンプルコードをコピペしてしまう可能性があります。
もし、サンプルコードがあまり好ましくないコードになっていると、そのコードがそのままあっちこっちに拡散してしまうことになります。

ここで1つ、具体例を出しましょう。
以下はRubyの例外処理を説明した"BADな"コード例です。

# Rubyの例外処理について説明している
# (が、コードとしてはあまりよくない)
begin
  some_method
rescue Exception => e
  puts "例外が発生しました: #{e}"
end

上のコード例ではExceptionクラスをrescueしています。
ですが、Rubyでは通常のプログラムで発生する可能性の高い例外はStandardErrorとそのサブクラスに束ねられているので、rescueするのはStandardErrorとそのサブクラスに限定すべきです。
Exceptionクラスを指定すると、通常回復不能な例外までrescueしてしまう恐れがあります。

さらに、StandardErrorとそのサブクラスをresuceしたい場合はrescue節に明示的に例外クラス名を書く必要がありません。

よって、例外処理を書くのであれば次のように書く方が適切です。

# OK(改善したくなる部分はまだあるが、さきほどのコードよりはマシ)
begin
  some_method
rescue => e
  puts "例外が発生しました: #{e}"
end

参考:Railsアプリケーションにおけるエラー処理(例外設計)の考え方 - Qiita

セキュリティ的に問題があるコードを書いてしまわないことも重要です。
ベタな例ですが、次のようなSQLインジェクションを引き起こすようなコードをサンプルコードとして載せるのはいけません。

# こんなふうにSQLインジェクションを引き起こすコードを書いてはいけない
User.where("email = #{params[:email]}")
# OK(SQLインジェクションは発生しない)
User.where(email: params[:email])

というわけで、みなさんもバッドプラクティスと見なされるようなコードやセキュリティ的に問題があるコードはサンプルコードとして書かないようにしましょう・・・と口で言うのは簡単なのですが、わざわざ「バッドプラクティスやセキュリティ的に問題があるコードを書いてやろう」と思って書く人は誰もいないですよね。

何がGOODで、何がBADなのかは、よっぽどの熟練者でないと自分で判断が付かないと思うので、このチェックポイントをクリアするのはなかなか難しいかもしれません。

参考:どうすれば問題があるコードを避けられるか?

RubyであればRuboCopBrakemanのようなツールである程度バッドプラクティスやセキュリティ的に問題があるコードを検出できるかもしれません。

Webアプリケーションのセキュリティ全般に関わる話であれば、いわゆる「徳丸本」や、Railsガイドのセキュリティガイドのページを読んで勉強しておきましょう。
こうした知識は技術記事を書く書かない、にかかわらず、エンジニアとして身につけておくべき大事な知識になります。

【やや難】説明の対象が何によって実現されているのか、ちゃんと理解すること

説明したい機能や仕組みが何によって実現されているのかをちゃんと理解できていないと、「合っているようで微妙に間違っている説明」をしてしまうことがあるので要注意です。

たとえば、Ruby on Railsであれば、RailsがRubyの標準ライブラリの機能を拡張しています。
具体例を挙げると、以下のblank?メソッドはRails(厳密にはActive Support)が独自に実装したメソッドです。

# blank?メソッドはRailsが独自に機能拡張して実装したメソッド
"".blank?    #=> true
"foo".blank? #=> false

もし、Rails以外の環境でblank?メソッドを実行しようとするとエラーが発生します。

# 素のRuby環境ではblank?メソッドは使えない
"foo".blank?
#=> NoMethodError (undefined method `blank?' for "foo":String)

ですので、上のようなサンプルコードを持ち出して「Rubyの便利メソッドを紹介します」と説明するのは、微妙におかしいです。
なぜなら、blank?メソッドはRubyが標準で提供している機能ではないからです。
この場合であれば、「Railsの便利メソッドを紹介します」と述べる方が適切です。

初心者の人は何が言語標準で、何がライブラリやフレームワークによって拡張された機能なのか、ぱっと識別できないかもしれません。
ですが、それでも「その機能が何によって実現されているのか」をできるかぎり意識して、「合っているようで微妙に間違っている説明」をしないように心がけてほしいと思います。

【やや難】おかしな英語を使わない

これも非常に難しいですね。サンプルコードには変な英語を使うな、という話です。
難しい話ではあるのですが、最低限、配列は複数形で表す、ぐらいのルールは守ってほしいかなと思います。

# えっ、userって単数形なのに配列なの!?
user.each do |u|
  # ...
end
# OK(複数形になっていれば、自然と配列であることがイメージできる)
users.each do |u|
  # ...
end

それ以外は「なるべく気を付けましょう」としか言いようがありません。
僕自身も「お前は絶対100点満点の英語を使っているのか?」と聞かれたら、決してそんなことはないと思いますし。
でも、普段からおかしな英語を使わないように気を付けているのは確かです。

なお、ソースコードと正しい英語については以前こちらの記事にいろいろ書いたので、参考にしてみてください。

モデルやメソッドに名前を付けるときは英語の品詞に気をつけよう - Qiita

まとめ

というわけで、この記事ではQiitaのような技術記事において、サンプルコードはどうあるべきか?という話題について論じてみました。

この記事に書いたチェックポイントをすべて満たそうとすると、1つの記事を執筆するのにかなり時間がかかると思います。
ですが、僕自身は技術記事や技術書を執筆する際にはいつもこうした点に注意しています。

全員が必ず従わなければいけないとは言いませんが、普段あまり深く考えずに技術記事を書いている人は、1つの考え方として参考にしてもらえると幸いです😃

あわせて読みたい

技術記事の執筆やサンプルコードのあり方について、僕がこれまでに書いた記事やスライドです。
よかったらこちらもどうぞ。

493
353
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
493
353

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?