Más contenido relacionado
La actualidad más candente (20)
Similar a 魂のコーディング (20)
魂のコーディング
- 3. p 経歴
p 2005〜2008:
女子大非常勤講師
p 2008〜2014:
組み込み系エンジニア、アーキテクト
p 2014〜
:
i3Systems,
inc.
@
福岡
p Ruby/Rails/インフラエンジニア
p ソーシャル
p t:
@devchick99
p f:
daisuke.tasaki.7
※本資料は私自身の見解であり、必ずしも私の所属する組織、立場、戦略、意見を代表するものではありません。
- 4. p i3Systemsが自社開発するモバイルデバイス管理システム
p Ruby
on
Rails製
p モデル数:
356個
p コントローラ数:
294個
p モバイルデバイスをリモートで運用/管理
p デバイス情報の取得・閲覧
p デバイス機能の設定・制限
p ネットワーク設定の一括配信
p アプリ配布ポータル
p デバイスのロック、データ消去
p モバイル管理(MDM/MAM/MCM)市場4年連続シェアNo.1(※)
※出典:
「ミック経済研究所・ITリポート2014年12月号」
「ミック経済研究所・コラボレーション/コンテンツ・モバイル管理パッケージソフトの市場展望
2013年度版」
2011年度、2012年度、2013年度出荷金額実績および2014年度出荷金額予測
- 6. #
コマンドが有効なバージョンかチェックする
def
enable_app_version?(app_version,
command_app_version)
if
ApplicationModel.check_ver_isnew(app_version,
command_app_version)
||
app_version.to_f
==
command_app_version.to_f
return
true
else
return
false
end
end
- 8. p check_ver_isnewメソッドはおそらく新しかったら
trueを返すのだろう
p でもどっち!?
どっちが新しいとき?
同値だったらどうなんの?
p その後のto_fしてるのはなに?
小数点込みはダメなん!?
#
コマンドが有効なバージョンかチェックする
def
enable_app_version?(app_version,
command_app_version)
if
ApplicationModel.check_ver_isnew(app_version,
command_app_version)
||
app_version.to_f
==
command_app_version.to_f
return
true
else
return
false
end
end
- 9.
if
tmp_new[idx].nil?
rtn
=
false
break
end
str_new
=
tmp_new[idx].rjust(3,
'0')
str_old
=
tmp_old[idx].rjust(3,
'0')
if
str_new
>
str_old
rtn
=
true
break
elsif
str_new
<
str_old
rtn
=
false
break
end
end
rtn
end
p →
定義元もなにしているのかわからん
(-‐”-‐;
#
バージョンチェック
def
self.check_ver_isnew(new,
old)
tmp_new
=
new.split('.')
tmp_old
=
old.split('.')
if
tmp_new.length
>=
tmp_old.length
max_size
=
tmp_new.length
else
max_size
=
tmp_old.length
end
rtn
=
false
for
idx
in
0..(max_size-‐1)
if
tmp_old[idx].nil?
rtn
=
true
break
end
- 10. p “1.0.0”のような文字列2つを引数にとり、
新しいバージョンか調べるメソッド
p 第1引数の方が第2引数より新しいバージョン番号の場合true
p 同値の場合はfalse
p 同値も含めたい場合は呼び出し後に同値チェック(to_fの箇所)
p ただし、“1.0”と“1.0.1”を同値と認識してしまう不具合あり
p そんなん読み取れないよ!
p この挙動を完全に把握するのに約30分かかりました…
p もっとコードに想いを込めようぜ!!
check_ver_isnew(“1.0.0”,
“0.9.9”)
→
true
check_ver_isnew(“1.0.0”,
“1.0.0”)
||
“1.0.0”.to_f
==
“1.0.0”.to_f
→
false
||
true
check_ver_isnew(“1.0.0”,
“1.0.1”)
||
“1.0.0”.to_f
==
“1.0.1”.to_f
→
false
||
true!?
- 12. p ISO/IEC
9126
p ソフトウェア品質特性に関する国際規格
p 機能性:
機能とその特性に影響する特性群
p 信頼性:
ある状況がある時間続いたときにどの程度機能するかに影響する特性群
p 使用性:
利用するのにかかる手間、個人の努力などに影響する特性群
p 効率性:
ソフトウェアの性能やそれに要するリソース量に影響する特性群
p 保守性:
何らかの変更を加えるのにかかる手間に影響する特性群
p 移植性:
別の環境にソフトウェアを移行させる可能性に影響する特性群
p コードに想いを込めて保守性向上
p 作成/変更の意図を誰が見てもわかるように
- 13. p 保守性が必要ないケース
p 自分しか使わないコード
p 一度しか使わないコード
p 保守性が重要なケース
p 他人も見るコード
p ずっと使われ続けるコード
p なぜなら
p 我々は製品コードを作成&メンテするプロ集団だから。
p チームでコードを作成し、
p サービスがEOLを迎えるまでメンテし続けなければならない
とにかく動けばなんてもいい
- 15. #
バージョンチェック
#
使い方1:
#
ApplicationModel.check_ver_isnew(比較対象文字列1,
比較対象文字列2)
#
→
比較対象文字列1
が
比較対象文字列2
より新しい場合true,
同値もしくはより古い場合false
#
使い方2:
#
ApplicationModel.check_ver_isnew(比較対象文字列1,
:newer_than
=>
比較対象文字列2)
#
→
比較対象文字列1
が
比較対象文字列2
より新しい場合true,
同値もしくはより古い場合false
#
使い方3:
#
ApplicationModel.check_ver_isnew(比較対象文字列1,
:newer_than_or_equal_to
=>
比較対象文字列2)
#
→
比較対象文字列1
が
比較対象文字列2
より新しいもしくは同値の場合true,
より古い場合false
def
self.check_ver_isnew(
*args
)
……
#
初期値:
等号含むならtrue,
含まないならfalse
#
(各要素が同値なら次の要素へ判断を持ち越す。すべて同値なら判断できず、初期値のままとなる。)
result
=
(equality
==
:newer_than_or_equal_to)
?
true
:
false
new.zip(old).each
do
|str_new,
str_old|
#
文字数の多い方に合わせて右寄せでゼロ埋め
str_len
=
[str_new.length,
str_old.length].max
……
end
end
- 16. p メソッドの使い方説明を追加
p 2つの引数のどっちが新しいときにtrueとなるのか明記
p 同値の場合にtrueとなるのか明記
p 既存の仕様はそのまま
p どうせならメソッド名も変えたかった…
p 同値を含めるか否かを呼び出し時に指定できるように
p 説明的なハッシュキー&バリューで指定
p 複雑な処理にはコメントを追加
p なぜこのコードが必要かという理由も
- 17. p 変数名をより説明的に
p 例:
この変数はオブジェクトのときと配列のときとどっちもあるんだよな…
p その想いをそのまま変数名にしたらいい!
→
device_or_ids
#
サービスへの招待をコマンドプッシュで通知する
def
invite_by_command(admin,
device_or_ids)
if
device_or_ids.is_a?(Device)
device_ids
=
[device.id]
elsif
device_or_ids.is_a?(Array)
device_ids
=
device_or_ids
end
……
end
- 18. p 短命な変数は1文字でもOK。ただし意味深く。
p イテレータ変数iはindexを意味する
p tmpは非推奨
p ローカル変数なんて大抵テンポラリなもの
p 何を表現したいのかもっとよくよく考えよう
p 長命なほどより意味深く、より説明的な命名を
長命
短命
for文の
イテレータ変数
ローカル変数
メソッドの仮引数
インスタンス変数
グローバル変数
- 19. p メソッドを呼ぶことでどんなことが起きるのかわかるように
p 英語のSVC構文、SVO構文を意識する
p 短く略称を使ってもよいケース
p 汎用的に、頻繁に呼び出すメソッド
p 気軽に(副作用なく)利用できるメソッド
p 意味深く説明的にするケース
p 特定の用途にしか使わないメソッド
p 呼び出しに注意が必要(副作用がある)メソッド
app_ver.newer_than_or_equal_to?(command_ver)
→
Is
the
app_version
newer_than_or_equal_to
command_version?
wizard.validate_params_on_building_request
→
The
wizard
validates
parameters
on
building
a
request.
name
=
device.to_s
self.generate_aes_encrypt_compatible_key
←
単にgenerate_keyだったらどんな用途かわからない
self.push_certificate_with_disable_expired_certificates
- 20. p クラス名はグローバル定数とほぼ同義
p 長命
p ヒト/モノ、用途を表す
p ヒト/モノ:
User、Device
p 用途:
DeviceBuilder、CommandGenerator
p 業界用語を使う
p 製品ドメインの用語
p デザインパターン名
p コードの作者と読者で共通の認識を持ちやすい
p ただし、目的と手段を履き違えないように
- 21. p コメントは作者から読者への直接的なメッセージ
p でも、変数名/メソッド名/クラス名が充分に意味深ければコメントは不要
p 効果的なコメントとは?
p whatは今のコードを読めば大体わかる
p how/whyでコーディング時の想いを残そう
p [how]
クラス/メソッドの使い方説明
p [why]
なぜそのコードが必要なのか
p [why]
なぜ現在のコードになったのか
#
結果を返す
return
result
#
初期値:
等号含むならtrue,
含まないならfalse
#
(各要素が同値なら次の要素へ判断を持ち越す。すべて同値なら判断できず、初期値のままとなる。)
result
=
(equality
==
:newer_than_or_equal_to)
?
true
:
false
#
人物がいない場合は、該当組織のみで検索実施
#(不具合対応。これをはずすと人物が存在しない組織の管理者の場合に条件が追加されない)
#
return
{}
if
people_abstract_user_ids.blank?
abstract_user_ids
=
organization_abstract_user_ids
+
people_abstract_user_ids
論外
- 22. p publicなメソッド
p いろんなところから呼び出されている可能性があるため全体
grepして影響調査が必要
p privateなメソッド
p そのクラス内だけで使われているため、クラス外部への影響を
気にしなくて良い
p なので、
p とりあえずpublicで。というのはやめよう
p 影響範囲はここまでなんです!と主張しよう
- 23. p 利用者と拡張者へのメッセージ
p to
利用者:
p オブジェクトがどの具象クラスのもの
か分からなくても、そのメソッドは呼
び出していいよ
p to
拡張者:
p 子クラスを実装するときには必ずオー
バーライドしなさい
p Rubyにはvirtual修飾子がない
p どのメソッドでも後から気軽に拡張
できるから疎かにされがち
p 親クラスのメソッドで例外発生させ
ることで表現
class
Device
def
push_notification
raise
“Must
be
overriden!”
end
end
- 24. p コミットメッセージで改修意図を示そう
p [what/when/where/who]
コミット内容を見れば大体わかる
p [why]
なぜその改修をしたのかを残そう
p [how]
どうやったかは残しにくい
p ログ表示やblame表示したときに読まれることがある
p プッシュしてしまうとメッセージを修正できない
p 誤字/脱字、関連するチケット番号に間違いがあるかも
p 情報としてちょっと信頼性が低いので注意
- 25. p コード改修の意図を記載しよう
p コメント、コミットメッセージには書ききれなかった改修意図
p 思いの丈をレビュアーにぶつけよう
p コード改修が問題ないことをどう確認したか
p [how&result]
影響範囲調査項目とその結果
p [how&result]
デバッグ試験項目とその結果
p コードだけでなくプロセスのレビューができるように
- 26. p コードからチケットへのトレーサビリティ
p コメント、コミットメッセージにチケット番号を記載
p チケット番号を自動的にリンクしてくれるツールを活用
p Redmine、JIRA&Bitbucket、などなど
p チケットにはいろいろ書ける
p [what]
改修内容の概要
p [how&result]
影響範囲調査項目とその結果
(プルリクがなければ)
p [how&result]
デバッグ試験項目とその結果
(プルリクがなければ)
p [why]
コード改修のそもそもの要件
- 28. p 実装の意図大事!
p なぜそのコードなのか意図を主張しよう
p 名前付け大事!
p 意味深く説明的な名前がついていればコメントはもはや不要
p コードに込め切れないあふれた感情は
p コミット、プルリク、チケットに吐き出そう