リファクタリングについて伝えたいこと。

この文章は以下に該当する方へ、なぜエンジニアにリファクタリング(リファクタ)させるべきなのかを記載しています。

最初に

リファクタリングの話をする前に、一般的な職場に関する質問があります。

  • あなたの職場は綺麗ですか?
  • あなたが思い浮かべる「できる同僚・上司」の机は整理整頓されていますか?

全ての人に当てはまるわけではないと思います。しかし大抵の方は両方回答がYesになると思います。

職場を綺麗にするのはそこで働く人の健康維持やモチベーション向上に役立ちます。職場を綺麗にしてくれる専門のスタッフがいる企業もあるのではないでしょうか?また整理整頓された机で仕事することにより、ムダを省略することが出来ます。仕事をするスペースが増えることにより効率もあがります。大抵の出来る人は机を整理整頓している傾向があるそうです。著名な会社の研修でも同じようなことを説いていました。

汚い環境で働くということは、モチベーションを下げ、ムダな作業を発生させ、効率を下げるということです。汚い環境で働くのは非常に辛く、可能であれば、人はその環境から離れていきます。

リファクタリングとは何か?

さて、本題のリファクタリングについてです。wikipediaでは以下のように説明されています。

リファクタリング (refactoring) とはコンピュータプログラミングにおいて、プログラムの外部から見た動作を変えずにソースコードの内部構造を整理すること。*1

もう少しサービス開発に絡めて切り込んだ説明にすると、

リファクタリングするということは、サービスの機能の追加や削除は一切行わず、コストをかけて、今まで動いていたコードに対して修正を加える作業です。」

リファクタリングをすることにより、バグを埋め込んでサービスを止めてしまう可能性も含まれることになります。もちろんそれを避ける術はいくつかあるのですが、手段はエンジニアが考えればいいのでここでは省略させていただきます。

リファクタリングをなぜやるのか?

なぜこんなムダな作業を行うのでしょうか?エンジニアはアホなんでしょうか?

エンジニアはコード上で仕事をしている

(実際、アホなことやる人は多いですが・・・)事自分たちが行っているサービス開発に関して言えば、プライドを持って行っているはずです。サービスに携わっている以上、そのサービスがより良くなることを望んで開発しています。そのエンジニアがコストがかかることを承知で、リファクタリングさせて欲しいという理由があります。それはエンジニアはコード上で仕事をしているということです。

デスクの綺麗さとコードの綺麗さ

私が非エンジニアにリファクタリングの重要性を説明する時は以下のように説明します。

  • デスクに毎日のようにいろんな人が資料を置いていくとします。
  • 資料を置くことを目的にする社員もいるので、資料はあなたが意図した場所には置かれません。
  • デスクがどんどん汚くなっていき、必要な資料を探すのに苦労します。
  • 間違った資料を使って仕事をする可能性も出てきます。
  • このような状況になった場合、あなたがまず最初に行うのが、整理整頓だと思います。

ではエンジニアはコード上で仕事をしているということなので、デスクを「コード」、置かれていく資料を「追加機能」と読み替えてみます。

  • コードに毎日のようにいろんな人が機能を追加していきます。
  • 機能追加を目的にする社員もいるので、エンジニアが意図した場所に機能が追加されません。
  • コードがどんどん汚くなっていき、必要な機能を調査するのに苦労します。
  • 間違った機能を使って仕事をする可能性も出てきます。(=バグを作り出す)
  • このような状況になった場合、エンジニアがまず最初に行うのが、整理整頓(=リファクタリング)だと思います。

エンジニアが作業しているコードを綺麗にすることにより、将来的にバグを作り出さなかったり、効率良く作業が出来る環境を作ることが出来ます。

エンジニアを惹きつける、引き止めるためのリファクタリング

汚い環境で働くということは、モチベーションを下げ、ムダな作業を発生させ、効率を下げるということです。汚い環境で働くのは非常に辛く、可能であれば、人はその環境から離れていきます。

この文章も同じように読み替えることが出来ます。

汚いコード上で働くということは、モチベーションを下げ、ムダな作業を発生させ、効率を下げるということです。汚いコード上で働くのは非常に辛く、可能であれば、エンジニアはそのコード(会社)から離れていきます。

