MDD
38
2020-03-19 23:57:10
5
279

c# 리팩토링 이란건 대체 어떻게 해야할까요?


여러번 리펙토링을 하면서 코드를 뜯어고치고 등등을 해봤지만 항상 하면서 느끼는 것은

고치다가 그것을 보완하기 위해 만든 변수같은것들이 넘쳐나게 되고 그리고

넘쳐나는걸 다시 고치고 그렇게 끝없이 고치기만 하게 됩니다.


구글링을 해봐도 확장성을 고려해서 설계해라. 알고리즘화 해라. 등등 너무 추상적이랄까 대강 설명되어있어서 제대로 된 이해를 하지 못하고 있습니다.


제가 무엇을 놓치고 거나 모르고 있는걸지 감도잡히지 않아서 질문을 드리게 되었습니다.


제가 만든 코드의 리팩토링한 전후를 올려보았는데

참고가 될 수 있으면 좋겠습니다.


변경전 

using System;
using System.Collections.Generic;
public class BackTracking3x3
{
  public static void Main()
  {    
      int[] answer = new int[10]; //각 빈칸에 해당 하는 데이터를 저장하는공간
      int[] rowAnswer = new int[]{11,12,22};
      int[] verAnswer = new int[]{14,15,16};
     
      int answerCount = 0;
      int index = 1;
​
      bool[] isUsed = new bool[10]; //숫자의 중복 사용 방지를 위한 배열
      bool isPrev = false;
      bool isNext = false;
​
      while(index <= 9 )
      {
          if(index == 0) {Console.WriteLine("답을 모두 찾았습니다."); break;}
         
          //이동 시작
          if(index == 3) //index 3에 대한 이동
          {
              answer[index] = rowAnswer[0] - (answer[1] + answer[2]);
​
              if(9< answer[index] || answer[index] < 1) {isPrev = true; answer[index] = 0;}
              else if(isUsed[ answer[index] ] == true)  {isPrev = true; answer[index] = 0;}
              else if(!isPrev)                          {isNext = true; isUsed[ answer[index] ] = true;} //등록
          }
          else if(index == 6)
          {
              answer[index] = rowAnswer[1] - (answer[4] + answer[5]);  
​
              if(9< answer[index] || answer[index] < 1) {isPrev = true; answer[index] = 0;}
              else if(isUsed[ answer[index] ] == true)  {isPrev = true; answer[index] = 0;}
              else if(!isPrev)                          {isNext = true; isUsed[ answer[index] ] = true;} //등록
          }
          else if(index == 7)
          {
              answer[index] = verAnswer[0] - (answer[1] + answer[4]);  
​
              if(9< answer[index] || answer[index] < 1) {isPrev = true; answer[index] = 0;}
              else if(isUsed[ answer[index] ] == true)  {isPrev = true; answer[index] = 0;}
              else if(!isPrev)                          {isNext = true; isUsed[ answer[index] ] = true;} //등록
          }
          else if(index == 8)
          {
              answer[index] = rowAnswer[0] - (answer[2] + answer[5]);  
​
              if(9< answer[index] || answer[index] < 1) {isPrev = true; answer[index] = 0;}
              else if(isUsed[ answer[index] ] == true)  {isPrev = true; answer[index] = 0;}
              else if(!isPrev)                          {isNext = true; isUsed[ answer[index] ] = true;} //등록
          }
          else if(index == 9)
          {
              answer[index] = rowAnswer[2] - (answer[7] + answer[8]);
              answer[0]     = verAnswer[2] - (answer[3] + answer[6]);    
             
              if(9< answer[index] || answer[index] < 1) {isPrev = true; answer[index] = 0;}
              else if(isUsed[ answer[index] ] == true)  {isPrev = true; answer[index] = 0;}
             
              if(!isPrev && answer[9] == answer[0])  //정답을 찾으면
              {
                  answerCount++;
​
                  for(int count = 0; count < 3;count++)
                  {
                      Console.WriteLine($"answer : {answer[count*3+1]} {answer[count*3+2]} {answer[count*3+3]}");
                  }
                 
                  isPrev = true; //돌아가서 다음수를 검색하라는 뜻
              }
             
          }
          else if(!isPrev && !isNext) // 인덱스(3,6,7,8,9 제외) 에 대한 이동
          {
              int prevValue = answer[index];
              int nextValue = -1;
​
              for(int i = prevValue+1 ; i<10 ; i++)
              {
                  if(isUsed[i] == false)
                  {
                      nextValue = i;
                      break;
                  }
              }
             
              if(nextValue != -1) //다음으로 진행할 수가 존재하면
              {
                  Console.WriteLine($"Plus {index} : ({answer[index]} -> {nextValue})");
                  isUsed[prevValue] = false;
                 
                  answer[index] =  nextValue;              
                  isUsed[nextValue]= true;
                 
                  isNext = true;
              }
              else isPrev = true;
          }  //이동 종료
         
          if(isNext) //다음으로 넘어가야할 때
          {
              isNext = false;
              Console.WriteLine($"Next {index}");
              index += 1;
          }
         
          if(isPrev) //이전으로 초기화 하고 돌아가야할 때
          {
              //isPrev = false; //끄는방법은 안됨. 다른 변수를 선언해야하나?
              Console.WriteLine($"Prev {index}");
             
              isUsed[ answer[index] ] = false;  
              answer[index] = 0;
             
              index--;        
          }
         
         
         
      } //while종료
     
      Console.WriteLine($"answerCount = {answerCount}");
      Console.WriteLine($"loopCount = {loopCount}");
  }// Main  메소드 종료
}​

