2021-12-17 수업내용

범고래·2021년 12월 22일
0

비트캠프 수업내용

목록 보기
15/20

(1) 최적화와 리팩토링

(2) 리팩토링 예시

package com.eomcs.mylist;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController 
// 이 클래스가 클라이언트 요청 처리 담당자임을 표시한다.
// 이 표시(애노테이션)가 붙어 있어야만 스프링부트가 이 클래스를 인식한다.
public class ContactController {

  String[] contacts = new String[5];
  int size = 0;

  @RequestMapping("/contact/list")
  public Object list() {
    String[] arr = new String[size]; // 배열에 저장된 값만 복사할 새 배열을 만든다.
    for (int i = 0; i < size; i++) { 
      arr[i] = contacts[i]; // 전체 배열에서 값이 들어 있는 항목만 복사한다.
    }
    return arr; // 복사한 항목들을 담고 있는 새 배열을 리턴한다.
  }

  @RequestMapping("/contact/add")
  public Object add(String name, String email, String tel, String company) {
    String contact = name + "," + email + "," + tel + "," + company;
    contacts[size++] = contact;
    return size;
  }

  @RequestMapping("/contact/get")
  public Object get(String email) {
    for (int i = 0; i < size; i++) {

      if (contacts[i].split(",")[1].equals(email)) { // 예) "u1@test.com"
        return contacts[i];
      }
    }
    return "";
  }

  @RequestMapping("/contact/update")
  public Object update(String name, String email, String tel, String company) {
    String contact = name + "," + email + "," + tel + "," + company;
    for (int i = 0; i < size; i++) {
      if (contacts[i].split(",")[1].equals(email)) { 
        contacts[i] = contact;
        return 1;
      }
    }

    return 0;
  }

  @RequestMapping("/contact/delete")
  public Object delete(String email) {
    for (int i = 0; i < size; i++) {
      if (contacts[i].split(",")[1].equals(email)) { // 예) "u1@test.com"
        // 현재 위치의 다음 항목에서 배열 끝까지 반복하며 앞으로 값을 당겨온다.
        for (int j = i + 1; j < size; j++) {
          contacts[j - 1] = contacts[j];
        }
        size--;
        return 1;
      }
    }
    return 0;
  }
}

다음의 코드를 리팩토링할때 다음의 과정을 거친다.

1) 한 사람의 연락처 정보를 문자열로 만드는 코드를 메서드로 분리한다.

  • ContactController.createCSV() 정의
  String createCSV(String name, String email, String tel, String company) {
    return name + "," + email + "," + tel + "," + company;
  }
  • add() 변경
  @RequestMapping("/contact/add")
  public Object add(String name, String email, String tel, String company) {
    contacts[size++] = createCSV(name, email, tel, company);
    return size;
  }
  • update() 변경
  @RequestMapping("/contact/update")
  public Object update(String name, String email, String tel, String company) {
    for (int i = 0; i < size; i++) {
      if (contacts[i].split(",")[1].equals(email)) { 
        contacts[i] = createCSV(name, email, tel, company);
        return 1;
      }
    }

    return 0;
  }

2) 이메일로 연락처를 찾아 배열 인덱스를 알아내는 코드를 분리한다.

  • ContactController.indexOf() 정의
int indexOf(String email) {
    for (int i = 0; i < size; i++) {
      if (contacts[i].split(",")[1].equals(email)) { 
        return i;
      }
    }
    return -1;
  }
  • get() 변경
  @RequestMapping("/contact/get")
  public Object get(String email) {
    int index = indexOf(email);
    if (index == -1) {
      return "";
    }
    

    return contacts[index];
  }
  • update() 변경
  public Object update(String name, String email, String tel, String company) {
    int index = indexOf(email);
    if (index == -1) {
      return 0;
    }

    contacts[index] = createCSV(name, email, tel, company);
    return 1;
  }

3) 배열 항목 삭제 코드를 분리한다.

코드 기능을 명확하게 설명하고 싶을 때도 메서드를 활용하여 코드를 분리한다.

  • ContactController.remove() 정의
 String remove(int index) {
    String old = contacts[index];
    for (int i = index + 1; i < size; i++) {
      contacts[i - 1] = contacts[i];
    }
    size--;
    return old;
  }
  • delete() 변경
  @RequestMapping("/contact/delete")
  public Object delete(String email) {
    int index = indexOf(email);
    if (index == -1) {
      return 0;
    }

    remove(index);
    return 1;
  }

