matobaの備忘録

育児しながら働くあるエンジニアの記録

ソフトウェアをリファクタリングするということ

リファクタリングについて調べてます。

この記事の続き。

リファクタリングについて調べはじめた - blog.mtb-production.info

キチンとしたリファクタリングのやり方を知りたいと思ってます。*1

というわけで、この本を読んでます。

新装版 リファクタリング―既存のコードを安全に改善する― (OBJECT TECHNOLOGY SERIES)

新装版 リファクタリング―既存のコードを安全に改善する― (OBJECT TECHNOLOGY SERIES)

本を読んでいて、自分なりにポイントだと思ったことを書いています。最後に所感も書いてます。

リファクタリングの頻度

リファクタリングは定期的にやることではなく、何かをやる時に一緒にやること。

  • Bad:定期的(例えば、二週間に一回)やる。
  • Good:リファクタリングするべきタイミングでやる。

リファクタリングをやること

リファクタリングは目的ではなく、手段である。

リファクタリングのタイミング

次のようなタイミングでやる。

リファクタリングしないとき

次のタイミングでは、リファクタリングを避けます。

  • コードが汚すぎて書き直す方が早いとき
  • 既存コードが動かないとき
  • 締め切りが迫っているとき

なにをリファクタリングするか

  • じゃあ、なにをリファクタリングしたらいいの?ってと言うと、不吉な臭いのするコードリファクタリングする。
  • 不吉なコードを嗅ぎ分けるスキルは経験によって養われる。

所感

この話の中だと、一番良かったのが、何かを対応する中で理解のためにリファクタリングするということ。

ちょうど、開発してるコードでも、新しい機能を作ったら、元のコードで気になる部分が出てきていた。

新しく作っている機能がなかったら気にならなかったけど、新しい機能を追加したら気になることがある。

たとえば、新しい機能があることで既存機能の変数名が誤解を招くとか、無駄な処理があるとか、そもそも、設計が微妙になるとか、そういうやつ。

そういう微妙ななにかは、新しい機能を追加するときにわかるし、それはリファクタリングすべきコードだということがわかった。

そして、リファクタリングした際に、デグレートしてないかを確かめるためにユニットテストが有効に作用する。

ユニットテストがしっかりしていれば、リファクタリングがスムーズにできることがわかってきた。

あと、これまではユニットテストを書くのが遅かったけど、ユニットテストを書くスピードが上がれば、ソフトウェア品質と開発スピードを保ったまま、ソフトウェアを拡張していけることがわかってきた。

これまで、設計した後にコーディングをする。そして、コーディングの段階で、設計を修正しないといけないのがわかったら負け。みたいなマインドがあった。

コーディングする前に、設計が全部わかるわけないでしょ。と思っていたけど、『僕が実力不足なだけで、できる人ならコーディングする前に設計が終わるのかもしれない。』とも思ってた。

ただ、この本を読みつつ仕事をしてる中で真実はこうでは?と思ってることがある。

  • 設計してからコーディングした方が良い。(必須ではない。規模、複雑さ、何回使いまわすか、による。)
  • コーディングする前に設計が完了するときもある(だいたい作ったことがあるシステムと、全く同じものを作る場合は近いかもしれない。ただ、ホントにそんなことある?チュートリアルか?)
  • 設計してからコーディングして、その後に設計を修正することはある。(必ずではない。コードの目的が何なのかによる。)
  • 前は良かった設計が、新しい機能追加によって悪い設計になるときがある(拡張性が高ければ良い設計ではない。拡張されないのに、拡張ポイントを作ると、逆に読みにくいコードになる。コードが読みにくいければ良い設計とは言えない。)
  • 時間と共に設計は、腐っていくので改善しないといけない。(周辺環境によって、設計が良いか悪いかは変化するし、周辺環境は時間と共に変化していくので、それに合わせたリファクタリングが必須。)

とりあえずおわり。

*1:キチンとした、ってなんか型にハマってて、書いてあることしかやらなさそうな響きが個人的には好きじゃないんだけど、そういうのはとりあえず基本をしっかりしてから言う事な気がしてるのでとりあえず基本的なことをやりたい気持ち。

