• 오픈소스 라이브러리를 사용해야 할 경우
  1. 외부코드 사용하기

    • 외부 코드를 사용할경우 반환하는 Object를 올바른 유형으로 반환할 책임은 사용하는 클라이언트에 있다.
    • 랩퍼 클래스로 한번 숨기면 그 안에서 객체 유형을 관리하기 때문에 나머지 프로그램에는 영향을 미치지 않는다.
    • 그리고 이 랩퍼 클래스는 사용자에게 필요한 인터페이스만 제공하므로 이해하기 쉽고
    • 오용하기는 어렵다.
    • 또한 이 랩퍼 클래스는 설계규칙과 비즈니스 규칙을 따르도록 강제할수 있다.
  2. 경계 살피고 익히기

    • 간단한 테스트 케이스를 작성해 외부 코드를 익히는 방법
    • 이를 학습 테스트 라고 한다.
    • 학습테스트는 프로그램에서 사용하려는 방식대로 외부 API를 호출한다.
    • 학습테스트는 API를 사용하려는 목적에 초점을 맞춘다.
  3. log4j 익히기

    • 2번의 방식대로 log4j로 로그 찍는법을 익혀보자.
  4. 학습 테스트는 꽁짜 이상이다.

    • 어차피 api를 배워야 하기 때문에 학습테스트에 드는 비용은 없다.
    • 나중에 새버전나왓을때 호환이 되는지 확인하기도 좋다.
  5. 아직 존재하지 않는 코드를 사용하기

  • 인터페이스를 만들어 어댑터 패턴을 이용해 api 사용을 캡슐화해 api가 바뀔 때 수정할 코드를 한곳으로 모았다.

  • 이와 같은 설계는 테스트도 아주 편하다.

  • ( 뭔소린지 모르겠다 다시 읽어봐야 할듯 )

  1. 깨끗한 경계
  • 경계에 위치하는 코드는 깔끔히 분리한다.
  • 외부 패키지를 호출하는 코드를 가능한 줄여 경계를 관리하자
  • 아니면 새로운 랩퍼 클래스를 만들던지 adapter 패턴을 사용해
  • 외부 패키지가 제공하는 인터페이스를 우리가 원하는 방식으로 바꾼다.

'book > 클린코드' 카테고리의 다른 글

10장 - 클래스  (0) 2020.12.22
9장 - 단위 테스트  (0) 2020.12.02
7장 - 오류처리  (0) 2020.11.27
6장 - 객체와 자료구조  (0) 2020.11.25
5장 - 형식 맞추기  (0) 2020.11.23

목표

  • 자바가 제공하는 다양한 연산자를 학습하세요

학습할것

  • 산술 연산자
  • 비트 연산자
  • 관계 연산자
  • 논리 연산자
  • instanceof
  • assignment(=) operator
  • 화살표(->) 연산자
  • 3항 연산자
  • 연산자 우선 순위
  • (optional) Java 13. switch 연산자

산술 연산자

  • 산술연산자는 사칙연산자 ( + , - , * , / ) 4개와 나머지 연산자 ( % ) 로 이루어져 있다.

  • 사칙 연산자

    • 피 연산자가 정수 일 경우 0 으로 나눌수 없다.

    • 피 연산자가 같을 경우 결과는 피연산자와 같고

    • 피 연산자가 다를 경우 ( 정수 + 실수 ) 조합일 때 결과는 실수가 된다.

    • 피 연산자가 다를 경우에는 좀더 범위가 넓은쪽을 결과의 타입으로 쓴다.

    • 연산자 결과의 최소 타입은 int형이다.

      byte a = 1; byte b = 1; byte c = a+b; // 에러발생 provided는 int형 인데 byte에 담으려 했기 때문 byte c = (byte)(a+b); // 명시적 형변환할 경우 에러안남
      • byte+byte로 더해서 byte에 담으려 하면 에러가 난다.
        • 결과는 int로 나오는데 int ( 4byte)보다 더작은 byte에 담으려 했기 때문
        • 이때는 명시적으로 형변환을 시켜줘야 한다.
        • 하지만 큰 타입에서 작은 타입으로 변환해서 데이터를 넣을 경우
        • 값이 작은 타입의 데이터 범위를 넘을 경우 데이터 손실이 일어난다.
    int aa = 1000000; int bb = 1000000; long cc = aa*bb; // result -727379968
    • 같은 타입 피연산자의 연산결과 합이 타입의 허용 값을 넘어서 결과가 나온다면
    • 더 높은값을 담을수 있는 타입에 저장할 때 이 타입의 형태로 저장되는게 아닌 피연산자 타입의 연산결과의 합이 담긴다.
    • 그리고 연산 중 오버플로우가 일어난다면
    • 상위 타입에 저장한다고 해도 이미 오버플로우가 일어나서 오버플로우가 일어나기 전까지의 값만 저장가능하다.
  • 문자열 연산

char a = 'a'; char b = 'b'; char c = a+b; // 결과값은 Ã String a = "a"; String b = "b"; String c = a+b; final char a= 'a'; final char b = 'b'; char ccc = a+b; // 에러 안남

  • char의 문자열 연산은 해당문자의 유니코드 ( 정수 ) 로 바뀌어 저장되므로 정수간의 연산이된다.

  • 문자열 자체가 더해지는 것이 아닌 유니코드가 더해져서 char에 변수에 담는것이다.

  • 재밌게도 스트링은 따로 형변환을 안해도 되고 그자체로 더해진다.

    • 그 이유는 스트링은 리터럴이기 때문이다.
    • 리터럴 끼리의 합은 형변환을 안해도 된다.
      • 문자열 끼리만이 아닌 정수와 실수도 가능하다.
  • 리터럴 연산

    • 리터럴 연산은 컴파일시 컴파일러가 먼저 계산하고 리터럴간의 연산을 먼저 실행시킨다.
    • 그래서 형변환을 안해도 연산이 되는것이다.
    • 만약 리터럴이 아닐경우 도중에 값이 바뀔 위험이 있기에 컴파일러가 미리 연산을 하지 못한다 그래서 형변환이 필요한것이다.
  • 나머지 연산자

    • 왼쪽의 피 연산자를 오른쪽의 피연산자로 나누고 난 나머지 값을 결과로 리턴하는 연산자.
    • 나눗셈처럼 나누는 수 ( 오른쪽 피 연산자) 를 0으로 사용할수 없다.