변경후


using System;
using System.Collections.Generic;
public class BackTracking3x3
{
   enum IndexState {Prev, Stop, Next}; //stop 은 기본값
   
     public static void Main()
     {    
         IndexState state = IndexState.Stop;
         
         int[] answer = new int[10]; //각 빈칸에 해당 하는 데이터를 저장하는공간
         int[] rowAnswer = new int[]{22,12,11};
         int[] verAnswer = new int[]{16,15,14};  

         int afterNum = 0;
         int answerCount = 0;
         int index = 1;
        
         bool[] isUsed = new bool[10]; //숫자의 중복 사용 방지를 위한 배열
       
         while(index <= 9)
         {
             if(index == 0) {Console.WriteLine("답을 모두 찾았습니다."); break;}

             if(state == IndexState.Next) //다음으로 넘어가야할 때
             {
                 isUsed[ afterNum ] = false;
                 afterNum = 0;
                 isUsed[ answer[index] ] = true;
                 index += 1;
             }

             if(state == IndexState.Prev) //이전으로 돌아갈때
             {
                 isUsed[ afterNum ] = false;
                 
                 answer[index] = 0;
                 afterNum = answer[index-1];
             
                 index--;        
             }

             // 인덱스(3,6,7,8,9 제외) 에 대한 이동
             if(index == 1 || index == 2 || index == 4 || index == 5)
             {
                 int prevValue = answer[index];
                 int nextValue = -1;

                 for(int i = prevValue+1 ; i<10 ; i++) //애 어떻게 깔끔하게 줄일수 없나?
                 {
                     if(isUsed[i] == false)
                     {
                         nextValue = i;
                         break;
                     }
                 }

                 if(nextValue != -1) //다음으로 진행할 수가 존재하면
                 {
                      answer[index] =  nextValue;              
                      state = IndexState.Next;
                 }
                 else state = IndexState.Prev;
             }  
             else if(state != IndexState.Prev) //점프 이동 시작
             {
                 switch(index)
                 {
                     case 3:
                         answer[index] = rowAnswer[0] - (answer[1] + answer[2]);
                         break;
                     case 6:
                         answer[index] = rowAnswer[1] - (answer[4] + answer[5]);
                         break;
                     case 7:
                         answer[index] = verAnswer[0] - (answer[1] + answer[4]);
                         break;
                     case 8:
                         answer[index] = verAnswer[1] - (answer[2] + answer[5]);
                         break;
                     case 9:
                         answer[index] = rowAnswer[2] - (answer[7] + answer[8]);
                         answer[0]     = verAnswer[2] - (answer[3] + answer[6]);
                         break;
                 }
                 
                 if(9< answer[index] || answer[index] < 1) {state = IndexState.Prev;} //범위를 벗어날 경우
                 else if(isUsed[ answer[index] ] == true)  {state = IndexState.Prev;} //이미 사용중일 경우
                 else                                      {state = IndexState.Next;} //통과
                           
                 if(index == 9 && state != IndexState.Prev && answer[9] == answer[0] ) //정답을 찾을 경우
                 {
                     answerCount++;               
                     state = IndexState.Prev; //돌아가서 다음수를 검색하라는 뜻  
                 }
             }//강제 이동 종료
             
         } //while종료
         
         Console.WriteLine($"answerCount = {answerCount}");
         Console.WriteLine($"loopCount = {loopCount}");
   }// Main  메소드 종료
}