エンジニアが働く場所の環境を良くすることとそのエンジニアを魅了するためにリファクタリングをさせる猶予を与えてあげてください。この魅力的な余裕があることでエンジニアとしてやる気が向上し、整理されたコードで仕事が出来るためパフォーマンスが上がります。働きやすい職場(コード)で最高のパフォーマンスを出すことが出来るのであれば、エンジニアが離職するのを引き止めるのに役立つはずです。

まとめ

汚い場所で人を働かせることが辛いということがわかるのであるなら、ぜひ汚い環境で働かされているエンジニアに掃除をする猶予を与えてあげてください。それが長期的に見るとサービスを改善を早くし、技術力のあるエンジニアを定着させ、変化に柔軟なサービスを提供させることが出来るようになるからです。

自己紹介


はじめてはてなブログを使ってみようと思います。

普段技術ネタをQiitaにあげているのですが、技術ネタではないものを書くためにこのブログを開設しました。shirajiともうします。

Qiitaもshirajiというアカウントで記載しておりますので、そちらも確認してください。

思ったものを記載していくつもりです。更新ペースはそこまで高くないです。

よろしくお願いいたします。

Eclipseの環境構築をまとめてみた


最近、Objective-cやらJavaやらRailsやらPlay frameworkやら手を出しまくっているせいか書くネタがない。。。

ということで、本題。
端末をかえることが重なってしまい、毎回Eclipseの設定をするという非常にだるいことになったので、一旦、何を毎回しているかメモ書き。あくまで自分の環境なので、設定して壊われても責任持ちません。
(いい加減、このあたりなんとかならないものか・・・。vimのvundleみたいにファイル一つでやってくれたらいいのに。)


1. インストール
面倒なので、All in one(Android開発ならADT)
URL: http://mergedoc.sourceforge.jp/
重い場合は新しいPC買えばいいと思う。(自分はお金がないので我慢。)

2. 英語化
URL: http://d.hatena.ne.jp/shiraji/20130427/1367054426

3. プラグイン

  • Eclipse Color Theme (Editorの色変更)
    • URL: http://eclipsecolorthemes.org/
    • Update Site: http://eclipse-color-theme.github.io/update/
    • 設定方法
      • テーマを選ぶ
        • Window > Preference > General > Appearance > Color Themeで選ぶ(いつもWombat)
      • カーソルがある行のハイライトがうざいので消す
        • Window > Preference > General > Appearance > Text Editor > Highlight current lineのチェックを外す
      • ついでに行番号を表示する
        • Window > Preference > General > Appearance > Text Editor > Show line numbersのチェックを入れる
      • Wombat好きなんだけど、field名とクラス名の色が同じなので、かえる。
        • Window > Preference > Java > Editor > Syntax Coloring > Java > Fieldsを選択。色を変える。(色はだいたいいつも左から6番目、上から3番目)
  • Eclipse Theme (Editor以外のテーマ変更、4.2 - Juno以上だった場合)
    • URL: https://github.com/jeeeyul/eclipse-themes
    • Update Site: https://raw.github.com/jeeeyul/eclipse-themes/master/net.jeeeyul.eclipse.themes.updatesite
    • 設定方法
      • テーマを選ぶ
        • Window > Preference > General > AppearanceでJeeeyul's theme - Chrome Themeを選び、再起動する
      • パディング(Shadow?)を消す
        • Window > Preference > General > Appearance > Chrome Theme > General > Sash WidthでThin Sashを選ぶ
      • さらに画面大きく
        • Window > Preference > General > Appearance > Chrome Theme > Part > Part Statck ShapeのPart Paddingを0pxにする
      • 各パネルの色がいや
        • Window > Preference > General > Appearance > Chrome Themeで、右にあるパレット?の横の下三角形から > Editor's Presets > Chrome Classic
    • メモ
      • Eclipse Dark Junoというものもあるけど、ところどころ白くて嫌。全部まとめて変えられればいいのに。


4. 補完

  • Javaの補完の機能をもっと便利に
    • Window > Preference > Java > Editor > Contents Assist
      • Enable auto activationをチェック
      • Auto activation delay(ms): 80
      • Auto activation triggers for Java: .abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_
  • いらない補完候補を消す
    • Window > Preference > Java > Editor > Contents Assist > Advanced
    • Javaの開発ならJava Proposalsだけあれば十分


