LoginSignup
23
22

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-03-06

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

細かな方針について

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

23
22
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
22