プロジェクトと停滞と復活

僕が前に書いてたメモを見つけた。こんなこと書いてた。

プロジェクトが詰まった時にどうすれば復活できるか?

まあ気が向いたので、ちょっと調べてみた。*1

調べてみたら色々出てくるもんなんだなあ。と思った。*2

PMOの視点

こんな記事が出てきた。

www.pm-portal.jp

書いてあったこと。

  • 体制、役割、期待値の明確化
  • プロジェクト全体スケジュール策定
  • チームWBS策定
  • 会議体整理

PMOっぽいと思った。PMOと言うのは、Project Management Officeと言うやつで、その組織の中でいくつも走っているプロジェクトがいい感じになるように色々やる人。プロジェクトが炎上してないかをチェックしてたり、炎上してるプロジェクトの火消ししたり、プロジェクトがうまく回りそうに後ろで色々動く人たち。いわゆるプロジェクトリーダーの相談役みたいポジション。

個人レベルの視点

関連キーワードで検索してたら、こんな記事が出てきた。

orangewind.hatenadiary.jp

GTDの話。GTDについては、原著読むほうがいいと思うので、書かない。

全面改訂版 はじめてのGTD ストレスフリーの整理術

全面改訂版 はじめてのGTD ストレスフリーの整理術

僕もGTDやってるけど、GTDに定期点検は必須だと思う。*3

とは言え、止まってるプロジェクトとかあるよなあ。止まったら嫌なプロジェクトは、定期的に「見直し」みたいなタスクがあがるようにして、少しずつ前に進むように工夫してるなあ。とか思い出した。

プロジェクトリーダーの視点

別のキーワードで検索してたら、出てきた。

xlinkpat.jp

書いてあったこと。

  • プロジェクト全体を俯瞰する
  • 頭より手を動かす
  • 新メンバーを入れる
  • 専門家の手を借りる
  • 三人寄れば文殊の知恵

終わり

調べてる途中で思ったけど、こう言うのって、当事者にならないとイマイチわからないなあ。*4

後、個人的には、自分がどう言う役割なのか、を考えて頑張るんじゃなくて、誰でもいいから前に進めよう、と言う感じの混沌としたスタイルの方が好きだと思った。*5

それから、プロジェクトによって状況は変わるから、なんとも言えないよなあ。とかぼんやり考えていた。

*1:ただ単に、メモから削除したい気持ちがあったけど、せっかくメモしてたから多少調べてみようと思った。

*2:僕が関わっていたプロジェクトに行き詰まりを感じたこともあったし、そう言う時にどうすればスムーズに復活できるんだろうと考えたりしたけど、ググったらよかったんだなと思った。

*3:基本的にタスクがモリモリ増えていくから、定期点検しないと埋もれてしまう。

*4:と言うか、当事者じゃないと真剣に考えられない。。。

*5:役割分担が厳密に定義されたとしても、それをみんなが同じように認識するまでだいぶ時間がかカルシ、同じように認識したからできるわけじゃないし、その時間いるの?って思ったりするから。それなら泥臭くても前に進める方が良さそう

もっともっと手を動かす時間を増やしたいと思った話

絵はすぐに上手くならない。って本を読んでいる。この本がものすごく面白い。

絵はすぐに上手くならない

絵はすぐに上手くならない

読んでいて、そりゃそうだ!と思うようなことがたくさんあった。 気づきもたくさんあった。書きます。

2つのうまさ

本に書いてあったことから学んだこと。

  • 絵には二つのうまさがある。
  • 1つ目は、技術的なうまさ。何が良くて何が良くないのかわかり、表現力が高いこと。
  • 2つ目は、引き出しの多さ。何かを描こうとした際に、すぐに描けること。

音楽やプログラミングでも同じような話があると思う。 そして、引き出しの多さは、制作のスピード感に関係があるとのこと。 レベルが低くてもすぐに描けないと情熱が薄れてしまうという話。 そして、僕は、音楽にしてもプログラミングにしても引き出しが少ないことに気づいた。