4) 배열 크기를 자동으로 늘린다.

  • ContactController.add() 변경
    • 배열이 꽉차면 새 배열을 만들어 확장한다.
  @RequestMapping("/contact/add")
  public Object add(String name, String email, String tel, String company) {
    if (size == contacts.length) { // 배열이 꽉찼다면,
      // 기존 배열 보다 50% 큰 배열을 새로 만든다.
      int newCapacity = contacts.length + (contacts.length >> 1);
      String[] arr = new String[newCapacity];

      // 기존 배열의 값을 새 배열로 복사한다.
      for (int i = 0; i < contacts.length; i++) {
        arr[i] = contacts[i];
      }

      // 기존 배열 대신 새 배열을 연락처 저장 배열로 사용한다.
      contacts = arr;
    }
    contacts[size++] = createCSV(name, email, tel, company);
    return size;
  }

5) 배열 크기를 늘리는 코드를 별도의 메서드로 분리한다.

코드 기능을 명확하게 설명하고 싶을 때도 메서드를 활용하여 코드를 분리한다.

  • ContactController.grow() 생성
  String[] grow() {
    // 기존 배열 보다 50% 큰 배열을 새로 만든다.
    int newCapacity = contacts.length + (contacts.length >> 1);
    String[] arr = new String[newCapacity];

    // 기존 배열의 값을 새 배열로 복사한다.
    for (int i = 0; i < contacts.length; i++) {
      arr[i] = contacts[i];
    }
    return arr;
  }
  • add() 변경
@RequestMapping("/contact/add")
  public Object add(String name, String email, String tel, String company) {
    if (size == contacts.length) { // 배열이 꽉찼다면,
      contacts = grow(); // 메서드 이름에서 해당 코드에 대한 설명을 짐작할 수 있다.
    }
    contacts[size++] = createCSV(name, email, tel, company);
    return size;
  }

6) 배열 크기를 계산하는 코드를 별도의 메서드로 분리한다.

코드 기능을 명확하게 설명하고 싶을 때도 메서드를 활용하여 코드를 분리한다.

  • ContactController.newLength() 생성
  // 기능:
  // - 주어진 배열에 대해 50% 증가시킨 새 배열의 길이를 알려준다.
  //
  int newLength() {
    return contacts.length + (contacts.length >> 1);
  }
  • grow() 변경
  String[] grow() {
    String[] arr = new String[newLength()];

    // 기존 배열의 값을 새 배열로 복사한다.
    for (int i = 0; i < contacts.length; i++) {
      arr[i] = contacts[i];
    }
    return arr;
  }

7) 배열을 복사하는 코드를 메서드로 분리한다.

코드 기능을 명확하게 설명하고 싶을 때도 메서드를 활용하여 코드를 분리한다.

  • ContactController.copy() 생성
 // 기능: 
  // - 배열을 복사한다.
  // 
  void copy(String[] source, String[] target) {
    // 개발자가 잘못 사용할 것을 대비해서 다음 코드를 추가한다.
    // 즉 target 배열이 source 배열 보다 작을 경우 target 배열 크기만큼만 복사한다.
    int length = source.length;
    if (target.length < source.length) {
      length = target.length;
    }
    for (int i = 0; i < length; i++) {
      target[i] = source[i];
    }
  }
  • grow() 변경
  String[] grow() {
    String[] arr = new String[newLength()];
    copy(contacts, arr);
    return arr;
  }

8) 완성된 코드

package com.eomcs.mylist;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController 
public class ContactController {

  String[] contacts = new String[5];
  int size = 0;

  @RequestMapping("/contact/list")
  public Object list() {
    String[] arr = new String[size]; 
    for (int i = 0; i < size; i++) { 
      arr[i] = contacts[i]; 
    }
    return arr; 
  }

  @RequestMapping("/contact/add")
  public Object add(String name, String email, String tel, String company) {
    if (size == contacts.length) { // 배열이 꽉찼다면,
      contacts = grow(); // 메서드 이름에서 해당 코드에 대한 설명을 짐작할 수 있다.
    }
    contacts[size++] = createCSV(name, email, tel, company);
    return size;
  }

  @RequestMapping("/contact/get")
  public Object get(String email) {
    int index = indexOf(email);
    if (index == -1) {
      return "";
    }

    return contacts[index];
  }