비트 연산자

  • 피연산자를 비트단위로 논리 연산한다.

  • 피연산자를 이진수로 표현할 경우의 각 자리를 규칙에따라 연산하고 피연산자로 실수는 허용하지 않는다. 정수만 가능

  • 연산 규칙

    • | ( OR 연산자 )
      • 피연산자 중 한쪽의 값이 1이면 1로 값을 리턴한다 그 이외에는 0으로 리턴
    • & ( AND 연산자 )
      • 피연산자 양쪽이 모두 1이어야만 1로 값으로 리턴한다. 그이외에는 0으로 리턴
    • ^ ( XOR 연산자 )
      • 피연산자의 값이 서로 다를때만 1로 값을 리턴한다. 같을때는 0을 리턴한다.
  • 쉬프트 연산자 << >>

    • 피연산자의 각 자리 ( 2진수로 표현했을 때)를
    • 오른쪽 >> 또는 왼쪽 << 으로 이동한다고 해서 쉬프트 연산자 라고 불린다.
    • 예를 들어 " 8 << 2 " 는 왼쪽 피연산자인 10진수의 8의 2진수를 왼쪽으로 2자리 이동한다.
    10진수 8은 2진수로 '00001000' 8 << 2 는 10진수 8의 2진수를 왼쪽으로 2자리 이동시킨다 0 0 0 0 1 0 0 0 에서 왼쪽으로 2자리 이동되므로 가장 앞 2자리는 버려진다. 남은 값은 0 0 1 0 0 0 0 0 (10진수로 32) 빈자리는 0으로 채워진다. System.out.println((8 << 2)); // 결과값은 32
  • 비트전환 연산자 ~

    • 피연산자를 2진수로 표현했을때 0은 1로 , 1은 0으로 바꾼다.
    byte p = 10; System.out.println("~p = " + ~p); // 결과 -11 10은 이진수로 00000000000000000000000000001010이 된다. ~를 사용하여 0과 1이 뒤바뀌면 아래와 같이 -11의 이진수 값이 된다. -11은 이진수로 11111111111111111111111111110101이 된다.

관계 연산자

  • 두 연산자를 비교하는데 사용되는 연산자다.
  • 주로 조건문 과 반복문의 조건식에 사용된다.
  • 결과는 오직 true, false 단 두개뿐이다.

대소비교 연산자

  • 두 연산자의 값의 크기를 비교하는 연산자

  • 참 일 경우 true , 거짓이면 false를 리턴한다.

  • boolean형을 제외한 나머지 자료형에는 사용가능하나 참조형에는 사용할수 없다.

  • 4가지 종류가 존재한다.

      • 좌변이 크면 ture 아니면 false
    • <
      • 좌변이 작으면 true 아니면 false
    • =

      • 좌변이 크거나 같으면 true 아니면 false
    • <=
      • 좌변이 작거나 같으면 true 아니면 false

등가비교 연산자

  • 두 피연산자의 값이 같은지 또는 다른지를 비교하는 연산자

  • 대소비교 연산자와 다르게 기본형 , 참조형 , 모든 자료형에 사용 가능하다.

  • 기본형의 등가비교일 경우 저장되어있는 값이 같은지를 알수 있고

  • 참조형의 등가비교일 경우 저장되어있는 객체의 주소값을 비교한다.

  • 2가지 종류가 존재

    • ==
      • 두 값이 같으면 ture 아니면 false
    • !=
      • 두 값이 다르면 true 아니면 false

문자열의 비교

  • String으로 문자열을 비교할 경우에는 == 대신 equals를 사용 해야 한다.
  • ==로 비교하는 것은 참조주소를 비교한다는 것이기 때문에 만약 문자열이 같더라도
  • 참조주소가 다르면 다른것으로 간주하기 때문이다.
  • equals를 사용하면 문자열을 비교하기 때문에 문자열이 같으면 true를 반환한다.

논리 연산자

  • 2가지 조건으로 결합하여 참과 거짓을 구분한다.
    • && 와 ||

boolean a = true; boolean b = false; (a && a) // true (a || a) // true (a && b) // false (a || b) // true (b && b) // false (b || b) // false

  • 2가지 조건
    • && ( AND 결합 )
      • 피연산자 양쪽 모두 true 이어야 true를 리턴한다.
    • || ( OR 결합 )
      • 피연산자 중 한쪽 만 true면 true를 리턴 한다.

논리 부정 연산자

  • 피연산자가 true면 false로 false면 true로 결과를 바꿔서 리턴한다.

boolean a = true; boolean b = false; !a // false; !b // true;

instance of 연산자

  • 참조변수가 참조하고 있는 인스턴스의 실제 타입을 확인하는 연산자.
  • instanceOf 가 true 란 것은 그 타입일수도 있고 그 타입으로 형변환이 가능하다는 것이다.

void test (Car c) { if (c instanceOf SportsCar) { SportsCar sc = (SportsCar)c; } }

  • 위와 같이 사용할 경우 test 메소드의 Car c의 타입을 정확히 알수가 없다.
  • 진짜 car인지 아니면 car의 자손 클래스인지 정확히 알수가 없다.
  • 그렇기 떄문에 체크해서 사용한다.

assignment(=) operator

  • 대입 연산자

    • 변수와 같은 저장공간에 값 또는 수식의 연산결과를 저장하는데 사용
    • 오른쪽 피연산자의 값을 왼쪽 피연산자에 저장한다.
    • 대입 연산자의 왼쪽 피연산자를 lvalue ( left value ) 라고 하며
    • 오른쪽을 rvalue ( right value ) 라고 한다.
  • 복합 대입연산자

    • 다른 연산자와 결합하여 op= 와 같은 방식으로 사용가능하다.
    i = i+3; 과 같은 코드를 i +=3; 과 같이 사용 가능하다.

화살표 연산자

  • lambda를 표현식을 작성하기 위한 연산자다.

1. Interface k = new Interface() { @Override public void main() { } }; 2. Koy k = () -> { };

  • 위와 같이 인터페이스의 메소드가 1개일 경우 아래와같이 익명함수를 간단하게 람다식으로 변경할수 있다.

3항 연산자

  • 피연산자를 3개를 사용하는 연산자
  • 조건식과 결과 결과 로 이루어져 있으며 결과에 다시 3항연산자가 들어갈수도 있다.

int a = 1; int b = 2; int c = 3; boolean d = a < b ? true : false boolean d = a < b ? a < c ? true : false : false

연산자 우선순위

  • 식에 사용된 연산자가 둘 이상일 경우 연산자 우선순위에 의해 순서가 결정된다.
  • 곱셈과 나눗셈은 덧셈과 뺼셈보다 우선순위가 높다. ( 기초수학 )

x << 2 + 1 data & 0xFF == 0 x < 1 || x > 3 && x < 5

  • << 연산자는 덧셈 연산자보다 우선순위가 낮다.
  • & 연산자는 == 연산자보다 우선순위가 낮다.
  • &와 && 연산자는 |과 || 보다 우선순위가 높다.
  • and 와 or을 같이사용하는 경우에는 괄호를 사용해 우선순위를 명확하게 하는것이 좋다.

