마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

파일을 세분화 하고싶은데..

0 추천

저번에 DataLayer? 랑 ViewLayer랑 막 세분화하라고 하셔서.. 나름 분할하려고하는데..

string.xml에 정의 되어있는 string-array를 인터페이스로 나눠서 하려고하거든요..

근데 이게 배열하나다보니까 이거하나하는데 인터페이스 생성하고 enum 클래스 생성하고해서

액티비티에서 가져와도 괜찮은가 라는 생각이 들더라구요..

 

그래서 기존에 있던 enum 클래스에 코드한줄 넣으면 되는 일이긴한데.. 어떻게하면 좋을까요?

기존 인터페이스입니다

public interface WorkoutListSource {
    public List<String> getWorkoutListByPart(BodyType type);
}

기존 enum 클래스입니다

public enum BodyType {
    BACK(R.array.back_workout_list),
    CHEST(R.array.chest_workout_list),
    LEG(R.array.leg_workout_list),
    SHOULDER(R.array.shoulder_workout_list),
    BICEPS(R.array.biceps_workout_list),
    TRICEPS(R.array.triceps_workout_list),
    ABS(R.array.abs_workout_list);

    @ArrayRes
    private int resourceId;

    BodyType(int resourceId) {
        Log.d("확인용입나", "BodyType: ");
        this.resourceId = resourceId;
    }

    public int getResourceId() {
        return resourceId;
    }
}

 

제가 추가하려는 string.xml에 정의되어있는 string-array입니다

<!--   Body Part   -->
    <string-array name="dialog_list">
        <item>등</item>
        <item>가 슴</item>
        <item>하 체</item>
        <item>어 깨</item>
        <item>이 두</item>
        <item>삼 두</item>
    </string-array>

이걸 추가해야하는데,..이건 단순 BodyPart 그러니까 해당부위를 나타내는 리스트이고

BodyType은 해당 부위의 맞는 운동 리스트(string-array)를 가져와 정의하는 클래스인데

이 BodyPart리스트들을 BodyType에 그냥 넣을지..

 

아니면 한줄이더라고 더 직관성 있게 BodyPartSource 인터페이스와 BodyPart enum클래스를 새로 정의해서 분류하는게 나을까요?

 

 

그리고 추가적인 질문입니다만,

액티비티에서도 코드를 너무 onCreate나 프래그먼트의 경우 onCreateView에만 정의하는것같아

좀 정리하려고 합니다

init()이라는  함수를 정의하려하는데 여기에

findViewById()만 넣을지, 아니면 

layoutManager = new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false);
        rcv_dailyRecord.setLayoutManager(layoutManager);
        dailRecordItems = new ArrayList<>();
        dailyRecordAdapter = new DailyRecordAdapter();
        date = new Date();

이런 객체 생성하는것까지 다 넣을지.. 따로 넣는다면 이것도 새로 뭐 함수를 정의해서 할까하는데요..

어떻게 하면 좋을까요? 생명주기를 잘다룰줄알면 막 생명주기 함수들 정의해서 막 하고싶은데 아직 너무 어

렵네요 ㅠ

for(int i=0; i<dialog_str_list.length; i++) {
            dialogItems.add(new BodyPartModel(dialog_str_list[i]));
        }

그리고 이런 데이터를 넣어주는 작업조차 onCreate에서 하고있어 지저분해보여서

함수화 해주려고하는데 이런 한두줄 있는것도 메소도화 시키는게 더 좋을까요?

 

아직 어떻게 코드를 세분화하고 나눠야할지 어렵네요 감사합니다

codeslave (3,940 포인트) 님이 2021년 1월 12일 질문
init()은 뷰를 초기화는 과련코드가 들어갈 거고, findViewById 도 초기화의 일부부분이로 여기 포함되어야 하겠죠. 하지만 init이 너무 길어지므로 init을 작은 부분으로 나누어서 사용하는 형태로 해보세요. 참고로, init()은 좀 애매한 이름이고, 코틀린에서는 init이라는 함수가 존재하기 때문에, 만약을 대비에 조금 더 명확한 이름을 주는 게 나을 듯 합니다.

private void initViews() {
    bindViews();
    initRecyclerView();
}

private void bindViews() {
    text1 = findViewBydI(R.id.text1);
}