5. UTF-8
ファイルのエンコーディングUTF-8にする。てかこれなんでデフォルトじゃないのだろう?

  • Window > Preference > General > Workspace > Text file encodingをUTF-8



6. キーバインド

設定する場所: Window > Preferences > General > Keys

  • Glanceのため、Incremental FindとIncremental Find Reverseをアンバインド
  • Glanceのキーバインド

Name:「Open Glance」
Binding: Ctrl+j
When:「In Dialogs and Windows

Name:「Next Match」
Binding; Ctrl+j
When:「Glance Search Context」

上のキーバインドをコピーし、
Name:「Next Match」
Binding; Enter
When:「Glance Search Context」

Name:「Previous Match」
Binding; Ctrl+Shift+j
When:「Glance Search Context」

  • クリーン

Name:「Clean」
Binding; F8
When:「In Windows

Name:「Toggle Toolbar」
Binding; Ctrl+4
When:「In Windows

7. スプラッシュ画像を変える

  • 変えたいsplash.bmpを以下のフォルダに置く(オススメはEclipseたんなんですが、職場ではイメージを壊す恐れがあるので、要注意)
  • ADTの場合


8. ツールバーのカスタマイズ
Eclipse Junoを使っている方(特にADT)この設定はやらないほうがいいです。理由は追記に記載。

  • Window > Customize Perspective... > Tool Bar Visibilityで不必要なものからチェック外す。
    • 自分の場合、LaunchとDebug以外全て外す。LaunchとDebugはマウス使うので。
  • 右にある各Perspectiveのテキストがうざい
    • 右にある各Perspectiveのアイコン右クリック > Show Textからチェック外す


9. コードテンプレート

  • 新しくファイル作成するとファイルの1-3行目にコメントが入るのがうざい
    • Window > Preference > Java > Code Style > Code Templates > Comments > Files > Edit > 空にする
  • Overrideしたメソッドのコメントが意味不明
    • Window > Preference > Java > Code Style > Code Templates > Comments > Overriding methods > Editに以下を記載

/**
* {@inheritDoc}
*/

  • 新しいメソッドのテンプレートがうざい
    • Window > Preference > Java > Code Style > Code Templates > Code > Method body > Editで以下を記載

throw new UnsupportedOperationException("havn't implemented, yet");

  • 新しいファイル作成時、必ずコメントをつける
    • Window > Preference > Java > Code Style > Code TemplatesでAutomatically add comments for new methods and typesをチェック(これもデフォルトにしてー)


10. その他

  • 検索した結果からファイルへ飛ぶときに新しいタブを開いてほしい
    • Window > Preference > General > SearchでReuse editors to show matchesを外す
  • フィールド名の前は「m」とかプレフィックスにする。だけど、getter/setterではmはつけない場合。(開発場所により変わる)
    • Window > Preference > Java > Code StyleでFieldsを選択し、Edit > Prefix listにm
  • 保存時に何かする(フォーマットとか)
    • Window > Preference > Java > Editor > Save Actions
      • 開発場所によりかなり変わるため、なんともいえないが、必ずつけるものは以下
        • Format source codeをチェック
          • Format edited linesを選択
        • Organize importsをチェック
        • Additional actionsをチェックし、congifureをクリック
          • Code Organizing > Remove trailing whitespaceをチェック
            • All linesを選択
          • Missing Code > Add missing Annotationsをチェックし、その下の全てをチェック
          • Unnecessary Code > Remove unused importsとRemove unnecessaray castsをチェック
      • this.とかのルールもここで設定すると便利。これ設定するようになってから、ctrl+shift+oとctrl+shift+fを押さなくなりつつある。
  • Package Explorerに隠しファイルを表示する
    • Package Explorerの右側にある三角形 > Filters...をクリック
    • .* resourcesのチェックを外す。


なんかまとめたら大作になた・・・。
設定関連はgithubにあげて管理しなきゃ。放置しているレポジトリがあるから、腰をあげてみますか。

にしてもこのブログのフォーマットうまくできない。
写真つきにしようと思ったら、かなり長くなったので、やめた。


