# 코드리뷰 - Flutter (2022.10.12)

# boolean assign

# as is

onChanged: () {
    if (_emailController.text.length > 0) {
        setState(() {
            _signInEmailEnabled = true;
        });
    } else {
        setState(() {
            _signInEmailEnabled = false;
        });
    }
},

if (a == b) result = true;
else result = false;
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# to be

onChanged: () {
    setState(() {
        _signInEmailEnabled = _emailController.text.length > 0;
    });
},

result = (a == b);
1
2
3
4
5
6
7

# inline method

# as is

class SingUpModel extends ... {
  void signup() {
    Get.toNamed(AppRoutes.sign_up);
  }

  void findPassword() {
    Get.toNamed(AppRoutes.find_password);
  }

  ...
}

class MainView extends ... {
    ...
    void ...() {
        onClick: singUpModel.signup();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# to be

class MainView extends ... {
    ...
    void ...() {
        onClick: Get.toNamed(AppRoutes.sign_up);
    }
}
1
2
3
4
5
6
  • inline method 처리
    • 메소드의 코드 내용이 의미하는 바가 명확해서 메소드를 삭제하고 코드 자체를 사용한다.

# getter 활용

# as is

onModelReady: (model) async {
    await model.init(view);
    isLogin = model.loginUser != null;
},
1
2
3
4
  • isLogin 이후에 loginUser의 상태가 변한다면?

# to be

bool get isLogin => model.loginUser != null;
1

TIP

model.logined와 같이 모델 안에 속성으로 처리

# flag 파라메터 & null return

# as is

Future<User?> getUser({bool? isSync}) async {
    User? loginUser;
    try {
        if (isSync == false) {
            String? userData = _keyStorageService.loginUserData;
            if (userData?.isNotEmpty ?? false) {
                loginUser = User.fromJson(jsonDecode(userData!));
            }
        } else {
            final response = await httpService.callGet("/api/v1/users/me");
            loginUser = User.fromJson(response.data["user"]);
        }
    } catch (e) {
        developer.log("회원정보 호출 에러", error: e, name: 'UserService');
    }

    return loginUser;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# to be

User getUserFromLocalStorage() {
    User loginUser = User();
    String userData = _keyStorageService.loginUserData ?? "";
    if (userData.isNotEmpty) {
        loginUser = User.fromJson(jsonDecode(userData));
    }
    return loginUser;
}

Future<User> getUserFromServer() async {
    User loginUser = User();
    try {
        final response = await httpService.callGet("/api/v1/users/me");
        loginUser = User.fromJson(response.data["user"]);
    } catch (e) {
        developer.log("회원정보 호출 에러", error: e, name: 'UserService');
    }
    return loginUser;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  • flag 파라메터 대신 메소드를 분리한다.
  • null을 리턴하는 것을 최소화 한다.

# 타이머를 통한 라우팅 처리 제거 등

# as is

class SinginModel extends ... {
    Future<void> signin({...}) async {
        busy();
        try {
            final responseResult = await userService.signin({required String email, required String password});
            if (responseResult != null && (responseResult.user != null)) {
                    if (responseResult.user?.influencer?.confirmed_step == EnumUtils.getEnumName(InfluencerConfirmStep.withdrawal)) {
                        inputErrorMessage = "탈퇴한 계정입니다. ...";
                    } else {
                        Get.offAllNamed(AppRoutes.splash);
                        if (await connectedInstagramAndNotConnectedInstaPro()) {
                            Future.delayed(const Duration(seconds: 3), () => Get.toNamed(...));
                    }
                }
            } else {
                inputErrorMessage = '이메일 또는 비밀번호를 잘못 입력하셨습니다.';
            }
        } finally {
            idle();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# to be

class SinginModel extends ... {
    void signin({required String email, required String password}) async {
        final responseResult = await userService.signin(...);
        if (responseResult == null || responseResult.user == null) {
            inputErrorMessage.value = '이메일 또는 비밀번호를 잘못 입력하셨습니다.';
            return;
        }

        final confirmed_step = responseResult.user.influencer.confirmed_step;
        final hasWithdrawed =
            InfluencerConfirmStep.fromString(confirmed_step) ==
            InfluencerConfirmStep.withdrawal;
        if (hasWithdrawed) {
            inputErrorMessage.value = "탈퇴한 계정입니다. 고객센터에 문의 부탁드립니다.";
            return;
        }

        Get.offAllNamed(AppRoutes.splash);
    }
}

class MainView extends ... {
    
    void initState() {
        super.initState();
        singinModel.checkInstAndInstaProConnected();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  • GetX를 통해서 signin() 호출을 기다릴 필요 없도록 처리 (데이터 바인딩)
  • 길고 복잡한 조건문의 경우 임수 변수로 처리
  • 열거형과 문자열 비교 방식 변경
    • 열거형 안에 메소드 추가
    • confirmed_step의 type을 InfluencerConfirmStep 처리
  • 타이머를 통한 라우팅 처리 제거
  • busy() 처리를 서버를 호출하는 곳에서 처리

# 기타

# Warnning 메시지 확인 후 처리

# 에러 로그 확인 후 처리