x + 3 > y - 2 x > 3 && x - 2 result = x + y * 3

  • 비교연산자는 산술 연산자보다 우선순위가 낮다

  • && 연산자는 비교 연산자보다 순위가 낮다.
  • 대입연산자는 연산자중에서 우선순위가 제일 낮다.

우선순위 결론

  • 산술 > 비교 > 논리 > 대입 의 순위이며

  • 대입은 제일 마지막에 수행된다.

  • 단항 > 이항 > 삼항

  • 단항 연산자의 우선순위가 이항 연산자보다 높다.

  • 단항 연산자와 대입연산자를 제외한 모든 연산의 진행방향은 왼쪽에서 오른쪽이다.

Java 13 Switch Operator

  • preview 기능이므로 —enable-preview 옵션을 줘야 사용할수 있다.

  • : 대신 → 를 사용할 수 있다.

  • switch가 expression으로 사용될 수 있다.

    • 타입을 지정하고 변수를 할당할수 있게 되었다.
  • yeild 키워드가 추가 되었다.

    • return과 같이 사용가능.

switch (name) { case "KKK" -> System.out.println("이름이 KKK"); case "DDD" -> System.out.println("이름이 DDD"); } String result = switch (name) { case "KKK" -> "nameKKK"; case "DDD" -> "nameDDD"; }; String result = switch (name) { case "KKK" -> "nameKKK"; case "DDD" -> "nameDDD"; default -> { String a = "newname" yield a; } };

출처

https://johngrib.github.io/wiki/jdk13/#switch-expressions-preview

자바의정석

http://blog.kurien.co.kr/495

'백선생님 온라인스터디' 카테고리의 다른 글

6주차 상속  (0) 2021.01.10
4주차 - 제어문  (0) 2021.01.09
3주차 연산자  (0) 2021.01.07
스터디 2주차 - 자바 데이터타입, 변수 그리고 배열  (0) 2020.11.21
스터디 1주차 - JVM  (0) 2020.11.15
  • 오류처리는 깨끗한 코드와 연관성이 있다.
  • 하지만 오류처리로 인해 프로그램 논리를 이해하기 어려워 진다면 깨끗한 코드라 부르기 어렵다.
  1. 오류 코드보다 예외를 사용하라.

    • 함수를 호출 하는 즉시 오류 를 확인하고 처리해야하기 때문에 복잡한다.
    • 그래서 그냥 예외를 던지면 편하다.
    • 코드도 깔끔해지고 로직을 이해하기가 더 쉬워진다.
  2. Try- Catch - Finally 문 부터 작성하라.

  • try-catch 문은 트랜잭션과 유사하다.
  • 예외가 발생할 코드를 짤때는 try catch 문 부터 작성하자.
  1. 미확인 ( Unchecked ) 예외를 사용하라.
  • 확인된 예외는 OCP를 위반한다.

    • 확인된 예외를 던졌는데 catch 블록이 세 단계 위에 있다면 그 사이 메소드 모두가 선언부에 해당 예외를 정의해야 한다.
    • 즉 하위 단계에서 코드를 변경하면 상위 단계 메서드 선언부를 전부 고쳐야 한다는 말이다.
  • 최상위 함수에서 점점 아래함수를 호출하여 최하위 함수에서 새로운 오류를 던진다고 했을떄

  • 확인된 오류를 던진다면 최하위 함수를 거쳐온 모든 함수들을 수정해야 한다. ( throws 절을 추가 하거나 catch 블록에서 예외처리 )

  • 그리고 모든 함수가 최하위 함수가 던지는 예외를 알아야 하므로 캡슐화가 깨진다.

  • 아주 중요한 라이브러리를 작성한다면 모든 예외를 잡아야 한다.

  • 하지만 일반적인 애플리케이션은 의존성이라는 비용이 이익보다 크다.

  1. 예외에 의미를 제공해라.
  • 오류메세지에 정보를 담아 예외와 함께 던지면 발생한 원인과 위치를 찾기가 쉬워진다.
  • 로깅도 사용한다면 catch 블록에서 오류를 기록하도록 충분한 정보를 넘겨준다.
  1. 호출자를 고려해 예외 클래스를 정의하라.
  • 애플리케이션에서 오류를 정의할때 프로그래머에게 가장 중요한 관심사는

  • 오류를 잡아내는 방법 이 되어야 한다.

  • 외부 api를 사용할때 wrapper 클래스를 하나 만들어서 예외 처리하는 것은 좋은 방법이다.

  • 외부 api를 감싸면 외부 라이브러리와 프로그램 사이에 의존성이 크게 줄어든다.

  • 갈아끼우는것도 쉽다. wrapper 클래스에서 수정하면 되기 떄문.

  • ( wrapper 클래스 작성하는 비용이면 그냥 wrapper 클래스 안쓰고 class에 쓰면 되지않나 ? )

  • ( 의존성이 줄어든다는 장점때문에 wrapper를 사용하는것 같다 )

  • 흔히 예외 클래스가 하나만 있어도 충분한 코드가 많다.

  • 예외 클래스에 포함 된 정보로 오류를 구분해도 괜찮은 경우가 그렇다.

  • 한 예외는 잡아내고 다른 예외는 무시해도 괜찮은 경우라면 여러 예외 클래스를 사용한다.

  • ( 이 3문단이 이해가 안된다. )

  1. 정상 흐름을 정의하라.
  • 비즈니스와 오류처리가 잘 분리되면 코드가 대부분이 깨끗하고 간결하게 보인다.

  • 하지만 그러다보면 점점 오류처리가 저 멀리 떨어져 나가게된다

  • 굳이 예외처리를 안하는 상황이 있다.

  • 이를 특수사례 패턴이라 부른다.

  • 클래스를 만들거나 객체를 조작해 특수사례를 처리하는 방식이다.

  • 그러면 클라이언트 코드가 예외적인 상황을 처리할 필요가 없어진다.

  • 클래스나 객체가 예외적인 상황을 캡슐화해서 처리하므로.

  • ( 굳이 예외처리가 코드를 복잡하게 만든다면 Martin Fowler의 Special Case Pattern을 사용하자.(참조 3) )

  1. null을 반환하지 마라.
  • null을 반환하는 코드는 호출자에게 일거리를 늘려주는일이다.
  • null대신에 특수사례 객체를 반환하자.
  • 사용하려는 외부 API가 null을 반환한다면 wrapper method를 구현해 예외를 던지거나
  • 특수사례 객체를 반환하는 방식을 고려한다.
  • 많은 경우에 특수사례 객체가 손수윈 해결책이다.
  1. null을 전달하지 마라.
  • 정상적인 인수로 null을 기대하는 API가 아니라면 메서드로 null을 전달하는 코드는 최대한 피한다.
  • assert문을 사용해서 null체크 하는것도 괜찮은 방법이다.
  • ( 신기하다 다시보자 )

