Objective-C: リファクタリングする際の基本方針

個人的にリファクタをする中で蓄積された、自分なりのリファクタの方針をまとめてみます。
ここは間違ってる、普通はこうしない、もしそうするならこうしたほうがいい、などの内容があれば、ぜひご教示ください。（コメントしていただければと思います。）

<h2>細かな方針について</h2>
* メソッドや変数はできるだけ具体的に書く。 </br>
ex) initView ではなく、initTestView や、何か該当する目的語を書く。
</br>
</br>

* 必要以上にクラス内の動詞の種類を増やさない</br>
ex) init や get など、定番の動詞をできるだけ使う。
</br>
</br>

* メソッド内で主に使う変数はメソッド名に含める。引数もうまく使う。</br>
ex) stopLearning ではなく、stopLearningWithAlertView や stopLearningWithAlertView:(FUIAlertView *)alertView など。
</br>
</br>

* アクションの書き方は基本的な形に固定・統一。</br>
ex) ボタンを押した時の動作は hogeButtonPushed
</br>
</br>

* BOOL は hasHoge や isFoo など、yes/no で答えられる書き方に統一。</br>
ex) BOOL isRankupTestFailed
</br>
</br>

* image は特定の画像を使う場合は、画像ファイルの名前でもいいのでは。</br>
ex) UIImage *anImage ではなく、UIImage *homeButtonImage など
</br>
</br>

* 変数だけではなく、定数も活用する。</br>
ex) #define TIME_OVER 5
</br>
</br>

* メソッドの並び・構成にも意味を持たせる。
ex) timer 関連のメソッドは同じ箇所に並べて、まとめる。動作の順にメソッドを並べる。
</br>
基本的にはメソッドは初期化=>設定=>各機能ごとのメソッド群、という順で書く。
（最初は必ず初期化。無駄な設定が残って、他の動作に影響を与えないように。）
</br>
</br>

* メソッドの肥大化より、入れ子（ネスト）の回避。</br>
以下のようなリファクタは避ける。メソッドの切り出しではなく、改行やコメントで対応。</br>
※複数箇所で同様のコードが使われている場合を除く。複数箇所でそのコードが使われている場合、一つのコードにまとめる。
</br>
</br>

```objc
[リファクタ前]
[_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];
}
```

* 可能な限り、ヘッダーファイルから編集する。</br>
変数名だけで理解できるかよい指標になる。また、変数がストーリーボードと関連する場合、ヘッダーファイルで変数名をリファクタしないとエラーが生じる。（再現条件については不確定なので、要検証）ヘッダーファイルからリファクタに取り掛かることで、不必要な変数にも気づけるし、変数に同じ命名規則を適用しやすい。
</br>
</br>

* メソッドのリファクタはそのメソッドが再利用される時(※)</br>
ex) 以下の二つのメソッドは、リファクタ後のメソッド一つで両方表現できる。
</br>
</br>

```objc
[リファクタ前]
-(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];
    }
}
```

<h2>リファクタの順序</h2>
1.ヘッダーファイルで変数名の確認と修正
2.修正後、機能群毎に並び替え
3.変数をグループ化できる場合は、統一命名規則を適用
ex1) 変数の書き方を countDownHoge に統一

```objc
UIImageView *countDownFromOneSecondImageView;
UIImageView *countDownFromTwoSecondsImageView;
UIImageView *countDownFromThreeSecondsImageView;
```

ex2) testedWords で統一 (複数形も一応意識)

```objc
NSMutableArray* testedWordsArray;
NSMutableArray* testResultsArray;
int testedWordIndex;
NSMutableArray* testedWordIndexesArray;
```

4.不必要な変数を削除（機能ごとに並べると実はいらなくなってる変数が浮き上がる）
必要に応じてコメントを添える
ex) View の部品は ```// Module``` でまとめる。

```objc
// 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.実装ファイルでも同様に、
変数の確認・修正=>並び替え=>不必要なメソッドを削除=>必要に応じてコメントを添える
加えて、冗長なコードを簡潔で汎用的なメソッドに書き直す。(※参照)