[Flutter] 코드 리팩토링(refactoring)

박망키·2022년 3월 3일
1

Flutter 야금야금 먹기

목록 보기
23/97

리팩토링(refactoring)이란?

코드를 보다 더 간결하게 만들고 코드의 재사용성을 증대시키는 방법.

이 한페이지에 고작 버튼 3개 들어있는데 코드가 이~~렇게 길다 🤨🤨

import 'package:flutter/material.dart';

class Login extends StatefulWidget {
  const Login({Key? key}) : super(key: key);

  @override
  State<Login> createState() => _Login();
}

class _Login extends State<Login> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Sign in',style: TextStyle(color: Colors.white)),
          centerTitle: true,
        ),
        body: Padding(
          padding: const EdgeInsets.all(10.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ButtonTheme(
                  child: ElevatedButton(
                      style: ElevatedButton.styleFrom(
                        primary: Colors.white,
                      ),
                      onPressed: () {},
                      child: Padding(
                        padding: const EdgeInsets.all(5.0),
                        child: Row(
                          children: [
                            Image.asset('assets/images/google.png', width: 30),
                            SizedBox(width: 40),
                            Text('Login with Google'),
                          ],
                        ),
                      ))),
              SizedBox(height: 3),
              ButtonTheme(
                  child: ElevatedButton(
                      style: ElevatedButton.styleFrom(
                        primary: Colors.white,
                      ),
                      onPressed: () {},
                      child: Padding(
                        padding: const EdgeInsets.all(5.0),
                        child: Row(
                          children: [
                            Image.asset('assets/images/facebook.png',
                                width: 30),
                            SizedBox(width: 40),
                            Text('Login with Facebook',
                                style: TextStyle(color: Color(0xffb3A589E))),
                          ],
                        ),
                      ))),
              SizedBox(height: 3),
              ButtonTheme(
                  child: ElevatedButton(
                      style: ElevatedButton.styleFrom(
                        primary: Color(0xffb499959),
                      ),
                      onPressed: () {},
                      child: Padding(
                        padding: const EdgeInsets.all(5.0),
                        child: Row(
                          children: [
                            Image.asset('assets/images/mail.png', width: 30),
                            SizedBox(width: 40),
                            Text('Login with Email',
                                style: TextStyle(color: Colors.white)),
                          ],
                        ),
                      )))
            ],
          ),
        ));
  }
}

코드 리팩토링을 통해 정리해보자

lib폴더안에 따로 빼둔 버튼을 모아둘 폴더를 만들고 그 안에 my_login_button.dart파일을 만들었다.

만든 파일에 따로 빼두고 싶은 버튼을 그대로 복사해서 붙여넣기 한다

싹 긁어서

Container()위치에 붙여넣기~!(이때 리턴 마지막의 세미콜론이 빠지지않게 주의)

이렇게 만들어 준다.

이제 이걸 활용해서 재사용이 가능한 코드를 만들어보자~!
바뀌는요소: 1. 로고이미지, 2.텍스트, 3.버튼색상, 4.클릭이벤트

지난번 build메서드내에서 리빌드 될수 있는건 final변수였다.
속성들을 위한 저 변수 모두 final로 지정을 하고 속성을 필요로 하는 곳에 변수의 타입을 지정해주면된다.
class 왜 자꾸 밑줄로 경고뜨나했더니 카멜케이스 안썼다고 뜨는거였다 ,,기억하자 클래스는 첫글자대문자..카멜케이스..

많은 코드를 함수로 한번에 묶는방법
body뒤의 코드들을 한번에 묶고 싶다~!
그러면 body:~부터 닫는곳까지 드래그 하고 우클릭후 Refactor-Extract Method를 눌러주면

짜잔~ 이런식으로 함수명이 생기고(설정할수있다) 아래에 따로 코드가 분리 된걸 볼수 있다.

_ 함수명에 언더스코어를 붙여서 접근불가능한 프라이빗한요소로 만들자(접근제어자)
같은파일내에서만 접근 가능하다(외부에서 불필요한 접근을 못하게 해서 함부로 데이터가 변경되는걸 막음)