결론

  • 깨끗한 코드는 읽기도 좋아야 하지만 안전성도 높아야 한다.

'book > 클린코드' 카테고리의 다른 글

9장 - 단위 테스트  (0) 2020.12.02
8장 - 경계  (0) 2020.11.30
6장 - 객체와 자료구조  (0) 2020.11.25
5장 - 형식 맞추기  (0) 2020.11.23
4장 - 주석  (0) 2020.11.22
  • 변수를 private으로 하는 이유는남들이 변수에 의존하게 하고싶지 않기 떄문이다.
  1. 자료 추상화

    • 추상 인터페이스를 사용해 사용자가 구현을 모른채 자료의 핵심을 구현할수 있어야
    • 진정한 클래스다.
    • 자료를 세세하게 공개하기 보다는 추상적인 개념으로 표현하는 것이 좋다.
    • 인터페이스나 조회 설정 함수만으로는 추상화가 이뤄지지 않는다.
    • 개발자는 객체가 포함하는 자료를 표현할 가장 좋은 방법을 심각하게 고민해야 한다.
    • 아무 생각없이 조회/설정 함수를 추가하는 방법이 가장 나쁘다.
  2. 자료/객체 비대칭

    • 객체는 추상화 뒤로 자료를 숨긴채 자료를 다루는 함수만 공개한다.
    • 자료 구조는 자료를 그대로 공개하며 별다른 함수는 제공하지 않는다.
    • 객체지향 코드에서는 어려운 변경은 절차적인 코드에서 쉽고
    • 절차적인 코드에서 어려운 변경은 객체지향 코드에서 어렵다.
    • ( 나는 아직 까지 절차지향에서 벗어나지 못하고 있었다. )
  3. 디미터 법칙

    • 모듈은 자신이 조작하는 객체의 속사정을 몰라야 한다는 법칙

    • 위에서 봣듯이 객체는 자료를 숨기고 함수를 공개한다.

    • 객체는 조회 함수로 내부 구조를 공개하면 안된다는 의미다.

    • 디미터 법칙은 클래스C의 메서드f는 다음과 같은 객체의 메서드만 호출해야 한다고 주장한다.

      • 클래스 C
      • f가 생성한 객체
      • f 인수로 넘어온 객체
      • C인스턴스 변수에 저장된 객체
    • 디미터 법칙은 메소드 체이닝을 사용하지 말라고한다.

    • 기차 충돌

      • 메소드체이닝을 기차충돌이라고 부른다고 한다.
      • 객체가 한줄로
    • 잡종 구조

      • 절반은 객체 절반은 자료 구조인 잡종 구조
      • 되도록 피하는 것이 좋다.
    • 구조체 감추기

      • 객체에게 뭔가를 시켜야지 객체의 내부구조를 보이게 해선 안된다.
      • ( 어렵다 )
    • 자료 전달 객체

      • DTO 라고도 한다.

      • bean 구조 이며 데이터베이스에 저장된 가공되지 않은 정보를 애플리케이션 코드에서 사용할 객체로 변환하는 일련의 단계에서 가장 처음으로 사용되는 구조체다.

      • DTO의 private 변수를 조회 설정 함수로 조작한다는 것을 작가 할아버지는 사이비 캡슐화로 보고있으며 별다른 이익을 제공하지 않는다고 한다.

      • ( 난 여태까지 이렇게 해왔었는데 잘못된 것이였는가 ? )

      • 활성 레코드

        • DTO와 같으며 대개 save와 find 같은 탐색함수도 제공한다.
        • 활성 레코드는 데이터베이스 테이블이나 다른소스에서 자료를 직접 변환한 결과다.
        • 활성레코드는 자료 구조로 취급한다.

      결론

      • 객체는 동작을 공개하고 자료를 숨긴다.
      • 기존 동작을 변경하지 안ㅇ흐면서 객체 타입을 추가하기는 쉬운 반면
      • 기존 객체에 새동작을 추가하기는 어렵다.
      • 자료구조는 별다른 동작 없이 자료를 노출한다.
      • 그래서 기존 자료구조에 새 동작을 추가하기는 쉬우나
      • 기존 함수에 새 자료구조를 추가하기는 어렵다.

'book > 클린코드' 카테고리의 다른 글