上手さと学校

本に書いてあったことから学んだこと。

  • 真実:絵が上手いから美大に入れた
  • 間違い:美大に入ったから絵が上手い

音楽でも、近いことが言えそうだあ、とか。色々、似たようなことを考えた。 環境は人を育てるけど、その環境に受け入れられるかどうかは人次第。

上手さと書きやすさ

本に書いてあったことから学んだこと。

  • 真実:絵が上手い人も必死で形をとって遠くから何度も眺めて形を整えながら絵を描いている。
  • 間違い:絵が上手い人は、いつも鼻歌を歌いながらササっと絵を描ける。

音楽とかプログラミングとか、映像とか、クリエイティブなことは全体的に同じことが当てはまりそうだなあと思った。

音楽とかプログラミングをやるときに、もっとサササッと作れるようになりたいと思ってたけど、そういうタイミング来ないんだ。。。という気持ちになった。そう言えば、すごい人もみんな必死な顔して音楽やプログラミングしてる。

デッサンと上達

本に書いてあったことから学んだこと。

  • 真実:デッサンをやったら上手くなる
  • 間違い:デッサンをやらないと上手くならない。
  • 真実:デッサンをやらなくても、他のトレーニング(たくさん絵を描く等)をすれば上手くなる。
  • 間違い:デッサンをやらずに、他のトレーニング(たくさん絵を描く等)をしなければ上手くならない。

デッサンは、絵を描くために使う能力を効率的にトレーニングの一つであって、絶対にやらなきゃダメなことではない。 ただし、何をやりたいかわからないなら、デッサンやる方が汎用性が高い。との話。

これも、音楽とかプログラミングで同じこと言えそうだなあ・・・と思った。 例えば、音楽なら、「音楽理論を勉強すべき」vs「譜面も読めない音楽家がいるしやる必要はない」の議論をたくさん見たけど、同じ話だと思った。

絵とトレーニング

本に書いてあって学んだこと

  • 間違い:いろんなスキルや工程があって、一つずつクリアして行くと最終的に絵が描けるようになる
  • 真実:いろんなレベルのスキルや工程がぐちゃぐちゃしていて、クリアとかない。
  • 現実:スキルを整理して、全体的にレベルアップしやすくしている。

ソフトウェア開発や音楽制作も同じかなーという気持ち。

レベルと作品制作

本に書いてあって学んだこと

  • どんなレベルであったとしても作品制作はすぐ始めること
  • 上手くなってから始めようとしても、自分で自分のことを上手くなったと思う日はない。
  • 勉強が終わってから始めようとしても、勉強は終わらない。

とりあえず、作ろう。という話。能書きはいらない。

トレーニングと作品制作

本に書いてあって学んだこと

  • 作品制作は、頭の中にある世界を描いて絵にする。
  • トレーニングは、目で見たことを絵にする。

僕、音楽にしてもプログラミングにしても頭の中にあるものを具体的にアウトプットするために、めちゃくちゃ時間がかかって、心折れそうになるんだけど、それってトレーニングが足りてないんだ。。。ということがわかった。 トレーニングします。

トレーニングの種類

本に書いてあって学んだこと

  • 平面に書いてある絵を平面に写すトレーニング。比較的、簡単。線を描くスキルが必要。
  • 現実にある立体的なものを平面に書くトレーニング。比較的、難しい。線を描くスキルに加えて、構図を考えたり、陰影をつけたりするスキルも必要になってくる。

音楽だと、譜面に書いてある音楽をコピーするのと、流れている音楽を耳コピするのの違いかなあと思った。 プログラミングだと、ソースコードを写経する、仕様からコードを書く、要求から仕様を決めてコードを書く、とか段階がありそうだなあと思った。

終わり

全体的に、僕は、いきなり全部やろうとして、時間がかかりすぎてあっぷあっぷしてる感じがある。もっと下からレベルを上げていきたい。下積みを増やしたい。

プログラミングならソースコード写経のレベルをあげていこう。 音楽なら、譜面をコピーしまくろう。

もっと手を動かす時間を増やそう。

集中する時間はどうするのがよいか