이제 만들어둔 MyLoginButton클래스를 이용해서 버튼하나를 더 추가해보자

결과

다른 버튼들도 MyLoginButton으로 바꾸자~!


속이다 후련하네~~~!
vue로 컴포넌트 짤때 느낌이 나는데 prop emit에 비해 더 간편하고 직관적인거 같다!😍
그리고 따로 my_login_button.dart를 어딘가에 전역적으로 선포하지 않더라도 편하게 가져다 쓸수있는점이 굉장히 맘에든다(vue는 만들고 index.js에서 export하고..main.js에서 import하고..폴더위치 바뀌면 index.js가서 또 수정해주고......파일명 다르면 에러뜨고...)

➕ 추가

보다보니 저 코드도 불-편 해졌다
변수는 다 빼놓고 공통된요소하나로 반복해서 보여줄수 없을까 생각하다가 ListView가 생각났다

MyLoginButton()의 위젯에서 변수도 조금더 쏙쏙 들어갈수있게 변수 자리에 넣어줬다(기존 Widget타입에서 String으로 바꿈)

버튼이 생성되는페이지(login.dart)에서 변수요소들을 배열로 따로 다 빼주었다.

그리고 기존 MyLoginButton이 있던곳에 ListView.builder로 리스트 형식으로 만들어 줬다.
itemCount는 ButtonList갯수만큼,itemBuilders는 만들어둔 MyLoginButton을 리턴하게 하고 인자로 ButtonList[index]의 변수를 넣어주었다.

shrinkWrap:true를 안넣으면 상위 Column의 MainAxisAlignment.center가 적용되질 않아서 세로축중앙 정렬이 되지않는다.
shrinkWrap가 어떤속성일까 하고 찾아보니 스크롤보기 범위가 보고있는 내용에 따라 결정되어야 하는지 여부라고 한다 😦

(일반적으로 ListView뿐만 아니라 GridView, PageView 및 CustomScrollView 는 목록 항목에 필요한 공간이 더 적은 경우에도 상위 요소에서 제공하는 모든 사용가능한 공간을 채우려고 한다고 한다)

기본값은 false이고

ShrinkWrap 속성 을 설정하지 않으면 ListView 가 부모만큼 커진다. true로 설정하면 목록이 콘텐츠를 래핑하고 자식이 허용하는 만큼 커진다.

결과

코드

<script>
import 'package:flutter/material.dart';
import 'package:newflutter/my_button/my_login_button.dart';

class Login extends StatefulWidget {
  const Login({Key? key}) : super(key: key);

  @override
  State<Login> createState() => _Login();
}

class _Login extends State<Login> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Sign in', style: TextStyle(color: Colors.white)),
          centerTitle: true,
        ),
        body: _buildPadding());
  }

  Widget _buildPadding() {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        ListView.builder(
          padding: const EdgeInsets.all(10.0),
          itemCount:ButtonList.length ,
          shrinkWrap: true,
          itemBuilder:(BuildContext context, int index){
            return  MyLoginButton(
              image:'${ButtonList[index]['image']}',
              text:'${ButtonList[index]['text']}',
              btnColor:'${ButtonList[index]['btnColor']}',
              onPressed: () {},
              textColor: '${ButtonList[index]['textColor']}',
            );
          } ,
        ),
      ],
    );
  }
}
const ButtonList = [
  {
    "image":"facebook.png",
    "text":"Login with Facebook",
    "textColor":"b3A589E",
    "btnColor":"ffffff",
  },
  {
    "image":"dog.jpg",
    "text":"Login with Dog",
    "textColor":"AF496F",
    "btnColor":"ffffff",
  },
  {
    "image":"google.png",
    "text":"Login with Google",
    "textColor":"000000",
    "btnColor":"ffffff",
  },
  {
    "image":"mail.png",
    "text":"Login with Mail",
    "textColor":"ffffff",
    "btnColor":"489959",
  },
];

</script>

조금...맘이 편해진거 같다 🥰🥰
더 간결한 방법이 있으면 또 바꿔야지

profile
무럭무럭 자라는 망키

0개의 댓글