// 追記 ////////////////////////////////////////////////
ツールバーの変更について
書いてから、気づいたのですが、現在ADTではツールバーにバグが存在しています。
ツールバーのアイコンの移動や消したものをもとに戻す機能にバグがあり、動かないと報告もあります。https://bugs.eclipse.org/bugs/show_bug.cgi?id=340695

もし、ツールバーからアイコン消したけど、やっぱり必要だったーなどがあった場合、以下のファイルを消すともとに戻ります。
workspace/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi
ただし、このファイルはビュー関連の設定が入っているファイルですので、消す場合、またパースペクティブなどのレイアウトをし直す必要があります。扱いには細心の注意を払って下さい。

Objective-cでNSArrayのcountではまったこと。

10月くらいからObjective-cを触っている。
結構毎日触っているんだけど、まだまだわからないことが多くて大変です。
さらにプライベートではwindows使っていて、Mac持っていないので、会社でしか触れていなくて。Mac買おうかなー。

ということで初歩的なところではまったのでメモ。

// 配列
NSArray array = @[@"赤",@"青",@"黄",nil];

for (NSIntger index = -1; index < [array count]; index++) {
if (index > 0) {
NSLog(@"%@", [array objectAtIndex:index]);
} else {
NSLog(@"%@", @"以下から選んで下さい。");
}
}

こんな感じで、ループさせてみた。まぁなにゆえ、ループ前にやらないのかとかあるけど、とりあえずそこはおいておいて。
このループ実は実行されない。なぜかというと[array count]の戻り値がNSUInteger。つまり、unsigned integer。
index=-1を比較する場合、indexがunsigned integerとして扱われ、-1はunsigned integerの一番大きな数字となる。

Javaにはないunsigned型があるので注意しましょうということでした。

chef-soloでcookbookを作成する

以前からJenkinsさんをchefで立ち上げるところまで自動化したのですが、
Jenkinsさんの自動起動が設定されていなかった。
ドキュメントを流し読みしてみても、Jenkinsさんの自動起動設定がない。
じゃあそういうレシピ作成してみよかと思ったのですが、数カ月前ということもあり、完全に失念!

ということで、chefのcookbook作成方法のメモです。

まず、環境を作る。

git clone https://github.com/shiraji/chef-repo.git
cd $HOME/chef-repo
bash chef_setup.sh
これで問題なければ、今回使うchefやknifeが入る。
chef-soloなので、knifeの設定(knife configure)をせずに突き進む。

以前にも書いたと思うけど、ざっくり構成についておさらい。

chef-repo/
├── cookbooks --- 人が作ったcookbooksを保持
├── nodes --- 実行される各サーバ固有の設定を保持
├── roles --- cookbook利用時の設定値を保持
└── site-cookbooks --- 自分が作成したcookbookを保持
├── addusers --- 自作ユーザ追加cookbook
└── server_settings --- 自作サーバの基本設定のcookbook
nodesとrolesはかなり重要で、この2つを意識したcookbookを作れば、拡張性が高くなる。

実際にcookbookを作成してみる。

cd $HOME/chef-repo/site-cookbooks/
knife cookbook create autorun_settings -o .
knifeが色々揃えてくれた結果がこれ
site-cookbooks/
└── autorun_settings
├── CHANGELOG.md
├── README.md
├── attributes --- attributeを設定する。default.rbがデフォルトの値
├── definitions
├── files
│ └── default
├── libraries
├── metadata.rb
├── providers
├── recipes
│ └── default.rb --- デフォルトのrecipe
├── resources
└── templates
└── default
Hello worldしてみる。

デフォルトのrecipe(recipes/default.rb)に以下を書き込む。

puts "Hello World"
これだけでほぼ終わりなのだけど、せっかくなので、nodes, rolesを設定する。

まずはrole。$HOME/chef-repo/roles/にjenkins_autorun.jsonを作成する。
本当はここで、knife role createとかするべきなんだけど、knifeの設定してないしーということで簡単なスクリプト作成したので、それを利用して、作成する。

cd $HOME/chef-repo/roles/
bash new_role.sh jenkins_autorun.json
new_role.shはsedでテンプレートファイルの中身を変更し、それをファイルに保存している。
#!/bin/sh