메소드는 가능한 경우라면 한 메소드가 하나의 기능만 수행하도록 하는게 가장 좋습니다. 하지만 이게 항상 그렇게 되지만은 않지만, 그래도 최소한의 기능만 수행하도록 코드을 짜는 게 좋습니다. 그리고 네이밍이 아주 중요합니다.  메소드가 두가지 일을 한다면 이걸 메소드 이름에 반영해 주는게 코드를 읽기에 훨씬 좋습니다.  예를 들면,
public void fetchUsers();
public void fetchUsersAndUpdateList();

첫번째는 User리스트만 가져오는 것이고, 두번째는 User리스트를 가져온 다음 리스트를 업데이트 하는 거죠. 이렇게 메소드 이름만으로도 해당 메소드가 어떤 일을 하는지 명확하게 해줄 수 있다면 좋은 코드가 되는 거죠. 이렇게 하면 특별한 경우가 아니면 코드에 코멘트가 필요없어져요. 왜냐하면 코드 자체가 코멘트가 되는거니까요.
보통은 클래스들은 분리해서 별도의 파일로 만들고 같은 종류의 클래스라면 같은 패키지로 넣으세요. 같은 파일에 두개 이상의 클래스를 넣는 경우라면 inner class 같은 경우라면 상관없겠죠. 만약 BodyType이 WorkListSource와 아주 가까운 경우라고 생각하신다면, 같은 파일에 있거나 inner enum으로 만드시는 것도 일리가 있을 것 같습니다.
감사합니다. init을 만들되 좀더 세부적으로 나누어보겠습니다.
그런데 선생님께서 initRecycler와 bindView를 따로 만드셨는데 차이점이 뭘까요?
initView도 아니고 그냥 제가 Recycler 뷰를 사용해서 그렇게 사용하신건지요.
만약 그런거라면 저는 액티비티에서 다양한 뷰를 사용하기때문에 initView로
전체적인 뷰들을 초기화 해도 될까요?,
그리고 bindView라고하셨는데, 저는 findViewById가 init함수쪽에 올거라 생각했는데 bindView에 두신거게 궁금합니다 bind라는 단어는 제가 생각하기에
인스턴스의 초기화보다 초기화후 뭐 각 아이템에 데이터를 셋팅, 값을 셋팅한 다는 뜻으로 많이 알고 있었는데 조금 다른가요? 물론 인스턴스 생성도 초기화하는 것이고 안에 있는 멤버들의 데이터를 세팅한다는것에는 똑같긴하지만요..

findViewById를 init에 안두고 bind에 두었다면 init에는 어떤것들이 와야하나요?
new 같은 인스턴스의 생성이나 어댑터의 초기화 등이 와야하나요?
아 그리고 추가적으로 클래스를 패키지로 나뉘어서 정리할때,
액티비티는 액티비티 패키지를 따로 만들어 나누고 프래그먼트는 프래그먼트 패키지를 따로 만들어 나누어 나누는 것이 좋을까요
아니면 같은 기능 별로 나누는 것이 좋을까요?
예를들면 다이얼로그는 다이얼로그끼리 내비게이션은 내비게이션끼리 액티비티와 프래그먼트와 상관없이 이런 같은 기능이 여러개 있다면 같은 것들끼리 묶는게 나을지..
그냥 액티비티는 액티비티.. 프래그먼트는 프래그먼트 패키지에.. 이렇게 나누는게 좋을지 궁금합니다
아니면 기능과 관계없이
앞에서 말씀드렸다시피 하나의 함수는 가능하다면 한가지 기능한 하도록 설계하려고 했기 때문에 bindViews()와 initRecyclerView()로 나눈 겁니다. 이건 그냥 예시이므로 님의 상황에 맞게 함수이름은 좀 길어도 상관없으므로 되도록 명확하게 주시는게 좋습니다. 여기에는 정답이 없습니다. 그 때 상황을 보고 다른 사람이 내 코들 읽어도 최대한 흐름을 쉽게 파악할 수 있도록 만들기 위한 겁니다. 그래야 코드를 작성한 사람도 몇 개월 후에 수정사항이 생겨서 코드를 다시 만져야할 때 적응시간을 최소화할 수 있습니다. 다시 말씀드리지만, 님이 만드신 함수를 보고 아 이게 무슨 일을 하는 함수구나하는게 이해가 간다면 괜찮다고 말씀드릴 수 있습니다. 물론 함수 이름과 함수의 구현내용이 일치해야 겠죠.
패키지의 경우는 기능에 따라 나누는 사람들도 있고, 클래스의 종류의 따라 나누는 분들도 있습니다. 어떻게 보면 개인취향일 수도 있구요. 역시나 여기에서도 알아보기 쉽다면 충분합니다. 패키지 구조를 보고 직관적으로 "아, 이 패키지는 어떤 클래스들이 위치하겠구나"하고 파악할 수 있다면, 일단은 좋은 구조일 확률이 높습니다.
감사합니다..^^덕분이 좀더 세분화해서 나누었습니다

