unshiu

最近の更新履歴

開発ルール‎ > ‎

コーディングルール


実際のコーディングに近い部分のルールをまとめます

コーディングの心得 五ヶ条

株式会社電通国際情報サービスによるJavaコーディング規約より:

一、見やすさを重視せよ
一、ネーミングはわかりやすく
一、サンプルを鵜呑みにしない
一、同じコードは二度書かない
一、役割は一つに

タスク・タグ

ソース内に以下のルールでタスク・タグをうつことが可能です。 Eclipseを利用している人は 設定 -> Java -> コンパイラー -> タスク・タグ で設定を変えられるので統一してください。 またこれ以外のオレオレタスク・タグはtrunkには適用しないようにしましょう。(各個人のブランチは自由にやって問題なし)

BUG

もしバグを発見し影響範囲が広いために即時修正をできない場合は必ずチケットを発行し、チケット番号を書いてください。 また必ず具体的な発生条件と詳細を記載してください。長くなる場合はチケットに書いた上で「詳細はチケットxxxxで」といった形にしてください。

例)

BUG: ○○の際に文字化けする。詳細は #999 

だめな例

BUG: なんかうまく動かないときがある

FIXME

重要度は低くバグではないが、修正が必要な箇所につける。 その際、必ず具体的な問題点を明示すること。 粒度的にはチケットが必要か微妙な場合があるが、もしチケットを必要とするほど大きなリファクタリングの場合は必ずチケット番号を記述する

例)

FIXME: レコード数が増加した際に対応できないため、別のアルゴリズムに変更した方がいい

だめな例

FIXME: あとで直す

MEETING

以下のような次回ミーティングで話し合うべき箇所につける。

  • 実装はしたが実装に不安なところ
  • 仕様として不明確な点があるところ
  • 大きく構成が変わる箇所があるため全員の認識をあわせる必要があるところ

命名規則

  • 原則として、英語を用いる。また、英語の対義語を意識する。
  • 原則として、単語の省略は行わない。

クラス/モジュール名

  • クラス/モジュール名は、PascalCase?とする。
  • HTTPなどの略語の場合は、すべて大文字のままとする。

正しい例:

module ExampleModule
# ...
end

class HTTPClient
# ...
end

誤った例:

module Example_Module
# ...
end

module EXAMPLE_MODULE
# ...
end

class HttpClient
# ...
end

class HTTPclient
# ...
end

class HTTP_Client
# ...
end

例外クラス名

  • 例外クラスのクラス名は、末尾にExceptionを付ける。

メソッド名

  • メソッド名は、underline_styleとする。
  • 真偽値を返すメソッドでは、動詞または形容詞に?を付け、形容詞にis_は付けない。
  • 破壊的なメソッドと非破壊的なメソッドの両方を提供する場合、破壊的なメソッドには!を付ける。

正しい例:

def add_something
# ...
end

def visible?
# ...
end

誤った例:

def addsSomething
# ...
end

def Add_Something
# ...
end

def is_visible
# ...
end

def is_visible?
# ...
end

定数名

  • クラス/モジュール名以外の定数名は、すべて大文字とし、単語の区切りに_(アンダースコア)を用いる。

正しい例:

EXAMPLE_CONSTANT = "foo"

変数名

  • 変数名は、すべて小文字とし、単語の区切りに_(アンダースコア)を用いる。
  • ローカル変数、インスタンス変数、クラスインスタンス変数、クラス変数、グローバル変数に適用する。

正しい例:

local_variable
@instance_variable
@@class_variable
$global_variable

ファイル名

  • ファイル名は、すべて小文字とし、単語の区切りに_(アンダースコア)を用いる。
  • ファイル中の主な定義クラス/モジュールの名前を変換したものをファイル名に使用する。
  • ジュールを名前空間として使用する場合は、ディレクトリを使用して階層構造を表現する。

正しい例:

# Fooクラスを定義
foo.rb

# HTTPClientクラスを定義
http_client.rb

# Foo::Barクラスを定義
foo/bar.rb

ソースコード全般

インデント

半角スペース2個

