Java 프로그래밍 질문좀 드릴게요.

조회수 740회

초보 프로그래머입니다!!. 프로그래머스의 자바입문을 수강 후, 어떻게하면 프로그래밍 실력을 늘릴까 하다가 인터넷을 찾아보니 되도록 코드를 많이 짜보라고 하더라구요. 그래서 마침 눈에 띄는 중1수학책에 보니 '소인수분해를 이용한 최대공약수 구하기'가 보여서 그걸 주제로 코드를 짜보았습니다.

프로그램은 원하는 결과값은 나오는데요. 제가 질문드리고 싶은건 첫째 객체지향프로그램은 클래스들의 집합이라고 했는데, 제가 짠 프로그램은 클래스가 1개입니다. 클래스를 나누는 기준을 어떻게 잡으면 좋을까요?;; 제 프로그램이 작아서 그런진 몰라도 이게 나눠도 되나? 이런 생각만 들더라구요.

둘째 메소드일지 클래스일지 결정입니다. 첫번째 질문의 연잔선상일 수 있는데요. 어떤 메소드를 만들때 이걸 클래스로 해야할지 메소드로만 해야할지 결정하기가 어렵습니다. 제 코드 같은 경우 소인수분해를 이용한 최대공약수 구하기 프로그램인데 소인수분해 하는 부분, 최대공약수 구하는 부분, 지수를 정규화하는 부분 3가지로 프로그램을 나눌수 있고, 이들의 비중은 4:4:2 정도로 생각합니다.

이 때 소인수분해하는 메소드를 만든다고 했을때 저는 소인수분해하는 부분이 최대공약수를 구하기 위한 행동이라고 생각하여 메소드라고 넣어놨습니다만, 소인수 분해하는 부분이 또 다른 클래스로 가도 되는지 궁금하고, 어떤 메소드를 만들때 그냥 메소드로만 할지 클래스로 할지 결정하는 기준 (개인적인 기준도 괜찮습니다) 있으신지 궁금합니다.

셋째 public과 private의 사용기준을 잘 모르겠습니다. 이 부분을 위해서 제가 들은 강의를 재 반복하였으나 도무지 모르겠습니다. 실제 코드를 짜다보니 어떨대 private, public, protected를 넣을지 감이 안잡힙니다. 예를들어 클래스가 몇개이상일때 이걸 써라, 이건 클래스 개수와 상관없이 이럴 경우 써봐라 등등 팁좀 알려주시면 감사하겠습니다!!.

사진은 제가 프로그램을 짤 때 그린 약도 및 코드 입니다. 나름 해답을 찾으려 구글링 및 혼자 생각을 해보았지만, 머리속만 더 어지러워져 질문을 올립니다. 프로그래밍 초보라 질문이 허접할 수 있겠지만, 많은 지식공유 및 조언좀 부탁드립니다.!!

이미지

이미지

아래부터는 코드 입니다.


package mathProgramming;
import java.util.ArrayList;

public class TheGreatestCommonDivisor {

    public int number ; //소인수 분해 할 첫째  정수

    public ArrayList<Integer> numS = new ArrayList<>(); // 정수의 소인수 값
    public ArrayList<Integer> numE = new ArrayList<>(); // 정수의 소인수의 지수 값  