  @RequestMapping("/contact/update")
  public Object update(String name, String email, String tel, String company) {
    int index = indexOf(email);
    if (index == -1) {
      return 0;
    }

    contacts[index] = createCSV(name, email, tel, company);
    return 1;
  }

  @RequestMapping("/contact/delete")
  public Object delete(String email) {
    int index = indexOf(email);
    if (index == -1) {
      return 0;
    }

    remove(index);  // 메서드 이름으로 코드의 의미를 짐작할 수 있다. 이것이 메서드로 분리하는 이유이다.
    return 1;
  }

  // 기능: 
  // - 입력 받은 파라미터 값을 가지고 CSV 형식으로 문자열을 만들어 준다.
  //
  String createCSV(String name, String email, String tel, String company) {
    return name + "," + email + "," + tel + "," + company;
  }

  // 기능:
  // - 이메일로 연락처 정보를 찾는다.
  // - 찾은 연락처의 배열 인덱스를 리턴한다.
  //
  int indexOf(String email) {
    for (int i = 0; i < size; i++) {
      if (contacts[i].split(",")[1].equals(email)) { 
        return i;
      }
    }
    return -1;
  }

  // 기능:
  // - 배열에서 지정한 항목을 삭제한다.
  //
  String remove(int index) {
    String old = contacts[index];
    for (int i = index + 1; i < size; i++) {
      contacts[i - 1] = contacts[i];
    }
    size--;
    return old;
  }

  // 기능:
  // - 배열의 크기를 늘린다.
  // - 기존 배열의 값을 복사해온다.
  //
  String[] grow() {
    String[] arr = new String[newLength()];
    copy(contacts, arr);
    return arr;
  }

  // 기능:
  // - 주어진 배열에 대해 50% 증가시킨 새 배열의 길이를 알려준다.
  //
  int newLength() {
    return contacts.length + (contacts.length >> 1);
  }

  // 기능: 
  // - 배열을 복사한다.
  // 
  void copy(String[] source, String[] target) {
    // 개발자가 잘못 사용할 것을 대비해서 다음 코드를 추가한다.
    // 즉 target 배열이 source 배열 보다 작을 경우 target 배열 크기만큼만 복사한다.
    int length = source.length;
    if (target.length < source.length) {
      length = target.length;
    }
    for (int i = 0; i < length; i++) {
      target[i] = source[i];
    }
  }
}

9) 추가예시

https://github.com/InfraWhale/bitcamp-Study/tree/main/java-lang/app/src/main/java/com/eomcs/lang/ex07

Exam0110.java ~ Exam0130.java 참고

(3) 메서드

1) 개념 및 기본 문법

https://github.com/InfraWhale/bitcamp-Study/tree/main/java-lang/app/src/main/java/com/eomcs/lang/ex07

Exam0210.java ~ Exam0240.java 참고

2) 가변 파라미터

https://github.com/InfraWhale/bitcamp-Study/tree/main/java-lang/app/src/main/java/com/eomcs/lang/ex07

Exam0250.java ~ Exam0271.java 참고

3) 메서드 중첩 호출

https://github.com/InfraWhale/bitcamp-Study/tree/main/java-lang/app/src/main/java/com/eomcs/lang/ex07

Exam0280.java 참고

4) 메서드에서의 call by value

https://github.com/InfraWhale/bitcamp-Study/tree/main/java-lang/app/src/main/java/com/eomcs/lang/ex07

Exam0310.java 참고

4) 메서드에서의 call by reference

https://github.com/InfraWhale/bitcamp-Study/tree/main/java-lang/app/src/main/java/com/eomcs/lang/ex07

Exam0320.java ~ Exam0340.java 참고

5) JVM 메모리

https://github.com/InfraWhale/bitcamp-Study/tree/main/java-lang/app/src/main/java/com/eomcs/lang/ex07

Exam0410.java 참고

  • JVM과 메모리 영역

  • Exam0410 에서 클래스 실행 과정과 메모리 영역

6) Heap 메모리 영역

https://github.com/InfraWhale/bitcamp-Study/tree/main/java-lang/app/src/main/java/com/eomcs/lang/ex07

Exam0420.java, 0421.java 참고

  • JVM과 메모리 영역

  • Exam0420 에서 클래스 실행 과정과 메모리 영역

profile
끝없는 대양에서의 항해를 위해

0개의 댓글

Powered by GraphCDN, the GraphQL CDN