コメント

  • コメント記号(#)とコメントの間には、半角スペース1個を挿入する。
  • 容易に解釈できない場合を除き、メソッド定義の中にはコメントは記述しない。
  • クラス、モジュール、パブリックなメソッドには、仕様をRDoc形式で記述する。
  • メソッド定義の中にコメントが必要だと思われる場合は、コードのリファクタリングを行い、それでも必要な場合のみコメントを記述する。
  • 仕様変更で利用しなくなった、後の参考にしたい、もしかしたら復活するかもしれないメソッドやロジックをコメントアウトで放置しない
    • svnで管理されているので履歴はそちらで参照できる
    • 復活する場合もsvnを利用すれば簡単にそのバージョンのものを取得できる
  • 変更者名、変更日付などはsvnで管理されているので記述しない

クラス/モジュールの定義

クラス/モジュールの定義が3段以上ネストする場合は、ネストが深くなるのを防止するために、ネストの定義と実装を分離する。

module Foo
module Bar
class Baz
end
end
end

class Foo::Bar::Baz
def initialize
#...
end
end

メソッドの定義

メソッド定義の仮引数リストには括弧を付ける。ただし、引数がない場合は、括弧を省略する。

正しい例:

def foo(x, y)
# ...
end

def foo
# ...
end

誤った例:

def foo x, y
# ...
end

def foo()
# ...
end

クラスメソッドの定義

  • クラスメソッドの定義には基本的にはselfを使用する。
  • class << self...endといった記法はpluginなどのmodule内で必要とされる時以外では利用しない。
  • クラス名を用いる記法は利用しない。

正しい例:

class Foo
def self.foo
# ...
end
end

誤った例:

class Foo
def Foo.foo
# ...
end
end

class Foo
class << self
def foo
# ...
end
end
end

メソッド呼び出し

メソッド呼び出しの引数リストには括弧を付ける。ただし、引数がない場合は、括弧を省略する。 ただし、加算などの記号を用いたメソッド、後述する例外的なメソッドは括弧を省略しても良い。

正しい例:

foo(1, "abc")
obj.foo(1, "abc")
bar
print "x = ", x, "\n"

誤った例:

foo 1, "abc"
obj.foo 1, "abc"
bar()

例外的なメソッドは以下

  • IO#puts
  • IO#print
  • Kernel#p
  • Kernel#puts
  • Kernel#print
  • Kernel#require
  • Kernel#extend
  • Module#include
  • Module#attr_accessor
  • Module#attr_reader
  • Module#attr_writer

例外定義

メソッド全体にかかるような例外の場合、beginは省略する

正しい例:

def hoge
# 処理
rescue => ex

end

誤った例:

def hoge
begin
# 処理
rescue => ex

end
end

グローバル変数

グローバル変数を利用していると一つの変更の影響反意の想定がつかなくなるため、原則利用しない。

条件分岐

if/unless文のthenは省略する

正しい例:

if x > 0
puts "x > 0"
end

誤った例:

if x > 0 then
puts "x > 0"
end

unless の else はしない

unless
hoge = 'aaa'
else
hoge = 'bbb'
end

↑のようなものは↓のように書いたほうがわかりやすいです。

if
hoge = 'bbb'
else
hoge = 'aaa'
end

よくあるのが当初は unless だけだったのに後で問題があってelseを付け足してしまいこの形になることです。その場合はきちんと ソースを読み、リファクタリングしてください。

.zero?, .nil? 等を利用する

RailsのActiveSupport?の機能を活用してください。

正しい例:

if x.zero?  # x が 0 なら
puts "x == 0"
end

if x.nil? # x が nil なら
puts "x == nil"
end

誤った例:

if x == 0 
puts "x == 0"
end

if x == nil
puts "x == nil"
end

繰り返し

  • whileのdoは省略する。
  • hile !xのような否定を用いた式は、 until xに置き換える。

正しい例:

while cond
# ...
end

until cond
# ...
end

誤った例:

while cond do
# ...
end

while !cond
# ...
end

無限ループ

  • 無限ループにはKernel#loopを使用する。

正しい例:

loop {
# ...
}

誤った例:

while true
# ...
end

文字列リテラル

  • 文字列リテラルには基本的に"..."(ダブルクォート)を使用する。
  • 特殊文字を解釈させたくない場合のみ '...' (シングルクォート)を使用する。

do 〜 end と { } の使い分け

複数行に処理がまたがる場合は do 〜 end

hoge.each do 
hoge = 1
end

1行でかけるものは { } を使うようにしましょう。

hoge.each { hoge = 1 }

model

railsに乗る

  • 主キーとなる id を定義する
  • created_at, updated_at を定義する

→作成時、更新時に自動的に値が更新される

acts_as_paranoid は必ず定義する

アプリケーション全体として論理削除を基本としているので

SQLインジェクションを注意する

具体的には以下のように変数を展開する方式は利用しない。

Hoge.find(:all, :conditions => [" id = #{hogehoge} " ])

以下のように必ずパラメータを使うようにする。
この場合、railsがサニタイジングを行ってくれる。サニタイジングが不要な場合(ユーザから値をうけとるのではなく、内部的な値を利用する場合)でもコードの統一性と安全性からこちらの方法を使う

Hoge.find(:all, :conditions => [" id = ? ", hogehoge])
hoge.find(:all, :conditions => [" id = params[:hogehoge]", :hogehoge => '1']

また複雑なSQLを手動で組み立てる場合等で上記の方法を使えない場合は必ず個別にサニタイジングをすること。

レコード制約は必ずvalidate定義をする

テーブルのNull制約、文字列長制約を適切に設定することは必須だが、値のチェックはvalidate定義で行いテーブル制約任せにせず必ず定義 すること。またvalidate定義を書いていても、アプリケーション以外で値の更新が行われる(コンソール、もしくは他システム)場合に仕様外の値がま ぎれこむことを防ぐため各レコードの制約も適切に行う。

カラム名ルールを統一する

カラム名は用途、データ型別の以下のルールに従って付けること

データ型用途補足カラム名ルール
datatime全般 _at を語尾につける
datatime作成日付created_at
datatime更新日付updated_at
datatime削除日付deleted_at
boolean全般 _flag を語尾につける
intステータス値など _stats を語尾につける

find結果が単数か複数かを考慮してメソッド名をつける

単数なら

find_hoogehoge_base_user

複数なら

find_hogehoge_base_users

トランザクション

以下の場合は必ずトランザクションを利用し、データベースの整合をとること。

  • ポイントが絡む処理全般
  • 処理に失敗した際にユーザで状態を復旧できない、または失敗に気がつけない場合
  • データのインポートなど都度コミットによりパフォーマンスの低下が懸念される場合

controller

filter

利用用途

  • 認証などactionが呼ばれる前に事前に行いたいこと

こんなのには使わないよ!

  • 単純に処理を共通化したい場合
    • 普通にprivateメソッドを作成する

命名規則

  • フィルタリングする意味をメソッドにもたせる

ある権限などが必要なとき

xxxx_required

例)

#オーナー権限が必要なとき
owner_rquired

#管理者権限が必要なとき
admin_required

よくない例

access_filter
→ authorized_user_required # アクセス権限のチェックをしているので
deletable_filter
→ authorized_delete_required # 削除権限をチェックしているので

only, except

  • メソッドが増えた際に、追加する確率が少ないものを選択する(ただしあまりに対象メソッドが増える場合は、要検討)
  • 権限が絡む場合は追加する確率や対象メソッドの数を無視し、もしメソッドが増えた際に設定もれがあっても問題が発生しない確率が高い方を選 ぶ。(ある特定のユーザしかアクセスできないactionがあった際、アクセスできないことはバグとしてすむが、アクセスできてしまった場合は、同じバグ でもセキュリティホールという扱いを受け、ユーザ心理的にも、運営者側にも心象が悪いため)

view

W3C の XHTML 1.0に準拠した正しいHTMLを意識する。

具体的には幅をとるためだけに<br/>タグを使う、リスト表示するべきところを<ul>タグを利用しない で<p>タグや<br>タグでそろえるなどは仕様上正しくありません。特にPCで閲覧する画面に関してはSEOの視点、保守性か らも準拠していることは重要です。なお携帯viewの場合利用できるタグに制限があるため、必ずしも準拠することはできませんが、HTMLタグの最適化は やはりSEOに関わるので意識する必要があります。

インデントや見やすさを考慮する

controllerやmodelでインデントしない人は滅多にいませんが、rhtmlになった途端、意外とおろそかにしがちです。 ロジックをかかなくてもrailsのテンプレートエンジンの構造上 if 文や繰り返しなどはつかわれるため、 きちんとインデントされているかされていないかでも相当、コードを読んだり機能を追加するときに差があります。 viewもコードとみなして最低限の見やすさを考慮してください。

リスト表示をする場合

  • リストを表示する際に該当データがない場合は必ず「該当する○○はありません。」等のメッセージを表示をします。
  • ページネイトはヘッダーとフッター両方、設定してください。
  • 該当データがない場合、該当データがある場合の順番で書いてください。

正しい例:

<% if @hoge.size.zero? %>
該当する○○はありません。
<% else %>
<%= paginate_header @hoge %>

<% @hoge.each do |foo| %>
# リスト表示
<% end %>
<%= paginate_links @hoge %>
<% end %>

誤った例:

<% if @hoge.size > 0  %>
<%= paginate_header @hoge %>

<% @hoge.each do |foo| %>
# リスト表示
<% end %>
<%= paginate_links @hoge %>
<% else %>
該当する○○はありません。
<% end %>

JavaScript?

可能な限りjQuery記法を利用する

特別の理由がない限り生のJavaScript?のコードを書くことは禁止です。

正しい例:

$('#abcd')

誤った例:

document.getElementById("abcd");

jsdoc-toolkit形式にそってドキュメントを書く

特にutil的な使われ方をするものには必ず記述してください。書式、使い方はjsdoc-toolkitを参照のこと。

lib

参考