if [ $# -ne 1 ]; then
echo "No role name"
exit 1
fi

_role_name=$1

cat role_template.json | sed -e "s/NAME/${_role_name}/g" > ./${_role_name}.json

role_template.jsonはknife create roleすると出来るべきroleファイル
{
"name": "NAME",
"description": "",
"json_class": "Chef::Role",
"default_attributes": {
},
"override_attributes": {
},
"chef_type": "role",
"run_list": [

],
"env_run_lists": {
}
}

上記のコマンド叩いて、出来るのがこのrole。(コピペするだけでも問題ない。)
{
"name": "jenkins_autorun",
"description": "",
"json_class": "Chef::Role",
"default_attributes": {
},
"override_attributes": {
},
"chef_type": "role",
"run_list": [

],
"env_run_lists": {
}
}

今のところ、attributesなどはないので、設定せず、run_listに先程作成したcookbookを設定する。
{
"name": "jenkins_autorun",
"description": "",
"json_class": "Chef::Role",
"default_attributes": {
},
"override_attributes": {
},
"chef_type": "role",
"run_list": [
"recipe[autorun_settings]"
],
"env_run_lists": {
}
}
次にnode
run_listに上記で作成したroleを指定する。
{
"run_list": [
"role[jenkins_autorun]"
]
}
実行で必要な設定ファイル(chef-repo/solo.rb)はこんな感じ。
le_cache_path           "#{ENV['HOME']}/chef-repo"
data_bag_path "#{ENV['HOME']}/chef-repo/data_bags"
encrypted_data_bag_secret "#{ENV['HOME']}/chef-repo/data_bag_key"
cookbook_path [ "#{ENV['HOME']}/chef-repo/site-cookbooks",
"#{ENV['HOME']}/chef-repo/cookbooks" ]
role_path "#{ENV['HOME']}/chef-repo/roles"
$HOME直下に置いてあると想定されている。違う所に置いてある場合は、このファイルを変更すること。
拡張子で一目瞭然だけど、solo.rbはrubyファイル。$HOMEは使えないので注意。

それでは実行

cd $HOME/chef-repo
chef-solo -c solo.rb -j nodes/jenkins_autorun.json
実行結果
Starting Chef Client, version 11.6.0
Compiling Cookbooks...
Hello World
Converging 0 resources
Chef Client finished, 0 resources updated
これで、Hello Worldはできたので、今回の目的であるjenkinsのサービスの自動起動をしてみる。
chkconfig jenkins onを実行すればいい。
resourcesというものがchefで実行されるコマンド。詳細はここhttp://docs.opscode.com/resource.html
このresourcesとrubyの文法を駆使してrecipeを作成していく。
簡単なlinuxのコマンドのため、resourcesはexecuteを利用する。
chef-repo/site-cookbooks/autorun_settings/recipes/default.rbに以下を記載する
execute "autorun" do
command "chkconfig jenkins on"
action :run
end
ただ、これだと、jenkinsのみのcookbookになってしまう。そこでattributeを設定し、roleで指定できるようにする。
まずはデフォルトのattributeを作成する。
chef-repo/site-cookbooks/autorun_settings/attributesにdefault.rbを作成。中身は以下。
default[:autorun][:ons] = ["jenkins"]
これを使うrecipeはこんな感じ。
node[:autorun][:ons].each do |on|
if !on.empty?
execute "autorun on" do
command "chkconfig #{on} on"
action :run
end
end
end
実際に実行してみると
Starting Chef Client, version 11.6.0
Compiling Cookbooks...
Converging 1 resources
Recipe: autorun_settings::default
* execute[autorun on] action run
- execute chkconfig jenkins on

Chef Client finished, 1 resources updated
これでもまだ、拡張性がないので、autorunの設定のON、OFFができるようにする。
まずデフォルトの設定を以下にする。
default[:autorun][:ons] = []
default[:autorun][:offs] = []
デフォルトのrecipeを以下に
node[:autorun][:ons].each do |on|
if !on.empty?
execute "autorun on" do
command "chkconfig #{on} on"
action :run
end
end
end

node[:autorun][:offs].each do |off|
if !off.empty?
execute "autorun off" do
command "chkconfig #{off} off"
action :run
end
end
end

ここで、roleでoverride_attributesを設定する。chef-repo/roles/jenkins_autorun.jsonを以下のようにする。
{
"name": "jenkins_autorun",
"description": "",
"json_class": "Chef::Role",
"default_attributes": {
},
"override_attributes": {
"autorun": {
"ons": ["jenkins"]
}

},
"chef_type": "role",
"run_list": [
"recipe[autorun_settings]"
],
"env_run_lists": {
}
}
実行結果(上記と同じ)
Starting Chef Client, version 11.6.0
Compiling Cookbooks...
Converging 1 resources
Recipe: autorun_settings::default
* execute[autorun on] action run
- execute chkconfig jenkins on

Chef Client finished, 1 resources updated
これで完了。

■注意点■
私は今CentOSの環境のみしかないので、chkconfigが使えないubuntuとか気にしていない。
必要な場合はOS別のコマンドを作成すればいいと思う。

crontab -rを使えなくしてみた。

crontabは恐ろしいオプションがあるとそこらじゅうのブログで見ていて、crontab -eもしないようにcrontab file_nameで設定するように心がけていました。
で、いざやっていると、crontab file_nameの後ってうんともすんとも言わんのです。
こんな感じです。

[shiraji ~]% cat test.crontab
0 0 * * * /bin/bash /tmp/test.sh
[shiraji ~]% crontab test.crontab ### ★ここで何も言わない
[shiraji ~]% crontab -l
0 0 * * * /bin/bash /tmp/test.sh
[shiraji ~]%
本当に設定できたの?と毎回crontab -lをするはめに。
結局オプションコマンド必要じゃん!・・・じゃあcrontab file_nameの後に必ずcrontab -lをするようにしようとaliasを作ってみた。

結果、偶然crontab -rを使えなくできた。
crontab -u shiraji -rはできるのでご注意を。-rあればコマンドスルーでできると思うけど、複雑になるし、-uコマンド使わないから、省略。

てかcrontabなんて使わずに、Jenkins使えばいいと思う。

Thorを使いやすくしてみた(Ruby・Railsバッチ編)

以前のエントリー:Thorを使ってみた(Rubyバッチ編)
いくつかRailsのバッチを書いていて、共通な部分が結構あったので、クラスとして出して、使いやすくしてみました。

やっていること:

  • Helpの設定(-hでヘルプ表示)
  • ログレベルの設定(-l FATAL, ERROR, WARN, INFO, DEBUGの5種類)
  • ログファイルの設定(-f 上記ログレベルの設定がされていれば、出力先のログファイルを指定する)
  • 実行環境の設定(-e Railsの実行環境を設定)

■注意点
Railsの環境設定を行っているため、Thor::Invocation.invoke_commandを継承している。
Thorの更新が入った場合、invoke_commandメソッドの呼ぶタイミングが変更されるかも?
Thor.invoke_command
Thor.dispath
Thor.start
などを参照してみてください。

■使い方
前のTestバッチ

class Test < Thor
class_option :help, :type => :boolean, :aliases => '-h', :desc => 'Thor test'
default_task :execute
desc "execute [OPTION]", "Test execute"
option :production, :type => :boolean, :aliases => '-p', :desc => "Run production DB server"
option :number, :type => :numeric, :aliases => '-n', :default => 3, :desc => "test number"

def execute
# DBオプション
if options[:production] then
@mode = 'PRODUCTION'
else
@mode = 'DEVELOPMENT'
end

puts @mode
puts options['number']
end
end

Test.start

MyThorを使ったバッチ。

class Test2 < MyThor
default_task :execute
desc "execute [OPTION]", "Test execute"
option :number, :type => :numeric, :aliases => '-n', :default => 3, :desc => "test number"

def execute
puts Rails.env
puts options['number']
end
end

Test2.start

さらに簡単に。default_taskもMyThorに持っていくといいかもしれない。

===
はてなさんが直すのを待ち続けていたのですが、一向に直らないので、GistのCSSいじりました。多少見やすくなったのではないでしょうか。
コードが横に長いと行番号の横幅が無くなってしまい1行1桁しか表示されなくなってしまうのが問題でした。

デフォルトで!とおもったのですが、さすがに我慢できず。