8장 - 경계  (0) 2020.11.30
7장 - 오류처리  (0) 2020.11.27
5장 - 형식 맞추기  (0) 2020.11.23
4장 - 주석  (0) 2020.11.22
3장 - 함수  (0) 2020.11.19
  • 깔끔하게 보기 좋은 코드를 만들자.
  • 간단한 규칙을 정하고 규칙을 착실히 따라야 한다.
  • 팀으로 일한다면 팀이 합의해 규칙을 정하고 모두가 따라야한다.
  • 자동으로 적용하는 도구를 활용하자.
  • ( 우리회사는 구글 형식맞추는거 사용 )
  1. 형식을 맞추는 목적

    • 코드의 형식은 중요하다 너무중요하다.
  2. 적절한 행길이를 유지하라

    • 클래스 하나가 500줄을 넘지 않고 대부분 200줄로만 짜고도

    • 커다란 시스템을 구축할수 있다.

    • 일반적으로 큰파일보다 작은파일이 이해하기가 쉽다.

    • 신문기사 처럼 작성하라.

      • 이름은 간단하면서도 설명이 가능하게 짓는다.
      • 이름만 보고도 올바른 모듈을 살펴보고 있는지 아닌지를 판단할 정도로 신경 써서 짓는다.
      • 소스 파일 첫부분은 고차원 개념과 알고리즘을 설명한다.
      • 아래로 내려갈수록 의도를 세세하게 묘사한다.
      • 마지막에는 가장 저차원 함수와 세부내역이 나온다.
    • 개념은 빈행으로 분리하다.

      • 거의 모든 코드는 왼쪽에서 오른쪽 그리고 위에서 아래쪽으로 읽힌다.
      • 각 행은 수식이나 절을 나타내고, 일련의 행 묶음은 완결된 생각 하나를 표현한다.
      • 생각 하나 사이에는 빈 행을 넣어 분리해야 마땅하다.
      • 빈 행은 새로운 개념을 시작한다는 시각적 단서다.
      • ( 말 멋있다. )
    • 세로 밀집도

      • 줄바꿈이 개념을 분리 한다면 세로 밀집도는 연관성을 의미한다.
      • 즉 서로 밀집한 코드행은 세로로 가까이 놓여야 한다는 뜻이다.
      • 변수나 일급컬렉션 메소드 이 3개도 붙여야된다. 연관되어있다면.
    • 수직거리

      • 서로 밀집한 개념들은 세로로 가까이 둬야 한다.
      • 서로 밀집한 개념들은 한파일에 속해야 마땅하다.
      • protected 변수를 피해야 되는 이유.
      • ( protected 변수를 쓰면 같은 패키지내에서 쓸수 있으니까. )
    • 변수선언

      • 변수는 사용하는 위치에 최대한 가까이 선언한다.
      • 루프문을 제어하는 변수는 흔히 루프 문 내부에 선언한다.
    • 인스턴스 변수

      • 반면 인스턴스 변수는 클래스 맨 처음에 선언한다.
      • 변수간에 세로로 거리를 두지 않는다.
      • 잘 설계한 클래스는 많은 클래스 메서드가 인스턴스 변수를 사용하기 때문이다.
    • 종속 함수

      • 한 함수가 다른 함수를 호출 한다면 두 함수는 세로로 가까이 배치한다.
      • 또한 그낭하다면 호출하는 함수를 호출되는 함수보다 먼저 배치한다.
      • 첫째 함수에서 호출하는 첫번째 함수가 바로 아래 정의된다.
      • 그다음은 그아래 정의된다.
      • 그러므로 호출되는 함수를 찾기가 쉬워지며 그만큼 모듈 전체의 가독성도 높아진다.
    • 개념의 유사성

      • 비슷한 동작을 수행하는 일군의 함수들
      • 명명법이 비슷하고 기본 기능이 유사한것들
      • 종속적인 관계가 없더라도 가까이에 배치해야될 함수
    • 세로 순서

      • ( 좀 어렵다 )
      • 호출되는 함수를 호출하는 함수보다 나중에 배치한다.
      • 그러면 소스코드 모듈이 고차원에서 저차원으로 자연스럽게 내려간다.
    • 가로형식 맞추기

      • 한 행은 가로로 얼마나 길어야 적당할까 ?
      • 글쓴이 할아버지는 120자정도로 행길이를 제한함.
    • 가로 공백과 밀집도

      • aa(String a)
      • 이것처럼 함수안에 인자는 괄호 사이에 공백을 넣지 말자.
      • 여러개일경우는 우선순위를 강조하기 위해서 공백을 사용한다.
      • 연산자 ( + - 같은것들 ) 은 우선순위 강조를 위해 띄어 쓴다.
    • 가로 정렬

      • 선언문과 할당문을 별도로 정렬하면 보기가 안좋다
      • 예) String a;
      • 예) Long b;
      • 예) Integer c;
      • 정렬이 필요할 정도로 목록이 길다면 클래스를 쪼개야 된다는 의미다.
    • 들여쓰기

      • 범위로 이루어진 계층을 표현하기 위해 우리는 코드를 들여 쓴다.
      • 들여쓰는 정도는 계층에서 코드가 자리잡은 수준에 비례한다.
      • 클래스 정의처럼 파일 수준인 문장은 들여 쓰지 않는다.
      • 클래스 내 메서드는 클래스보다 한 수준 들여 쓴다.
      • 메서드 코드는 메서드 선언보다 한 수준 들여 쓴다.
      • 블록 코드는 블록을 포함하는 코드보다 한 수준 들여 쓴다.
    • 들여쓰기 무시하기

      • 간단한 if문 짧은 while문 짧은 함수에서 들여쓰기 규칙을 무시하면 안된다.
      • 한행에 범위를 뭉뚱그린 코드를 피한다
      • 예) public String render() throws Exception { return ""; }
    • 가짜 범위

      • 때로는 빈 while문이나 for문을 접한다.
      • 제대로 들여쓰기해서 써줘라.
    • 팀 규칙

      • 팀이 규칙을 정했으면 팀원은 그 규칙을 정해야 한다.

'book > 클린코드' 카테고리의 다른 글

7장 - 오류처리  (0) 2020.11.27
6장 - 객체와 자료구조  (0) 2020.11.25
4장 - 주석  (0) 2020.11.22
3장 - 함수  (0) 2020.11.19
2장 - 의미있는 이름들  (0) 2020.11.17