    public void FractionalDecomposition (int number) { //입력 받은 두수의 소인수 분해한 값을 구하는 함수

        this.number = number;

        int result = 0; // 재귀함수 호출을 위해 사용하는 변수
        int count = 0; // 지수값 변수

        for(int i = 2; i <= number; i++) { // 1은 소인수가 아니므로 i를 2부터 number까지 수로 지정한다.
            if(number / i == 1 && number % i == 0  ) { // 자기 자신으로 나눴을 때 값이 1이고, 나머지가 0이면 배열에 추가한다. ex) 7/7 = 1,  7%7 = 0 
                numS.add(number); // 소인수 값을 어레이리스트에 추가
                count ++; // 지수값 저장을 위해 1증가 시킨다.
                numE.add(count); //numS의 지수값을 저장한다.
                break;
            }

            else if(number % i != 0) { //0으로 나눠 떨어지지 않으면  다음으로 넘어 간다.
                continue;
            }

            else // i가 2~ number보다 작은 값으로 나눠서 나머지가 0 일때 실행
                numS.add(i); // 소인수 값을 어레이리스트에 추가
                count ++; // 지수값 저장을 위해 1 증가 시킨다.
                numE.add(count); //numS의 지수값을 저장한다.
                result = number / i; // 다음 재귀함수 호출을 위한 매개변수 값을 계산한다.              
                FractionalDecomposition(result); 
                break; // 재귀를 호출한 후, 값이 필요 없으므로 종료 시킨다.

        }

   }

    public void Normalization() { //지수를 조정하는 메소드 ex) 2 * 2 * 5  를  2 ^ 2 x 5 ^ 1으로 변경 해준다.

        for(int i = 0; i < numS.size()-1; i++) {    // i = 0 부터 어레이 리스트 사이즈 -1 까지 반복      
            if(numS.get(i)!=numS.get(i+1)) // 값이 다르면 뛰어 넘는다
                continue;

            else if(numS.get(i) == numS.get(i+1)) { // i번째 요소와 i+1 요소의 값이 같으면 ex) 값 : 2, 2, 5 / 지수 :  1, 1, 1
                numS.remove(i+1); // i + 1번째 값을 지우고 ex) 값 : 2, 5 / 지수 : 1, 1, 1
                numE.remove(i+1); // i + 1번째 값의 지수 값을 지운다 ex) 값 : 2, 5 / 지수 : 1, 1
                numE.set(i, numE.get(i)+1); // 그리고 i 번째 값의 지수 값을 증가 시킨다. ex) 값 : 2, 5 / 지수 : 2,1
                i--; // 그리고 값이 갱신되 었으므로 다시 i번째 값 부터 지수 조정을 위해 i 값을 감소시킨다.

            }

        }

    }

    public void Copy(ArrayList<Integer> num, ArrayList<Integer> num2) { //계산한 소인수의 값들을 복사, 초기화 메소드

        for(int i = 0; i < numS.size(); i++) { // 값을 복사한다.
            num.add(i, numS.get(i));
            num2.add(i, numE.get(i));
        }

        for(int i = 0; i < numS.size(); i++) { // 두번째 정수 값의 연산을 위해 값을 초기화 한다.
            numS.remove(i);
            numE.remove(i);
            i--; // remove 사용시 인덱스가 자동 조정되므로 i 값을 감소시킨다.
        }

    }

    public void CompareCommon(ArrayList<Integer> num1, ArrayList<Integer> num1E, ArrayList<Integer> num2, ArrayList<Integer> num2E) { //최대공약수를 구하는 메소드.
        //매개변수는 첫번째 소인수 값, 첫번째 소인수값의 지수, 두번째 소인수 값, 두번째 소인수 값의 지수 순이다.
        int result = 1; //최대공약수 값을 저장할 변수

            for(int i = 0; i < num1.size(); i++) { // 2개의 어레이리스트를 비교하기 위한 2중 for문 
                for(int j = 0; j < num2.size(); j++) { // 1개의 어레이리스트를 기준으로 나머지 1개의 어레이리스트를 계속적으로 비교하기 위한 for문

                    if(num1.get(i) == num2.get(j)) {  //2개의 소인수 값이 같은  경우
                       if(num1E.get(i) == num2E.get(j)) { //2개의 소인수의 지수값이 같은 경우
                           result = result * num1.get(i) * num1E.get(i); // 그대로 곱해 준다. 
                       }

                       else //소인수 값은 같은데 지수 값이 다른 경우

                           if(num1E.get(i)>num2E.get(j)) //num1의 지수값이 큰 경우, 작은지수인 num2의 지수값을 이용하여 곱해준다.
                               result = result * num1.get(i) * num2E.get(j);
                           else
                               result = result * num1.get(i) * num1E.get(i); //num2의 지수값이 큰경우, 작은 지수인 num1의 지수값을 이용하여 곱해준다.
                    }       
                }
            }        
            if(result != 1)
                System.out.println("두수의 최대 공약수는 : " + result);
            else
                System.out.println(" 서로 공통된 최대 공약수가 없습니다. ");
    }







package mathProgramming;
import java.util.ArrayList;
import java.util.Scanner;

public class TheGreatestCommonDivisorExam {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner scan = new Scanner(System.in);
        int num1 = scan.nextInt();
        int num2 = scan.nextInt();