朝の通勤時間に考えてたことを、書きます。

それは、集中する時間はどうなるのがいいんだろう?って話です。別に結論はありません。

集中する時間とは

ここでいう集中する時間は、1つのことに取り組んでいる時間です。

何かをはじめたら開始。別のことをはじめたら終了。別のことを考え始めても終了。です。

なぜ集中する時間を増やしたいか

なんとなく、仕事が早く進みそうに思うから。

と言うか僕は、複数のことを同時にやるとパフォーマンスがどんどん下がっていくようなので、同時にやることは一つに絞りたいです。

自分だけで完結せず並行してタスクが動くときは、jobリストを作って、定期的にそのリストをポーリングする方がストレスフリーですし、パフォーマンスあがります。これは人それぞれな気がします。

集中する時間の測り方

今のところ、アプリを使って測っています。

何かを始める前に、タイマーをスタートして、終わったらタイマーをとめる。

タイマーが動いているときは、一つのことしかできない。と考えてタイマーの開始ボタンを押します。別のことが気になってきたら、停止ボタンを押します。

つまり、タイマーが動いているときは、一つの事しかやってない。ということです。

このやり方だと、何をやるか、を決めないと集中を開始できないことになってます。

僕は、今、Togglというアプリで測っています。TimeCrowdというアプリでもいいかもしれません。もっと他に良いアプリがあるかもしれません。

集中する時間の増減

時間を測って分析すると次のようなことがわかります。

  • 合計でどれくらいの時間、集中したか
  • その集中時間がどれくらい長いか短いか
  • 集中している時間の割合はどうか
  • 全体のパフォーマンスと集中時間に関係はあるか
  • どんなタスクだと集中できたか

集中する時間の密度

集中する時間にも密度があるはず。

1つのことをやってるとき、ものすごく集中してることもあれば、とりあえず1つのことをやってることもある。

集中力には、集中度合いがあるはず。

集中力の総量

1人の人が1日に使える集中力の総量があるはず。

どれくらい集中しているかを集中度、と言うすると、1人の人が1日に使える集中力は、集中度と集中した時間の掛け算の積になると思う。

集中する時間の量

集中する時間は、多い方が良いのか短い方が良いのか。

1人が1日に使える集中力に上限があるとすれば、毎日その限界まで使う方が良いようなきがする。でも集中力って毎日上限まで使って大丈夫なのかな。

とりあえず、1日あたり適切な集中力のバランスがある気がす。

おわり

とりあえず時間がきたのでおわります。

まとまりのない文を読んでくれてありがとうございました。

では。

レベルがあがるってなんだろう

上手い。ってなんなんだろう?

何かしらのレベルの高さを示す言葉な気がする。

経験から考えてみて、音楽制作にしてもソフトウェア開発にしても、かけた時間とレベルが一致するわけじゃない。

例えば、僕より音楽制作に使った時間が少ない人が僕より音楽制作が上手いことはある。その逆もある。

つまり、同じだけ時間を消費しても上手くなり度合いが違う、という事。時間をかけてない人が上手いことはないので、時間とレベルには相関があるけど、他の要因も関係してると思う。

じゃあ、何が理由で違うんだろう。

というか、単純に、同じだけ時間をかけたのにAさんは上手くなって、自分は上手くならなかった。という状況は納得がいかない気持ちがある。

かけた時間が少なかったから上手くならなかった。という話なら、努力が足りない。という話になるし、努力の話になってくると、まあ納得いく気持ちがある。でも、時間じゃなさそう、となると、時間をかける気持ちが薄れる。

その理由がわからないと、また同じように時間をかけたのにあんまりレベルがあがらない状況になるんじゃないか、と思ってしまう。

そんなことを考えてたら、1つの本を見つけた。

絵はすぐに上手くならない

絵はすぐに上手くならない

買った。(まだ読んでない)

上手くなる。ということについて本1冊書いてるのは興味がある。

まだ目次をパラパラしただけだけど、いろいろ気になることは書いてありそう。

読み終わったら、感想をブログに書こうかなーという気持ち。