개요

  • 주석은 잘달리면 유용하다.

  • 쓸데없는 주석이나 조잡한 주석은 거짓과 잘못된 정보를 퍼뜨려 해악을 미친다.

  • 주석을 쓴다는 것은 내가 코드를 잘 설명한다는것에 실패했다는 의미.

  • 왜냐면 그것을 보완하는 설명을 주석으로 쓰는것이니까.

  • 주석은 오래될수록 코드랑 멀어진다. 오래될수록 완전히 잘못될 가능성도 높아진다.

  1. 주석은 나쁜 코드를 보완하지 못한다.
  • 주석 달아도 코드 그지같은건 그지같은거니까 코드 그지같은거나 고쳐라
  1. 코드로 의도를 표현하라.
  • 주석으로 달려는 설명도 코드로 충분히 표현할수 있다.
  1. 좋은 주석
  • 어떤 주석은 필요하거나 유익하다.

  • 하지만 정말 좋은 주석은 주석을 달지 않을 방법을 찾아낸 주석이란것을.

  • 법적인 주석

    • 회사가 정립한 구현 표준에 맞춰 특정 주석을 넣으라고 명시한다.
    • 이럴 경우 사용한다.
    • 그리고 각 소스 파일 첫머리에 주석으로 들어가는 저작권 정보와 소유권 정보는 필요하고도 타당하다.
    • ( 쓰레기라더니 좋게말함 ㅋㅋ)
  • 정보를 제공하는 주석

    • 추상 메서드가 반환할 값을 설명할 경우
      • 하지만 가능하다면 함수 이름에 정보를 담자.
    • 정규표현식이 시각과 날짜를 뜻하는 경우를 주석으로 표현할때
    • 이럴 경우는 시각과 날짜를 변환하는 클래스를 만들어 코드를 옮겨주면 더 깔끔해지고
    • 주석이 필요 없어진다.
  • 의도를 설명하는 주석

    • 때떄로 주석은 이해하게 도와주는 선을 넘어 결정에 깔린 의도까지 설명한다.
  • 의미를 명료하게 밝히는 주석

    • 인수나 반환값이 표준 라이브러리나 변경하지 못하는 코드에 속한다면 의미를 명료하게 밝히는 주석이 유용하다.
    • 그릇된 주석을 달 확률도 높아진다.
    • 그래서 주석을 검증하기가 쉽지가 않으므로 고민하고 사용하도록 한다.
  • 결과를 경고하는 주석

    • 테스트케이스를 실행하면 안될 경우 사용하는 주석

    • 이럴떈 @Ignore 애노테이션을 사용 하자. 예) @Ignore("시간이 오래걸리니까 쓰지마세요")

    • //쓰레드에 안전하지 못하다.

    • //그래서 각 인스턴스를 독립적으로 생성해야 된다.

    • 위와 같은 주석이 아주 합리적이다.

    • 쓰레드를 정적으로 초기화 시켜서 사용할수도 있는데 이 주석을 보고 실수를 면한다.

  • Todo 주석

    • 때로는 앞으로 할일을 주석으로 남겨두면 편하다.
    • 함수를 구현하지 않은 이유와 미래 모습을 Todo 주석으로 설명할수 있다.
    • 당장 필요하지도 않고 구현하기가 쉽지 않은 것들을 써논다.
    • 하지만 TOdo 코드로 떡칠하는건 좋지 않다.
    • 주기적으로 Todo 주석을 점검해 없애도 괜찮은 주석은 없애자.
  • 중요성을 강조하는 주석

    • 대수롭지 않다고 여겨질 뭔가의 중요성을 강조하기 위해 주석을 사용한다.
    • ( 이건 나쁘다 좋다 별말이 없다 )
  • 공개 API에서 javadocs

    • 설명이 잘 된 공개 API는 참으로 유용하고 만족스럽다.
    • 특히 표준 자바 라이브러리에서 사용한 javadocs가 좋은 예다.
    • 공개 API를 구현한다면 javadocs를 아주 잘써야된다.
  1. 나쁜주석
  • 대다수 주석이 이 범주에 속한다.

  • 쓸데없이 주절거리는 주석

    • 자기만 이해하는 주석은 낭비다.
  • 같은 이야기를 중복하는 주석

    • 알기쉬운 코드를 그대로 주석으로 옮겨논것
    • 간단하거나 다 아는것들을 쓸데없이 여러번 쓰는것
    • 이건 예제를 봐야됨. 목록 4-2 ContainerBase.java
  • 오해할 여지가 있는 주석

    • 오해할 여지조차 주게 하면 안된다.
  • 의무적으로 다는 주석

    • 모든 함수에 javadocs를 넣으라는 규칙 같은건 하면 안된다.
  • 이력을 기록하는 주석

    • 이젠 git같은 소스관리 시스템같은게 있으니까 그만달자.
  • 있으나 마나 한 주석

    • 이런건 쓰지말자.
    • 예) 기본생성자
  • 무서운 잡음

    • 변수명과 동일한 주석
    • ( 진짜 똑같음 )
  • 함수나 변수로 표현할수 있다면 주석을 달지마라

  • 위치를 표시하는 주석

    • 가독성이 구려지므로 특히 뒷부분에 슬래쉬 ex ) //////// 이런식으로 끝나는 잡음은 제거하는 편이 좋다.
    • 진짜 필요할떄만 아주 드물게 사용해라
  • 닫는 괄호에 다는 주석

    • } // try
    • 위처럼 닫는 괄호에 주석 다는대신 함수를 줄이려고 시도해라.
  • 공로를 돌리거나 저자를 표시하는 주석

    • 이제 git과 같은 소스코드 관리시스템이 있으므로 지워라
  • 주석으로 처리한 코드

    • 주석으로 처리된 코드는 다른 사람들이 지우기를 주저한다.
    • 그냥 지워라.
    • git이 기억해준다.
  • HTML 주석

    • 혐오 그자체다
    • 도구로 주석을 뽑아 웹페이지에 올릴 작정이라면 그건 도구가 해야할일이다.
  • 전역정보

    • 주석을 달아야 한다면 근처에 있는 코드만 써라
    • 코드 일부에 주석을 달면서 시스템의 전반적인 정보를 쓰지마라.
    • 왜냐면 시스템 어딘가에 있는것들을 설명한것인데 그것이 어딨는지 읽는사람은 전혀 모르니까.
  • 너무 많은 정보

    • 주석에다 흥미로운 역사나 관련 없는 정보를 쓰지마라.
  • 모호한 관계

    • 주석과 주석이 설명하는 코드는 둘사이의 관계가 명백해야 한다.
    • 주석자체가 다시 설명을 요구해선 안된다.
  • 함수 헤더

    • 짧은 함수는 긴 설명이 필요없다.
    • 함수를 짧고 한가지만 수행하도록 만들며 함수에 이름 잘붙여라 함수헤더같은거 쓰지말고
  • 비공개 코드에서 javadocs

    • 공개하지 않을거면 쓸모가 없다.

'book > 클린코드' 카테고리의 다른 글

7장 - 오류처리  (0) 2020.11.27
6장 - 객체와 자료구조  (0) 2020.11.25
5장 - 형식 맞추기  (0) 2020.11.23
3장 - 함수  (0) 2020.11.19
2장 - 의미있는 이름들  (0) 2020.11.17

www.notion.so/77b364c091ea4d81a74042331b26dc1e

 

자바 데이터타입, 변수 그리고 배열

목표

www.notion.so

 

목표

  • 자바의 프리미티브 타입, 변수 그리고 배열을 사용하는 방법을 익힙니다.

학습할것

  • 프리미티브 타입 종류와 값의 범위 그리고 기본 값
  • 프리미티브 타입과 레퍼런스 타입
  • 리터럴
  • 변수 선언 및 초기화하는 방법
  • 변수의 스코프와 라이프타임
  • 타입 변환, 캐스팅 그리고 타입 프로모션
  • 1차 및 2차 배열 선언하기
  • 타입 추론, var

프리미티브 타입 종류와 값의 범위 그리고 기본값

  • 프리미티브 타입의 종류
    • 자바에는 8가지의 타입이 있으며 논리형, 문자형, 정수형, 실수형으로 나뉘어져있다.
      1. 논리형

        • boolean
          • true와 false중 하나를 값으로 가진다.
          • 나머지 타입들과 연산이 불가능함.
          • 크기는 1byte
          • 값의 범위는 false, true
          • 기본값은 false
      2. 문자형

        • char
          • 문자를 저장한다.
          • 변수에 하나의 문자만 저장가능
          • 다만 내부적으로 유니코드 ( 정수 ) 로 저장하기 때문에 정수형과 별반 다르지 않다.
          • 그렇기에 정수형 또는 실수형과 연산이 가능하다.
          • 크기는 2byte
          • 값의 범위는 '\u0000' ~ '\uffff'
          • 기본값은 \'u0000'
      3. 정수형

        • byte, short, int, long
          • 정수를 저장함
          • int를 주로 사용하며 ( 기본 자료형 )
            • 크기는 4byte
            • 값의 범위는 -2,147,483,648 ~ 2,147,483,647
            • 기본값은 0
          • byte는 이진데이터를 사용할때 쓰고
            • 크기는 1byte
            • 값의 범위는 -128 ~ 127
            • 기본값은 0
          • short는 C언어와의 호환을 위해 사용
            • 크기는 2byte
            • 값의 범위는 -32,768 ~ 32767
            • 기본값은 0
          • long은 int 이상의 범위가 필요할때 사용
            • 크기는 8byte
            • 값의 범위는 -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
            • 기본값은 0L
      4. 실수형

        • 실수를 저장하는데 사용 주로 double ( 기본 자료형 ) 을 사용한다.
          • double
            • 크기는 double은 8byte 다.
            • 값의 범위는 4.9E-324 ~ 1.8E308
            • 기본값은 0.0
          • float
            • 크기는 float은 4byte
            • 값의 범위는 1.4E-45 ~ 3.4E38
            • 기본값은 0.0F