1개의 답변

0 추천

우선 앱의 리소스는 뷰레이어에 속합니다. 데이터 레이어에는 기본적으로 안드로이 플랫폼 관련 클래스가 들어가면 안됩니다. 님의 경우는 안드로이드 리소스를 가져다 쓰는 것이므로 이건 바로 데이터 레이어로 들어가면 곤란합니다. 주된 이유는 종속성 때문에 그렇습니다. 

제가 보기에 운동부위 데이터는 데이터베이스나 API 등에서 가져오는 데이터처럼, 데이터 소스의 성격이 강합니다. 그래서 데이터레이어에 속하는 것이 자연스러워 보이는데, 문제는 string resource로 되어 있다는 것이죠. 여기서 두가지 선택이 가능하다고 봅니다. string resource를 랩핑해서 데이터 레이어에서 가져다 쓰거나, 아니면, 이게 다국어 지원을 하는게 아니라면, 굳이 string resource에 들어갈 필요가 없다고 봅니다. 그냥 클래스 파일에 상수/변수로 정의하거나 아니면, 그냥 로컬 json파일로 저장한 후, 그걸 읽어 오셔도 됩니다. 저라면 두번째 옵션 중 JSON파일을 사용하는 옵션을 사용할 것 같습니다. 이렇게 하면, 추후에 이 데이터를 로컬 DB를 사용하거나 파이어 베이스에 옮기거나, 서버의 API 형태로 변환한다고 할 때 코드의 변경이 훨씬 적습니다. 무엇보다도 안드로이드 플랫폼 관련 클래스를 데이터 레이어에서 사용하지 않으면 유닛테스트가 훨씬 쉬워집니다.

운동 부위와 운동 아이템을 정의하는 JSON파일을 아래처럼 하나 만드세요. 이걸 Gson이나 Moshi를 써서 파싱하시면 일이 훨씬 간단해 집니다. Gson이나 Moshi사용하실 때 안드로이드 스튜디오에 플러그인을  설치하시면 클래스를 자동으로 생성해줍니다.

대표 플러그인: https://plugins.jetbrains.com/plugin/8634-robopojogenerator 

{
   "part": [
       {
          "id": 1,
          "name": "등",
          "items": [
              {
                 "id": 11,
                 "name": "아이템1"
                 
              },
              {
                 "id": 12,
                 "name": "아이템2"
                 
              }
              
          ]
       },
       {
          "id": 2,
          "name": "가슴",
          "items": [
              {
                 "id": 21,
                 "name": "아이템1"
                 
              },
              {
                 "id": 22,
                 "name": "아이템2"
                 
              }
              
          ]
       },
       {
          "id": 3,
          "name": "하체",
          "items": [
              {
                 "id": 31,
                 "name": "아이템1"
                 
              },
              {
                 "id": 32,
                 "name": "아이템2"
                 
              }
              
          ]
       }
    ]
}

 

이렇게 하시면 나중에 데이터베이스나 파이어베이스 같은 걸로 전환하기도 쉽고, 유닛테스트도 더 쉬워집니다.

spark (227,530 포인트) 님이 2021년 1월 13일 답변
제가 strings.xml에 운동종목들을 정의해놓고 가져와 쓰는데 이 strings가 뷰 레이어에 속하기때문에 이 운동부위는 분명 데이터적 성향이 강한것 같은데 그래서 이건 그닥 좋지 못한 방법이다 이 말씀이시죠? (그러니까 인터페이스로 정의한것돠 enum 이런것들이요).
저도 안그래도 나중에 DB를 사용해서 제가 만든 일지를 저장해야하기에 DB에 저장하거나
json같은걸 사용해서 API를 제가 만든후에 웹서버에 저장하고 가져오는 방법을 사용해야겠다고 생각했는데 오히려 그방법을 사용하는게 좋다고하시니 다행인것같습니다..일단 껍데기를 만드는중이라 일단 이렇게 했는데 추후 DB쪽으로 넘어가게되면 정리해서 다시해보겠습니다 감사합니다
...