        ArrayList<Integer> numR = new ArrayList<>(); //첫번째로 입력한 값의 소인수를 저장
        ArrayList<Integer> numRE = new ArrayList<>(); //첫번째로 입력한 값의 소인수의 지수를 저장

        ArrayList<Integer> numR2 = new ArrayList<>(); //두번째로 입력한 값의 소인수를 저장
        ArrayList<Integer> numRE2 = new ArrayList<>(); //두번째로 입력한 값의 소인수의 지수를 저장

        TheGreatestCommonDivisor ex = new TheGreatestCommonDivisor();
        ex.FractionalDecomposition(num1); //
        ex.Normalization(); 
        ex.Copy(numR, numRE);

        ex.FractionalDecomposition(num2);
        ex.Normalization(); 
        ex.Copy(numR2, numRE2);

        ex.CompareCommon(numR, numRE, numR2, numRE2);

    }

}
  • (•́ ✖ •̀)
    알 수 없는 사용자

1 답변

  • OOP라는 것이 문법일수도 있지만 아키텍쳐의 영역이라 딱 떨어지는 것이 아닙니다. 즉 상황에 따라 달라질 수 있습니다. 쉽게 질문자가 작성한 정도의 수준이라면 클래스 1개로 작성해도 됩니다만 만약 다양한 수학적 서비스를 고려한다면 즉 소인수분해를 이용한 최대공약수 구하기 외에 여러 다양한 수학적 기능을 구현해야 한다면...설계 즉 아키텍쳐 관점에서 생각해봐야 하는 겁니다.

    OOP 라는 것의 좋은 샘플은 GOF 디자인 패턴도 있고 자바의 다양한 라이브러리들도 좋은 참고가 되며 다양한 서적들(구체적으로 마틴파울러의 서적들)도 있습니다.

    추상적으로 들릴텐데...본래 그러한 영역입니다. 이럴땐 이렇게 해라 하는 딱 떨어지는 무엇이 아닙니다. 저도 과거에 그랬지만 디자인패턴에 너무 심취한 나머지 간단한 구조임에도 어떡하던지 디자인패턴을 적용해서 과도하게 클래스 설계를 하던때가 기억이 납니다.

    추천하는 학습법은 일단 자바의 기본 라이브러리들을 많이 사용해보되 큰 관점에서 생각해보라는 것 입니다. 리팩토링과 디자인패턴 서적을 참고하여 자바의 io 관련 라이브러리의 decorator 패턴이나 servlet api 에서의 template mathod 패턴등등 이런것들을 발견하는 재미를 느껴봤으면 합니다.

    또한 질문자는 코드 리뷰를 스스로 하는 좋은 자세를 갖추고 있으니 관심을 갖고 천천히 경험 및 학습하시면 됩니다.

    • 아직 초보적인 수준으로 답변을 완벽히 이해하진 못했지만, 내 프로그램이 저 1개로 끝날 것이면 클래스 1개로도 괜찮지만, 최대공약수를 구하는 것 외에 더 활용하고 싶으면 클래스를 더 많이 만들어도 된다 라고 생각하면 되겠지요? 말씀해주신대로 좀 더 크게 생각해보고, 다양한 라이브러리를 사용해볼 수 있도록 노력해보겠습니다. 답변 감사합니다! 알 수 없는 사용자 2019.5.22 13:01

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)