프리미티브 타입과 레퍼런스 타입

  • 프리미티브 타입
    • 실제 값을 저장한다.
    • 프리미티브 타입도 객체로 사용할때가 있다.
      • Boxing을 통해 프리미티브 타입을 감싼다고해서 Wrapper Class 라고 불린다.
        • 프리미티브 타입과 달리 주소를 값으로 가지고 있기 때문에
        • Null을 컨트롤 할수 있다.
  • 레퍼런스 타입
    • 값이 저장되어 있는 주소를 값으로 저장한다.
    • 위에서 본 8개의 프리미티브 타입을 제외한 나머지 타입

리터럴

  • 변수와 상수는 값을 저장할수 있는 공간을 의미

  • 하지만 상수는 변경이 불가능하다.

  • 상수는 변경이 불가능하므로 그자체로 값이라고 볼수 있다.

  • 그래서 상수의 다른이름은 리터럴

  • 리터럴은 값 그자체를 일컫기 때문이다.

  • 보통 String과 같은 불변 클래스들은 값의 변경이 가능하다.

  • 하지만 불변클래스는 값이 변할수 없는 클래스인데 어떻게 가능한 것일까 ?

    • 불변 클래스는 값이 불변이기 때문에 변경할수가 없다.
    • 그래서 새로운 스택을 만들어서 그곳에 새로 변경된 값을 저장한후
    • 불변클래스는 담고있는 주소의 값을 새로만든 스택의 주소로 바꾼다.
    • 이렇게해서 값을 변경시킨다.

변수 선언 및 초기화하는 방법

  • 변수 선언

    • 변수의 타입과 이름을 적는다.
    • 예) int count; // int 는 변수타입 count는 변수의 이름
    • 변수타입은 변수에 저장될 값이 어떤 타입인지 정하는 것이고
    • 변수이름은 변수에 붙인 이름이다.
  • 변수 초기화

    • 예) int count = 10; // int타입의 변수를 count란 이름으로 명명하고 10으로 초기화

    • 보통 선언과 초기화를 동시에 한다.

    • 생략하는 경우도 있지만 사용하기 전에 적절한 값으로 초기화 하는것이 좋다.

    • 명시적 초기화

      • 위와 같은 설명이 바로 명시적 초기화다.
    • 초기화 블럭

      • statc 초기화 블럭이나 인스턴스 초기화 블럭에서 초기화를 하면 된다.
      • 생성자보다 인스턴스 초기화 블럭이 먼저 수행된다.
    • 생성자 초기화

      • 변수를 선언만 해놓고 초기화는 하지 않고 생성자에서 초기화 하는 방법.

변수의 스코프와 라이프타임

  • 클래스 변수, 인스턴스 변수, 지역 변수 총 3가지가 있다.
    1. 클래스 변수

      • 선언 위치는 클래스 영역
      • 생성시기는 클래스가 메모리에 올라갈 때
      • 타입 앞에 static이 붙는다.
      • 클래스는 독립적인 저장공간을 갖지 않으므로 모든 인스턴스는 같은 값을 가진다.
    2. 인스턴스 변수

      • 선언 위치는 클래스 영역
      • 생성시기는 인스턴스가 생성되었을 때
      • 클래스 변수와 다르게 static이 붙지는 않는다.
      • 인스턴스는 독립적이므로 항상 다른값을 가질수 있다.
    3. 지역 변수

      • 선언 위치는 클래스 영역이 아닌 ( 메소드,생성자,초기화 블랙 내부 ) 이다.
      • 생성시기는 변수 선언문이 수행되었을 때
      • 인스턴스 변수와 마찬가지로 static이 붙지 않는다.
      • 메소드 블럭을 벗어나면 소멸한다.

타입 변환, 캐스팅 그리고 타입 프로모션

  • 타입 변환

    • 변수 또는 상수의 타입을 다른 타입으로 변환하는 것
  • 캐스팅

    double d = 99.9; int count = (int)d;
    • 캐스팅은 이렇게 명시적으로 변경해준다.
  • 타입 프로모션

    • 조건이 맞으면 컴파일러가 자동으로 형변환을 시켜준다.
    • 조건
      • 그 값이 형변환할 타입의 값을 초과하지 않는 것
      • 그리고 서로 연산이 가능한 타입이어야 한다는 것이다.
      • 프리미티브타입과 레퍼런스타입은 서로간에 타입 변환이 안된다.
      • 값의 범위가 작은 타입에서 큰 타입으로 변경할때도 가능

1차 및 2차배열 선언하기

  • 1차 배열 선언

    • 타입[] 변수이름; // 선언
    • 변수이름 = new 타입[길이]; // 생성
    int[] count; count = new int[10]; // 또는 int[] count = {1,2,3,4,5};
    • 선언만 했을경우 아직 메모리에 저장되지 않는다 왜냐면 길이가 정해지지 않았기 때문이다.
    • new에 의해 생성되거나 아예 선언과 동시에 생성할 경우에 메모리에 저장될 공간이 생성된다.
    • 그리고 각 값들은 int의 기본값인 0으로 초기화되고 ( new로 생성까지만 했을 경우 )
    • 그 이후나 값을 넣어주거나 선언과 동시에 값을 넣을 경우에는 배열에 그 값이 담긴 메모리 주소가 저장된다.
    • 배열의 길이에는 0도 포함된다.
  • 2차 배열 선언

    • 타입[][] 변수이름;
    //선언 방식은 3가지 int[][] count; //또는 int count[][]; // 또는 int[] count[]; //할당 방식은 1차배열과 비슷함 int[][] count; count = new int[10][10]; //또는 int[][] count = {{1,2},{2,3},{3,4},{1,4}}
    • 2차배열은 배열에 각각 배열의 주소가 담긴다.

