[노개북 1기] TIL (2022.02.09)

yourjin·2022년 2월 26일
0

read.log

목록 보기
21/37
post-thumbnail

TIL (2022.02.09)

DAY 18

🔖 오늘 읽은 범위 : 10장, 클래스


😃 책에서 기억하고 싶은 내용을 써보세요.

  • 하지만 코드의 표현력과 그 코드로 이루어진 함수에 아무리 신경 쓸지라도 좀 더 차원 높은 단계(=클래스)까지 신경 쓰지 않으면 깨끗한 코드를 얻기는 어렵다.
  • 클래스 체계
    • 표준 자바 관례
      • 가장 먼저 변수 목록이 나온다.
        • 정적(static) 공개(public) 변수 → 정적 비공개(private) 변수 → 비공개 인스턴스 변수 → 공개 변수
        • 공개 변수가 필요한 경우는 거의 없다.
      • 변수 목록 다음에는 공개 함수가 나온다.
      • 비공개 함수는 자신을 호출하는 공개 함수 직후에 넣는다. 즉, 추상화 단계에서 순차적으로 내려간다.
    • 캡슐화
      • 변수와 유틸리티 함수는 가능한 공개하지 않는 편이 낫지만 반드시 숨겨야 한다는 법칙도 없다.
      • 같은 패키지 안에서 테스트 코드가 함수를 호출하거나 변수를 사용해야 한다면 그 함수나 변수를 protected로 선언하거나 패키지 전체로 공개한다.
      • 하지만 그 전에 비공개 상태를 유지할 온갖 방법을 강구한다. 캡슐화를 풀어주는 결정은 언제나 최후의 수단이다.
  • 클래스는 작아야 한다!
    • 클래스를 만들 때 첫 번째 규칙은 크기다. 클래스는 작아야 한다. 두 번째 규칙도 크기다. 더 작아야 한다.
    • 그렇다면 가장 먼저 떠오르는 의문은, 함수와 마찬가지로, "얼마나 작아
      야 하는가?” 겠다.
    • 함수는 물리적인 행 수로 크기를 측정했다. 클래스는 다른 척도를 사용한다. 클래스가 맡은 책임을 센다.
      • 충분히 작을까?

        public class SuperDashboard extends JFrame implements MaetaDataUser {
        		public Component getLastFocusedComponent()
        		public void setLastFocusedComponent()
        		public int getMajorVersionNumber()
        		public int getMinorVersionNumber()
        		public int getBuildNumber()
        }
        • SuperDashboard는 메서드 수가 작음에도 불구하고 책임이 너무 많다.
        • 클래스 이름은 해당 클래스 책임을 기술해야 한다.
          • 간결한 이름이 떠오르지 않는다면 필경 클래스 크기가 너무 커서 그렇다. 클래스 이름이 모호하다면 필경 클래스 책임이 너무 많아서다.
          • ex. Processor, Manager, Super 등의 모호한 단어
        • 또한 클래스 설명은 만일("if"), 그리고("and"), -(하)며("or"), 하지만('but")을 사용하지 않고서 25단어 내외로 가능해야 한다.
          • "SuperDashboard는 마지막으로 포커스를 얻었던 컴포넌트에 접근하는 방법을 제공하며, 버전과 빌드 번호를 추적하는 메커니즘을 제공한다.”
            → 책임이 너무 많다는 증거!
    • 단일 책임 원칙
      • 단일 책임 원칙(Single Responsibility Principle, SRP)은 클래스나 모듈을 변경할 이유가 하나, 단 하나뿐이어야 한다는 원칙이다.
      • SRP는 책임’이라는 개념을 정의하며 적절한 클래스 크기를 제시한다. 클래스는 책임, 즉 변경할 이유가 하나여야 한다는 의미다.
      • 앞의 SuperDashboard 를 변경할 이유?
        1. SuperDashboard는 소프트웨어 버전 정보를 추적한다. 그런데 버전 소프트웨어를 출시할 때마다 달라진다.
        2. SuperDashboard 는 자바 스윙 컴포넌트를 관리한다. 즉, 스윙 코드를 변경할 때마다 버전 번호가 달라진다.
      • 단일 책임 클래스
        public class Version {
        	public int getMajorVersionNumber( )
        	public int getMinorVersionNumber()
        	public int getBuildNumber()
        }
        • SuperDashboard에서 버전 정보를 다루는 메서드 세 개를 따로 빼내 Version 라는 독자적인 클래스를 만든다.
      • 하지만 이상하게도 SRP는 클래스 설계자가 가장 무시하는 규칙 중 하나다. (...) 왜일까?
        • 소프트웨어를 돌아가게 만드는 활동과 소프트웨어를 깨끗하게 만드는 활동은 완전히 별개다. 우리들 대다수는 두뇌 용량에 한계가 있어 ‘깨끗하고 체계적인 소프트웨어’보다 ‘돌아가는 소프트웨어’에 초점을 맞춘다. → 관심사를 분리하는 작업
        • 문제는 우리들 대다수가 프로그램이 돌아가면 일이 끝났다고 여기는 데 있다. ‘깨끗하고 체계적인 소프트웨어’라는 다음 관심사로 전환하지 않는다.
        • 게다가 많은 개발자는 자잘한 단일 책임 클래스가 많아지면 큰 그림을 이해하기 어려워진다고 우려한다. (...) 하지만 어떤 시스템이든 익힐 내용은 그 양이 비슷하다.
      • 규모가 어느 수준에 이르는 시스템은 논리가 많고도 복잡하다. 이런 복잡성을 다루려면 체계적인 정리가 필수다.
      • 큰 클래스 몇 개가 아니라 작은 클래스 여럿으로 이뤄진 시스템이 더 바람직하다.
    • 응집도(Cohesion)
      • 클래스는 인스턴스 변수 수가 작아야 한다. 각 클래스 메서드는 클래스 인스턴스 변수를 하나 이상 사용 해야 한다. 일반적으로 메서드가 변수를 더 많이 사용할수록 메서드와 클래스는 응집도가 더 높다. 모든 인스턴스 변수를 메서드마다 사용하는 클래스는 응집도가 가장 높다.
      • 그렇지만 우리는 응집도가 높은 클래스를 선호한다. 응집도가 높다는 말은 클래스에 속한 메서드와 변수가 서로 의존하며 논리적인 단위로 묶인다는 의미기 때문이다.
      • Stack.java 응집도가 놓은 클래스
        • 인스턴스 변수가 거의 모든 메서드에서 사용된다.

          public class Stack {
          		private int topOfStack = 0;
          		List<Integer> elements = new Linkedlist<Integer>();
          		
          		public int size() {
          				return topOfStack;
          		}
          
          		public void push(int element) {
          				topOfStack++;
          				elements.add(element);
          		}
          
          		public int pop() throws PoppedWhenEmpty {
          			if (topOfStack = 0){
          				throw new PoppedWhenEmpty();
          			}
          			int element = elements.get(-topOfStack);
          			elements.remove(topOfStack);
          			return element;
          }
      • 함수를 작게, 매개 변수 목록을 짧게’라는 전략을 따르다 보면 때때로 몇몇 메서드만이 사용하는 인스턴스 변수가 아주 많아진다. 이는 십중팔구 새로운 클래스로 쪼개야 한다는 신호다.

🤔 오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요

  • 처음 클래스를 사용할 때, 캡슐화를 하나도 지키지 못하며 코딩했던 게 기억이 났다. 클래스로 분할을 하래서 하긴 했는데, 서로 연결 짓지 못해 전부다 public으로 두었다. 그때는 캡슐화, 상속, 다형성 등 객체 지향의 특징을 이해하지도 못한 채, 기한 내 ‘동작하는’ 소프트웨어를 만들기 바빴기 때문이다. 지금 그 코드를 보면 내가 봐도 이해가 잘 되지 않는 부분들이 많다. 왜 클래스 설계와 추상화를 잘 해야하는 지, 다시 한번 느낄 수 있는 하루였다.

🔎 궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요.

  • Java의 변수
    • 인스턴스 변수
      • 인스턴스 변수는 클래스 영역 내에 선언이 되고, 인스턴스를 생성할 때 만들어집니다.
      • 인스턴스 변수의 값을 읽어 오거나 저장하기 위해서는 먼저 인스턴스를 생성해야 합니다.
      • 인스턴스마다 고유한 상태를 유지해야 하는 속성의 경우, 인스턴스 변수로 선언합니다.
    • 클래스 변수
      • 클래스 변수를 선언하는 방법은 인스턴스 변수 앞에 static을 붙이기만 하면 됩니다.
      • 클래스가 로딩될 때(클래스가 메모리에 올라갈 때) 생성되어 프로그램이 종료될 때 까지 유지된다.
      • 클래스 변수는 인스턴스를 생성하지 않고도 언제라도 바로 사용할 수 있다.
      • 한 클래스의 모든 인스턴스들이 공통적인 값을 유지해야 하는 속성의 경우, 클래스 변수로 선언해야 합니다.
    • 지역 변수
      • 메소드 내에 선언되어 메소드 내에서만 사용 가능하며, 메소드가 종료되면 소멸되어 사용할 수 없습니다
    • 참고 링크: [Java] 클래스 / 인스턴스 / 지역변수 쉽게 이해하기
  • 응집도

소감 3줄 요약

  • 캡슐화를 풀어주는 결정은 언제나 최후의 수단이다.
  • 큰 클래스 몇 개가 아니라 작은 클래스 여럿으로 이뤄진 시스템이 더 바람직하다.
  • 클래스 이름은 해당 클래스 책임을 기술해야 하며, 응집도가 높게 유지되어야 한다.
profile
make it mine, make it yours

0개의 댓글