0
0
  • 답변 5

  • fender
    17k
    2020-03-20 01:14:29

    어떤 것이 나쁜 코드인지 알아도 좋은 코드는 어떤 것인지 모른다면 리팩터링을 하기 어렵습니다.

    제시하신 코드는 전형적으로 코드를 구문 단위로 이해하는 단계에 머물러 있을 때 보이는 습관을 여럿 포함하고 있습니다.

    즉, 조건문, 제어문, 배열 등 기본적인 문법을 어느 정도 능숙하게 쓸 수 있지만 클래스나 인터페이스 단위의 일반화에 익숙하지 않은 경우 흔히 저런 코드를 작성하게 됩니다.

    제 생각에는 객체지향이나 디자인 패턴에 대한 연습을 충분히 하면서 그런 문제를 극복해보시는 것이 바람직한 상황인 것 같습니다.

    0
  • mirheeoj
    10k
    2020-03-20 05:55:32

    리팩토링은 필요할 때 하는 게 답.

    리팩토링을 위한 리팩토링을 하게 되면 없던 문제가 생길 수 있고, 고객이 원하는 새 기능을 개발할 시간이 줄어들게 됩니다. 

    리팩토링이 필요해진 상황(속도, 메모리 사용량, 인터페이스 개선 등등)에선 목적이 분명해지므로 그에 따라 리팩토링을 하면 됩니다. 


    0
  • tteakuk
    264
    2020-03-20 09:29:38

    리펙토링은 클레스와 클레스 관계 정도이지

    한개 함수안에 로직은 대상이 아니죠.

    0
  • MDD
    38
    2020-03-20 23:35:55

    @fender

    정확하십니다. 현재 인터페이스랑 클래스는 사용은 할수있지만 어떻게 적용을 해야할지 모르는 상황입니다.


    그래서 말씀하신것중에 궁금한것이 "구문 단위로 이해하는 단계"라고 하셨는데

    혹시 그 다음단계라고 할만한것을 알고 계신다면 알려주시겠습니까?


    현재 그러면 디자인패턴이랑 객체지향을 공부해야지! 라고는 생각하나 너무 막연하다고 생각되어

    그 다음단계를 말씀해주신다면 확실한 목표를 갖고 나아갈수 있을것 같아서 질문드립니다.

    0
  • fender
    17k
    2020-03-21 08:19:52

    MDD // 사용하시는 언어가 C#이라면 역시 객체지향으로 설계하는 연습과 디자인 패턴을 병행하시는 것이 가장 빠른 길이라고 밖에 말씀을 드리기 어렵습니다.

    모든 프로그래밍은 보다 복잡한 시스템을 쉽게 만들기 위한 일반화와 추상화의 과정입니다.

    지금 단계에선 아마도 설계란 것은 어떤 데이터를 어느 배열에 담고, 조건문으로 어떻게 분기하고 그런 구문 수준에 국한되어 있을텐데, 그 걸 탈피해서 생각하시는 개념을 인터페이스나 클래스로 표현할 수 있는 연습을 해야 합니다.

    아마 인터넷이나 책으로 객체지향에 대한 기초를 먼저 습득하고 간단한 게임 같은 예제를 꾸준히 만들어 보시는 것이 가장 빠른 길이 아닐까 싶습니다. 특히 디자인 패턴 등은 이를 실제 적용한 예를 찾아보고 본인이 그런 문제를 접했으면 어떻게 풀었을까를 생각해서 비교해보면 도움이 됩니다.

    제 답변이 도움이 되셨으면 좋겠습니다.

    0
  • 로그인을 하시면 답변을 등록할 수 있습니다.