타입추론, var

  • 타입 추론

    • 코드 작성당시 정해지지 않은 타입을 컴파일러가 유추하는 것
    • java 9버전 이하에서는 generic과 lambda를 사용할때 쓰이고
    • java 10버전부터 var이라는 local variable한 키워드가 추가되었다.
    • 이러한 타입추론 덕분에 제네릭타입에 타입을 명시하지 않아도 된다.
  • var

    • 지역변수로서만 사용가능하다.
    • 선언과 동시에 초기화가 필수
    • 다이아몬드 연산자와 같이 사용할수 없다
    • java 10버전 이상부터 사용가능하며 그 이하버전은 lombok 설치시 사용가능.
    • 예 )
    var message = "ganadaramabasa"; ~~var message = new ArrayList<>();~~

참조

'백선생님 온라인스터디' 카테고리의 다른 글

6주차 상속  (0) 2021.01.10
4주차 - 제어문  (0) 2021.01.09
3주차 연산자  (0) 2021.01.07
연산자  (0) 2020.11.28
스터디 1주차 - JVM  (0) 2020.11.15

함수를 어떻게 만들어야 처음보는 사람이 쉽게 이해할까 ?

  1. 작게 만들어라.

    • 최대한 작게만들어서 그 함수가 무슨 역할을 하는지 알수 있게 만든다.
  2. 함수는 한가지 일만 해야한다.

    • 그래야 명확하게 그 함수가 무슨역할인지 알수 있으니까.
    • 한가지 일은 추상화 수준이 하나인 단계
      • 같은 추상화 단계에서 일하는 것들이 모여있으면 이것은 한가지일만 하는것
      • 추상화 수준이란 무엇일까 ?
        • nested하게 내려가거나 올라가지 않고 같은 레이어에서 작동하는것.
      • 함수당 추상화 수준은 하나로 하자.
  3. 코드는 소설책같은것들 처럼 위에서 아래로 읽혔을때 잘 읽혀야 한다.

  • 내려가기 규칙
  • 아래로 내려갈수록 추상화 단계가 한단계 씩 낮은 함수가 온다.
  • 아래로 갈수록 상위 함수에서 나온 함수를 설명하는 느낌으로 간다.
    • 예를 들어 상위 함수에서 쓴 함수를 하위에 바로 붙여서 쓰는식으로.
  1. Switch 문
  • 추상 팩토리 ( abstract factory ) 에 숨겨서 사용한다.
  • 예제를 좀더 봐야겠다. 어렵다.
  1. 서술적인 이름을 사용하라!
  • 이름이 길어도 된다.
  • 작은기능을 가진 함수는 이름짓기도 쉽다.
  • 일관성 있게 이름을 지어라.
  • include블라블라
  1. 함수 인수
  • 이상적인 인수는 0개

    • 그다음 1개, 그다음 2개
    • 3개는 가능한 피하는 편이 좋다.
    • 4개이상은 특별한 이유가 필요하다.
    • 4개 이상은 이유가 있어도 거의 사용하면 안된다.
  • void일때 인수 받는건 가급적 피해라.

  • 플래그인수 ( boolean 값과 비슷한 체크용 인수 ) 이거 될수있음 쓰지마라

  • 인수 두개 받을때 될수있으면 writeField(outStream, name) 일 경우

  • writeField를 outStream에 합류시켜서

  • outStream.writeField(name) 으로 하나의 인수만 넣도록 하자.

  • 삼항함수는 신중히 고려해서 하도록 하자.

  • 인수가 2~3개일때 일부를 독자적인 class화 시켜서 class 변수로 선언하는 방법도 있다.

    • 대신 인수가 연관관계나 비슷한 관계여야함.
    • 그래야 줄였을경우 인수에 대한 개념을 표현할수 있으니까.
  • 단항함수 일때 함수와 인수가 동사/명사 쌍을 이뤄야 한다.

    • 이때 메소드 이름은 write(name) 보단 writeField(name) 를 사용해서
    • name이 field라는 사실이 드러나게 한다.
  • 그리고 함수이름에 키워드를 추가하는 형식도 있다.

  • 즉 함수이름에 인수이름을 넣는다.

    • assertEquals 보단 assertExpectedEqualsActual(expected, actual)이 더 좋다.
    • 그러면 인수 순서를 기억할 필요가 없어진다.
  1. 부수효과를 일으키지 마라.
  • 함수에서 하나의 기능만 사용한다고 약속하고서 남몰래 다른짓을 하지말자.

  • 때로는 예상치 못하게 클래스 변수를 수정한다.

  • 떄로는 함수로 넘어온 인수나 시스템 전역 변수를 수정한다.

  • 어느쪽이든 교활하고 해로운짓이다.

  • 예제를 보면 이해하기가 쉽다.

  • 일반적으로 출력 인수를 피해야 한다.

  • 함수가 상태를 변경해야 한다면 웬만하면 함수가 속한 객체에서 변경시키자

  • 예제를 보면 이해하기가 쉽다.

  1. 명령과 조회를 분리하라
  • 함수는 뭔가를 수행하거나 뭔가에 답하거나 둘중 하나만 해야 한다.
  • 둘다하면 안된다.
  • 객체 상태를 변경하거나 아니면 객체 정보를 반환하거나 둘중 하나다.
  1. 오류 코드보다 예외를 사용하라
  • 명령 함수에서 오류코드를 반환하는 방식은 명령 조회 분리 규칙을 미묘하게 위반한다.

  • 오류코드를 반환하면 호출자는 오류코드를 곧바로 처리해야되는 문제에 부딪힌다.

    • Try/Catch 블록 뽑아내기
    • try/catch 블록도 별도의 함수로 뽑아내는 편이 좋다.
  • 오류 처리도 한가지 작업이다.

  • 함수는 한가지 작업만 해야한다. 결국 오류처리도 한가지 작업에 속한다.

  • try가 있다면 try로 시작해 catch finally문으로 끝내야 된다는 말이다.

  • Errorjava 의존성 자석

  • 오류 코드를 반환한다는 이야기는 클래스든 열거형 변수든 어디선가 오류 코드를 정의한다는 뜻이다.

  • 그래서 오류코드대신 익셉션을 반환해라.

  1. 반복하지마라
  • 중복 없애라
  • 반복 하지마라
  1. 구조적 프로그래밍
  • 모든 함수와 모든 함수내 블록에는 입구와 출구가 하나씩만 존재해야된다.
  • 즉 함수는 return문이 하나여야 한다.

'book > 클린코드' 카테고리의 다른 글

7장 - 오류처리  (0) 2020.11.27
6장 - 객체와 자료구조  (0) 2020.11.25
5장 - 형식 맞추기  (0) 2020.11.23
4장 - 주석  (0) 2020.11.22
2장 - 의미있는 이름들  (0) 2020.11.17

+ Recent posts