ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • dart mixin 클래스를 이용한 검증 로직 분리
    flutter 2021. 11. 23. 18:29


    단순히 제목과 내용을 입력하는 게시판이 아닌,
    투표 기능이 첨부된 게시판을 만들고있는데 입력 폼이 많다보니 폼에 입력된 텍스트가 올바른가 검증하는 과정이
    복잡해졌습니다. 투표답변 UI를 만들고 그안에 제대로 답변을 채워넣었는지, 너무길게 넣진 않았는지, 투표항목은 2개 이상인지, 5개 이하인지, 글제목은 입력했는지 등등..

    더구나 요구사항이 개별 검증성이 맞지 않을때마다 개별 알람창을 띄워줘야 해서 더욱 복잡했습니다.
    입력된 텍스트의 적합성을 따지는 검증작업을 bloc로 따로 처리할까 등 많은 생각을하다..
    dart언어에서는 mixin 이라는 코드 재사용이 가능하게 해주는 클래스가 있어 이용해보았습니다.





    class _WriteScreenState extends State<WriteScreen> with ValidatorMixin  {

      클래스 바디..

    }

     글쓰기창 있는 클래스에 with 를 붙이고 mixin 클래스를 명시해줍니다.


    mixin ValidatorMixin<T extends StatefulWidget> on State<T> 클래스를 만들어주면 상태가 있는 mixin 클래스 생성이 가능하고,
    initState 메소드에서 Bloc의 상태값을 가져올 수 있습니다.

    이 클래스를 검증이나 기타 기능 수행으로 사용할 것이기 때문에 따로 build 메소드를 오버라이드해서 화면을 그려주진 않습니다.







    코드 재구성 전에는 WriteScreen 클래스에서 글쓰기 완료 버튼을 누르면

     TextButton(
                    onPressed: () async {


      복잡한 조건문과 검증로직들...
                      
                    },
                    child: Text("등록",
                        style: theme.textTheme.subtitle1!
                            .apply(color: AppColors.primary)))


    기존에는 이 버튼 onPressed 함수안에 복잡한 로직을 전부 적어 검증을 수행했지만,
    UI 클래스에 너무많은 비즈니스로직이 들어가 가독성이 상당히 떨어졌습니다.

    조건문도 너무많이 들어가야하고, bloc을 투표bloc과 일반게시글bloc으로 나눠놨기 때문에

    글등록버튼 누르는순간 여러개의 bloc의 state value에 접근하는 과정에서 너무 코드가 길어졌습니다.

    그래서 상태가 있는 mixin 클래스를 사용하여 검증과정 자체를 mixin 클래스에서만 수행하도록 분리했습니다.

     


    수정후의 코드도 많이 짧다고는 못하겠지만 최대한 정리를 해보았습니다.


    수정후 -->

     

    (WriteScreen, 글쓰기 화면의 구현부..)



    class _WriteScreenState extends State<WriteScreen> with ValidatorMixin {

      late final PostBloc _getBloc;

      late final VoteBloc _voteBloc;


      @override
      void initState() {
        super.initState();
        _getBloc = BlocProvider.of<PostBloc>(context); 

       _voteBloc = BlocProvider.of<VoteBloc>(context);

    }

     

    중간생략....

    중간생략....

     

     


    TextButton(
              onPressed: () async {

    // 먼저 검증 함수를 수행하고 true일시 블록에 글쓰기 이벤트를 던지는데, baseValidator 함수에 검증할 값을 넘겨줄 필요가없습니다.
    // 왜냐면 ValidatorMixin 에서 bloc을 통해 실시간으로 작성중인 값에 접근할 수있기 때문입니다.
             
            if(baseValidator()) {

                 _getBloc.add(
    // makeBlocEvent 함수에서 event클래스를 생성해주고 그값이 Bloc에 add된다.
                     makeBlocEvent(


    // 글등록 버튼을 누른시점에서,  투표창이 활성화된 상태이면(bloc state가 EditingVoteListState)

    모델값을 생성한뒤 블록이벤트의 프로퍼티에 추가해준다.

    // makeModelItemFromMap함수는 enum값에 따라 모델값을 만들어서 리턴해주는 함수.. 

    // enum 값에 따라 어떤 모델을 만들것인지 정해줍니다.


    vote: _voteBloc.state.runtimeType == EditingVoteListState ?

    makeModelItemFromMap(modelTypeEnum.vote) : null,

     

    voteList: _voteBloc.state.runtimeType == EditingVoteListState ?

    makeModelItemFromMap(modelTypeEnum.voteList) : null,
                         
                           ));
                      }
                    },
                    child: Text("글등록"))



    (검증을 수행하는 ValidatorMixin클래스)
    mixin ValidatorMixin<T extends StatefulWidget> on State<T> {

      late final VoteBloc _voteBloc;
      late final PostBloc _getBloc;
      late final ImageBloc _imgBloc;

      @override
      void initState() {
        super.initState();

        _voteBloc = BlocProvider.of<VoteBloc>(context);
        _getBloc = BlocProvider.of<PostBloc>(context);
        _imgBloc = BlocProvider.of<ImageBloc>(context);
       
      }


    * mixin ValidatorMixin 클래스 내부의 함수들

      // 이곳에서 수행하는 검증 종류에 따라 분기를 해준다.
      baseValidator() {
        VoteState voteState = BlocProvider.of<VoteBloc>(context).state;

        switch(voteState.runtimeType){
          case EditingVoteListState :
            // 생략...

          default :
            // 투표 첨부 없이 단순 글 제목만 있는 경우, 여기서는 postValidator만 기재함...
            return postValidator( );
        }
      }

     

     

      bool postValidator( ){
        // 검증을 수행하는 함수 

          bool votePostValidate = false;

          AppVote? appVote = makeModelItemFromMap(modelTypeEnum.appVote);
          List<AppVoteItem> voteList = makeModelItemFromMap(modelTypeEnum.listVoteItem);

          if(validateVote(validateVoteTitle(appVote), validateItemArray(voteList)) ){
            // 검증할 값이 다양하여 복잡한 코드는 생략..
              // 중간생략 블라블라...

    votePostValidate = true;
          }
        return votePostValidate;
      }










Designed by Tistory.