gitのrebaseを簡単に試して見た。

gitのrebaseがよくわかっていない部分があるので、勉強したいと思う。

このあたりを読んでも文章が長くていまいちしっくりこない。というか矢印の向きとか図形の定義がよくわからなかったり、何を見たらいいのかわからなくて戸惑う。

Git - リベース

最近、何となく進んできた理解では、rebaseは、「今使っているブランチを派生させる場所を変更するコマンド」というイメージになっている。

その理解が正しいのかを確かめたい。

まずは、ローカルに動作確認用のリポジトリを作る。

$ cd git-rebase-test/
$ git init
Initialized empty Git repository in /Users/mtb/work/git-rebase-test/.git/
$ ll
.    ..   .git

とりあえず、masterブランチに、ファイルを一つ作る。

$ echo test1 >> ChangeLog.txt
$ cat ChangeLog.txt
test1
$ git status
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    ChangeLog.txt

nothing added to commit but untracked files present (use "git add" to track)
$ git add ChangeLog.txt
$ git commit -m "test1 commit"
[master (root-commit) 8296084] test1 commit
 1 file changed, 1 insertion(+)
 create mode 100644 ChangeLog.txt
$ git log
commit 82960845db034126e9ff913e7ed3bc30c2034165 (HEAD -> master)
Author: mtb_beta <example@example.com>
Date:   Thu Nov 30 07:32:55 2017 +0900

    test1 commit
$ git branch -a
* master

ここから、ブランチを作ってチェックアウトする。ブランチ名は、 branch1 にしよう。

$ git branch branch1
$ git checkout branch1
Switched to branch 'branch1'
$ git branch
* branch1
  master

追記してコミットする。3回やろう。

$ echo branch1-1 >> ChangeLog.txt
$ cat ChangeLog.txt
test1
branch1-1
$ git add ChangeLog.txt
$ git commit -m "branch1-1 commit"
[branch1 000ab89] branch1-1 commit
 1 file changed, 1 insertion(+)
$ echo branch1-2 >> ChangeLog.txt
$ git add ChangeLog.txt
$ git commit -m "branch1-2 commit"
[branch1 42ea439] branch1-2 commit
 1 file changed, 1 insertion(+)
$ echo branch1-3 >> ChangeLog.txt
$ git add ChangeLog.txt
$ git commit -m "branch1-3 commit"
[branch1 ca1720e] branch1-3 commit
 1 file changed, 1 insertion(+)

ファイルの中身とgitのログを見る。ChangeLog.txtに3回のコミットが追加されている。

$ cat ChangeLog.txt
test1
branch1-1
branch1-2
branch1-3
$ git log
commit ca1720e8913b2e0a8ec7b8767eac9a8c326464fb (HEAD -> branch1)
Author: mtb_beta <example@example.com>
Date:   Thu Nov 30 07:41:05 2017 +0900

    branch1-3 commit

commit 42ea439a6ba204468c0e037b640b36f08d5dbe0e
Author: mtb_beta <example@example.com>
Date:   Thu Nov 30 07:40:52 2017 +0900

    branch1-2 commit

commit 000ab898c73855aa0265025bd805ae052d38386a
Author: mtb_beta <example@example.com>
Date:   Thu Nov 30 07:39:57 2017 +0900

    branch1-1 commit

commit 82960845db034126e9ff913e7ed3bc30c2034165 (master)
Author: mtb_beta <example@example.com>
Date:   Thu Nov 30 07:32:55 2017 +0900

    test1 commit

次は、masterブランチのChangeLog.txtに修正を加えよう。それぞれは、別のコミットにする。

  • ChangeLog.txt の先頭行に「ChangeLogs」を追加
  • ChangeLog2.txt に 「test2」
$ git checkout master
Switched to branch 'master'
$ vim ChangeLog.txt
$ cat ChangeLog.txt
ChangeLogs
test1
$ git add ChangeLog.txt
$ git commit -m "change logs commit"
[master 5f50b58] change logs commit
 1 file changed, 1 insertion(+)
