個人的にリファクタをする中で蓄積された、自分なりのリファクタの方針をまとめてみます。
ここは間違ってる、普通はこうしない、もしそうするならこうしたほうがいい、などの内容があれば、ぜひご教示ください。(コメントしていただければと思います。)
細かな方針について
* メソッドや変数はできるだけ具体的に書く。 ex) initView ではなく、initTestView や、何か該当する目的語を書く。- 必要以上にクラス内の動詞の種類を増やさない
ex) init や get など、定番の動詞をできるだけ使う。
- メソッド内で主に使う変数はメソッド名に含める。引数もうまく使う。
ex) stopLearning ではなく、stopLearningWithAlertView や stopLearningWithAlertView:(FUIAlertView *)alertView など。
- アクションの書き方は基本的な形に固定・統一。
ex) ボタンを押した時の動作は hogeButtonPushed
- BOOL は hasHoge や isFoo など、yes/no で答えられる書き方に統一。
ex) BOOL isRankupTestFailed
- image は特定の画像を使う場合は、画像ファイルの名前でもいいのでは。
ex) UIImage *anImage ではなく、UIImage *homeButtonImage など
- 変数だけではなく、定数も活用する。
ex) #define TIME_OVER 5
- メソッドの並び・構成にも意味を持たせる。
ex) timer 関連のメソッドは同じ箇所に並べて、まとめる。動作の順にメソッドを並べる。
- メソッドの肥大化より、入れ子(ネスト)の回避。
以下のようなリファクタは避ける。メソッドの切り出しではなく、改行やコメントで対応。
※複数箇所で同様のコードが使われている場合を除く。複数箇所でそのコードが使われている場合、一つのコードにまとめる。
[リファクタ前]
[_rightButton setButtonColor:[UIColor turquoiseColor]];
[_rightButton setShadowColor:[UIColor greenSeaColor]];
[_rightButton setHighlightedColor:[UIColor turquoiseColor]];
[_rightButton setDisabledColor:[UIColor turquoiseColor]];
[_rightButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[リファクタ後]
-(void)setRightButton{
[_rightButton setButtonColor:[UIColor turquoiseColor]];
[_rightButton setShadowColor:[UIColor greenSeaColor]];
[_rightButton setHighlightedColor:[UIColor turquoiseColor]];
[_rightButton setDisabledColor:[UIColor turquoiseColor]];
[_rightButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
}
- 可能な限り、ヘッダーファイルから編集する。
変数名だけで理解できるかよい指標になる。また、変数がストーリーボードと関連する場合、ヘッダーファイルで変数名をリファクタしないとエラーが生じる。(再現条件については不確定なので、要検証)ヘッダーファイルからリファクタに取り掛かることで、不必要な変数にも気づけるし、変数に同じ命名規則を適用しやすい。
- メソッドのリファクタはそのメソッドが再利用される時(※)
ex) 以下の二つのメソッドは、リファクタ後のメソッド一つで両方表現できる。
[リファクタ前]
-(void)playCountDownSound {
self.countDownSoundFilePath = [[NSBundle mainBundle] pathForResource:@"countDownSound"
ofType:@"mp3"];
self.countDownSoundFileUrl = [[NSURL alloc] initFileURLWithPath:self.countDownSoundFilePath];
self.countDownSoundPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:self.countDownSoundFileUrl error:nil];
[self.countDownSoundPlayer prepareToPlay];
[self.countDownSoundPlayer play];
}
-(void)playTestStartSound {
self.testStartSoundFilePath = [[NSBundle mainBundle] pathForResource:@"testStartSound"
ofType:@"mp3"];
self.testStartSoundFileUrl = [[NSURL alloc] initFileURLWithPath:self.testStartSoundFilePath];
self.testStartSoundPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:self.testStartSoundFileUrl error:nil];
[self.testStartSoundPlayer prepareToPlay];
[self.testStartSoundPlayer play];
}
[リファクタ後]
-(void)playSoundWithPath:(NSString *)fileName {
NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:@"mp3"];
NSURL *fileUrl = [[NSURL alloc] initFileURLWithPath:path];
NSError *error;
_soundPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileUrl error:&error];
if (error) {
DLog(@"%@",error);
} else {
[_soundPlayer play];
}
}
リファクタの順序
1.ヘッダーファイルで変数名の確認と修正 2.修正後、機能群毎に並び替え 3.変数をグループ化できる場合は、統一命名規則を適用 ex1) 変数の書き方を countDownHoge に統一UIImageView *countDownFromOneSecondImageView;
UIImageView *countDownFromTwoSecondsImageView;
UIImageView *countDownFromThreeSecondsImageView;
ex2) testedWords で統一 (複数形も一応意識)
NSMutableArray* testedWordsArray;
NSMutableArray* testResultsArray;
int testedWordIndex;
NSMutableArray* testedWordIndexesArray;
4.不必要な変数を削除(機能ごとに並べると実はいらなくなってる変数が浮き上がる)
必要に応じてコメントを添える
ex) View の部品は // Module
でまとめる。
// Modules
@property (strong, nonatomic) IBOutlet SAProgressBarView *progressBar;
@property (strong, nonatomic) IBOutlet UILabel *englishLabel;
@property (strong, nonatomic) IBOutlet FUIButton *button1;
@property (strong, nonatomic) IBOutlet FUIButton *button2;
@property (strong, nonatomic) IBOutlet FUIButton *button3;
@property (strong, nonatomic) IBOutlet FUIButton *button4;
@property (strong, nonatomic) IBOutlet UILabel *countLabel;
@property (strong, nonatomic) IBOutlet UIImageView *correctImageView;
@property (strong, nonatomic) IBOutlet UIImageView *incorrectImageView;
@property (strong, nonatomic) IBOutlet UIImageView *testResultImageView;
// Button actions
- (IBAction)buttonPushed:(id)sender;
5.実装ファイルでも同様に、
変数の確認・修正=>並び替え=>不必要なメソッドを削除=>必要に応じてコメントを添える
加えて、冗長なコードを簡潔で汎用的なメソッドに書き直す。(※参照)