$ echo test2 >> ChangeLog2.txt
$ cat ChangeLog2.txt
test2
$ git add ChangeLog2.txt
$ git commit -m "change log2 add"
[master f76437a] change log2 add
 1 file changed, 1 insertion(+)
 create mode 100644 ChangeLog2.txt

git logを見て見る。masterブランチに二つのコミットがついた状態になっている。

$ git log
commit f76437af8af7fd44e09170968aeb45f1771674b1 (HEAD -> master)
Author: mtb_beta <example@example.com>
Date:   Thu Nov 30 07:47:51 2017 +0900

    change log2 add

commit 5f50b58689b86514224c4b2b59caa1a809954ea8
Author: mtb_beta <example@example.com>
Date:   Thu Nov 30 07:47:00 2017 +0900

    change logs commit

commit 82960845db034126e9ff913e7ed3bc30c2034165
Author: mtb_beta <example@example.com>
Date:   Thu Nov 30 07:32:55 2017 +0900

    test1 commit

banch1 は、commit 82960845db034126e9ff913e7ed3bc30c2034165 から派生したブランチだけど、新しく含まれている2つのブランチも取り込みたい。

こういう時にrebaseを使う。(多分。) 使って見る。

まずは、取り込みたいブランチにcheckoutする。そして、masterにrebaseする。 じゃあ色々ログが流れる。 ログを読むとわかるけど、masterのheadに戻って、そこから新しいコミットを適応していく。

$ git checkout branch1
Switched to branch 'branch1'
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: branch1-1 commit
Using index info to reconstruct a base tree...
M   ChangeLog.txt
Falling back to patching base and 3-way merge...
Auto-merging ChangeLog.txt
Applying: branch1-2 commit
Using index info to reconstruct a base tree...
M   ChangeLog.txt
Falling back to patching base and 3-way merge...
Auto-merging ChangeLog.txt
Applying: branch1-3 commit
Using index info to reconstruct a base tree...
M   ChangeLog.txt
Falling back to patching base and 3-way merge...
Auto-merging ChangeLog.txt

修正後のファイルを見て見ると、無事にマージされている様子。

$ ll
.              ..             .git           ChangeLog.txt  ChangeLog2.txt
$ cat ChangeLog.txt
ChangeLogs
test1
branch1-1
branch1-2
branch1-3
$ cat ChangeLog2.txt
test2

ログを見てもそうなっている。

$ git log
commit 0e639b0330dfebc47e503f7eb6e95091169c2765 (HEAD -> branch1)
Author: mtb_beta <example@example.com>
Date:   Thu Nov 30 07:41:05 2017 +0900

    branch1-3 commit

commit 3c301cf904baa9e61202c401b51270eb43668a60
Author: mtb_beta <example@example.com>
Date:   Thu Nov 30 07:40:52 2017 +0900

    branch1-2 commit

commit 02ebe3df591fefbab1d2d7d438aa40becef5526b
Author: mtb_beta <example@example.com>
Date:   Thu Nov 30 07:39:57 2017 +0900

    branch1-1 commit

commit f76437af8af7fd44e09170968aeb45f1771674b1 (master)
Author: mtb_beta <example@example.com>
Date:   Thu Nov 30 07:47:51 2017 +0900

    change log2 add

commit 5f50b58689b86514224c4b2b59caa1a809954ea8
Author: mtb_beta <example@example.com>
Date:   Thu Nov 30 07:47:00 2017 +0900

    change logs commit

commit 82960845db034126e9ff913e7ed3bc30c2034165
Author: mtb_beta <example@example.com>
Date:   Thu Nov 30 07:32:55 2017 +0900

    test1 commit

終わり

  • gitのrebaseを簡単に試して見た。
  • 当初抱いていた「今使っているブランチを派生させる場所を変更するコマンド」というイメージは、ある意味では間違ってないけど、厳密にいうと違う。
  • (多分、)指定したブランチのHEADから、現在のブランチに加えられたコミットを再適用するのがrebase。(ややこしい)
  • とはいえ、git reset ってなんだろう。とか HEAD って僕の理解で合ってるのかな。とか疑問はまだあるので、これもそのうち確かめたい。