Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[사다리 타기] 방예혁 미션 제출합니다. #3

Open
wants to merge 28 commits into
base: YehyeokBang
Choose a base branch
from

Conversation

YehyeokBang
Copy link

@YehyeokBang YehyeokBang commented May 11, 2024

우리가 생각한 사다리

  • 하나의 행(가로 줄)은 여러 개의 연결로 이루어져 있고, 사다리는 여러 개의 행으로 이루어져 있다.

우리가 미션을 진행한 방식

  1. 구현을 위해 우리가 필요하다고 생각하는 객체를 먼저 설계
  2. 필요한 클래스를 생성하고 바로 해당 클래스로 만들어질 객체가 담당하게 될 기능 테스트를 먼저 작성 후 커밋
  3. 테스트를 통과하도록 클래스를 작성 후 커밋
  4. 차례를 돌려가면서 2-3 과정을 반복

어려웠던 부분

  • 해당 객체가 어떤 기능을 담당해야 하고, 스스로 할 수 없는 일들 중 필요한 것(행위, 값)을 얻기 위해서 다른 객체에게 메시지(호출 등)를 전달하는 흐름을 설계하는 것이 가장 어려웠습니다.

가장 많은 고민을 한 부분

  • 이번 미션에서는 랜덤으로 사다리를 생성하지만 가로로 연속되면 안되는 것이 기준이었습니다. 그래서 추후 변경 가능성을 생각하면서 "연결을 담당하는 부분"을 생성 전략으로 만들어서 어떤 기준이 추가 되어도 전략에 맞게 사다리를 생성할 수 있게 구현했습니다.
  • 행은 정해진 생성 전략과 인원 수에 맞춰서 가로 줄을 담당하고, 사다리는 높이 수에 맞춰서 행을 생성하게 시키도록 설계했습니다.

결과

image
  • 출력에 대한 규칙은 없어서 같은 간격 기준을 만들어서 출력하도록 구현했습니다. 많은 사람이 참여해도 같은 갭을 가집니다.

리뷰 후 개선 사항

  • 중복된 이름을 가진 참가자가 있는지 확인하는 로직을 개선했습니다.
    • 기존 Stream을 활용하여 모든 이름을 그룹핑한 후 카운팅하여 중복된 이름이 있는지 확인(항상 모든 이름을 확인해야 함)하던 로직을 Set 자료구조와 for 문을 활용하여 중복된 이름이 발견될 경우 즉시 예외를 발생시키도록 수정했습니다.
  • 참가자 클래스의 생성자가 모든 검증 로직을 알고 있던 상황에서 메서드 분리를 통해 검증을 한다는 것만 알도록 수정했습니다.
  • 어떠한 상황에서도 해당 객체의 행위를 테스트가 가능하도록 개선했습니다.
    • 값이 고정된 연결 정보로 행이 생성되면 고정된 값으로 생성되는지 확인
      -> 랜덤하게 생성된 연결 정보로 행이 생성되어도 동일하게 생성되는지 확인
  • 재사용성이 매우 낮고 과도한 분리라고 판단된 메서드를 제거했습니다.

기타

validation에 관련한 함수들은 View쪽에 처리하는 것이 적합해 보여요. MVC 패턴을 기준으로 봤을때 뷰단에서 처리 못한 에러가 model까지 가게되면 예상치 못한 문제가 발생할 수 있지 않을까요?

저는 모델의 정합성을 높이기 위해 스스로 검증하고 생성되는 것이 좋다고 생각했었습니다.

MVC 패턴에서 데이터의 무결성을 유지하는 것은 매우 중요한 과제인 것은 분명합니다.
이번 과제에서는 모델을 만들기 위한 뷰가 하나이기 때문에 어디서 하더라도 어렵지 않게 정합성을 유지할 수 있을 것 같다고 생각합니다. 하지만 모델이 여러 뷰와 컨트롤러에서 사용될 때, 각 뷰와 컨트롤러에서 검증을 반복하는 것보다는 모델 자체에서 검증을 수행함으로써 모델의 일관성을 보장할 수 있다고 생각했습니다.

물론, 뷰에서도 기본적인 입력 검증을 수행하여 모델 레이어 자체에 예상하지 못한 값이 전달되지 않도록 하는 것도 좋은 것 같습니다. 하지만 View와 Model 모두에서 검증을 수행할 때 개발자의 실수로 검증 조건에 모순이 생길 수도 있다고 판단하여 모델의 정합성을 최종적으로 보장하는 역할은 모델 자체가 담당하는 것이 좋다고 생각했었습니다.

위 주제와 관련된 다른 의견도 듣고 싶습니다!

YehyeokBang and others added 21 commits May 8, 2024 15:12
- 참여자 생성자를 protected로 변경합니다.
- 이름 목록을 받아서 참여자를 생성하고 관리합니다.
- 랜덤으로 생성되는 값을 테스트 할 수 없기 때문에, 생성전략을 상속받아 고정된 값으로 테스트 할 수 있도록 도움
- 사람의 수를 받아 Boolean타입의 리스트를 반환하는 메소드를 가진다.
- 다리가 문제의 규칙을 여기지 않으며 생성되지 않는지 확인
- 0과 1을 랜덤으로 생성하여 0이면 false, 1이면 true 반환하는 메소드
- 이전에 다리가 연결된적 있는지 확인하는 메소드
- 위 2개 메소드를 활용하여 다리 생성 여부를 가지고 있는 Boolean타입 리스트 반환
- 생성 전략을 활용하여 행 생성
- 읽기 쉽게 변수명을 수정합니다.
- 더 의미있는 테스트를 할 수 있게 수정합니다.
- 관심사 기준으로 패키징합니다.
- 사다리가 알고 있는 행의 정보들을 반환합니다.
- 관련 모델과 화면을 사용하여 사다리 게임을 구현합니다.
- 구현한 기능 목록 체크
@YehyeokBang YehyeokBang marked this pull request as draft May 18, 2024 14:26
@YehyeokBang YehyeokBang marked this pull request as ready for review May 18, 2024 17:38
Copy link
Collaborator

@HanHyunsoo HanHyunsoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨어요! 리뷰 남겼으니 확인하시고 수정해주세요~

어려운 부분에 대한 답변

  • 해당 객체가 어떤 기능을 담당해야 하고, 스스로 할 수 없는 일들 중 필요한 것(행위, 값)을 얻기 위해서 다른 객체에게 메시지(호출 등)를 전달하는 흐름을 설계하는 것이 가장 어려웠습니다.
    • 다른 객체의 정보를 얻기 위한 방법으로 다양한 방법이 있지만 대표적으로 디자인 패턴 중 옵저버 패턴이 생각이 나네요. 한번 찾아보시면 좋을 듯 합니다 :)

}
}

private static String removeBlank(String input) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 함수는 재사용성이 크게 높지는 않은 것 같아요. 함수 내에서 사용하도록 변경해주는게 더 좋을 것 같습니다.

return input.replaceAll(" ", "");
}

private static List<String> split(String input) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removeBlank와 동일한 의견입니다.


import java.util.List;

public class OutputView {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전체적으로 봤을때 println 메서드가 많이 호출되네요 그만큼 출력 리소스에 대해 많이 발생하니 문자열로 정리한다음 하나의 출력으로 하는 것이 좀더 좋을 것 같아요.

(좀더 쉽게 설명하자면 백준 문제에서 다량의 출력을 할 경우 print를 여러번 할 시 시간 초과가 나는 것)

return bridges;
}

private static boolean wasPreviousBridgeConnected(List<Boolean> bridges, int currentIndex) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static을 쓴 이유가 있을까요? 이 클래스에서는 불필요해보여요.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여러 방법으로 구현해보다가 빼먹은 것 같습니다! 아래의 decideBridgeConnection() 처럼 static을 제거하여 인스턴스 메서드로 수정하겠습니다!

return name;
}

private void checkNameIsNotNull(String name) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validation에 관련한 함수들은 View쪽에 처리하는 것이 적합해 보여요. MVC 패턴을 기준으로 봤을때 뷰단에서 처리 못한 에러가 model까지 가게되면 예상치 못한 문제가 발생할 수 있지 않을까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 모델의 정합성을 높이기 위해 스스로 검증하고 생성되는 것이 좋다고 생각했었습니다.

MVC 패턴에서 데이터의 무결성을 유지하는 것은 매우 중요한 과제인 것은 분명합니다.
이번 과제에서는 모델을 만들기 위한 뷰가 하나이기 때문에 어디서 하더라도 어렵지 않게 정합성을 유지할 수 있을 것 같다고 생각합니다. 하지만 모델이 여러 뷰와 컨트롤러에서 사용될 때, 각 뷰와 컨트롤러에서 검증을 반복하는 것보다는 모델 자체에서 검증을 수행함으로써 모델의 일관성을 보장할 수 있다고 생각했습니다.

물론, 뷰에서도 기본적인 입력 검증을 수행하여 모델 레이어 자체에 예상하지 못한 값이 전달되지 않도록 하는 것도 좋은 것 같습니다. 하지만 View와 Model 모두에서 검증을 수행할 때 개발자의 실수로 검증 조건에 모순이 생길 수도 있다고 판단하여 모델의 정합성을 최종적으로 보장하는 역할은 모델 자체가 담당하는 것이 좋다고 생각했었습니다.

@DisplayName("정해진 다리 생성 전략에 따라 행 객체 생성")
void should_CreateCorrectSizeRow() {
// given
FixedGenerateStrategy fixedGenerateStrategy = new FixedGenerateStrategy(List.of(true, false, true));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 테스트 코드를 봤을때 상황이 true, false, true 일때만 판단되서 그 외의 경우에는 테스트가 성공할까? 라는 고민이 들어요

테스트를 진행할때 입력에 대한 것은 모든 상황을 고려한 랜덤한 값으로 진행하여 그 상황이 전부 정상적으로 동작(or 예외처리)하는 경우로 생각하면 더 정확한 테스트 코드가 될 것 같아요

Copy link
Author

@YehyeokBang YehyeokBang May 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

일단 해당 테스트는 정해진 생성 전략에 따라 행 객체를 생성하는 부분을 보고 싶었습니다.
그래서 개발자가 지정한 연결 내용 List에 따라 연결 정보를 만드는 전략을 만들어서
지정한 값에 맞게 행 객체를 올바르게 생성했는지를 보려고 했습니다.
모든 전략은 GenerateStrategy 인터페이스를 구현하여 같은 시그니처를 가진 메서드를 구현해야 하고,
구현된 메서드를 통해 연결 정보를 만들기 때문에 이렇게 하면 생성 전략에 맞게 행 객체가 잘 생성되는지 확인할 수 있다고 생각했었습니다.

해당 테스트 코드를 봤을때 상황이 true, false, true 일때만 판단되서 그 외의 경우에는 테스트가 성공할까?

다시 한번 테스트 코드만 봤을 때는 커버리지에 대한 의문이 드는 것 같습니다. 다양한 입력 상황을 고려하여 테스트를 작성하여 테스트의 신뢰도를 높이는 것이 중요한 것 같습니다. 말씀해주신 방법으로 고민해보겠습니다!

Copy link
Author

@YehyeokBang YehyeokBang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

다른 객체의 정보를 얻기 위한 방법으로 다양한 방법이 있지만 대표적으로 디자인 패턴 중 옵저버 패턴이 생각이 나네요. 한번 찾아보시면 좋을 듯 합니다 :)

학습해보겠습니다. 리뷰를 위해 시간 내주셔서 감사합니다!

return bridges;
}

private static boolean wasPreviousBridgeConnected(List<Boolean> bridges, int currentIndex) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여러 방법으로 구현해보다가 빼먹은 것 같습니다! 아래의 decideBridgeConnection() 처럼 static을 제거하여 인스턴스 메서드로 수정하겠습니다!

return name;
}

private void checkNameIsNotNull(String name) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 모델의 정합성을 높이기 위해 스스로 검증하고 생성되는 것이 좋다고 생각했었습니다.

MVC 패턴에서 데이터의 무결성을 유지하는 것은 매우 중요한 과제인 것은 분명합니다.
이번 과제에서는 모델을 만들기 위한 뷰가 하나이기 때문에 어디서 하더라도 어렵지 않게 정합성을 유지할 수 있을 것 같다고 생각합니다. 하지만 모델이 여러 뷰와 컨트롤러에서 사용될 때, 각 뷰와 컨트롤러에서 검증을 반복하는 것보다는 모델 자체에서 검증을 수행함으로써 모델의 일관성을 보장할 수 있다고 생각했습니다.

물론, 뷰에서도 기본적인 입력 검증을 수행하여 모델 레이어 자체에 예상하지 못한 값이 전달되지 않도록 하는 것도 좋은 것 같습니다. 하지만 View와 Model 모두에서 검증을 수행할 때 개발자의 실수로 검증 조건에 모순이 생길 수도 있다고 판단하여 모델의 정합성을 최종적으로 보장하는 역할은 모델 자체가 담당하는 것이 좋다고 생각했었습니다.

@DisplayName("정해진 다리 생성 전략에 따라 행 객체 생성")
void should_CreateCorrectSizeRow() {
// given
FixedGenerateStrategy fixedGenerateStrategy = new FixedGenerateStrategy(List.of(true, false, true));
Copy link
Author

@YehyeokBang YehyeokBang May 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

일단 해당 테스트는 정해진 생성 전략에 따라 행 객체를 생성하는 부분을 보고 싶었습니다.
그래서 개발자가 지정한 연결 내용 List에 따라 연결 정보를 만드는 전략을 만들어서
지정한 값에 맞게 행 객체를 올바르게 생성했는지를 보려고 했습니다.
모든 전략은 GenerateStrategy 인터페이스를 구현하여 같은 시그니처를 가진 메서드를 구현해야 하고,
구현된 메서드를 통해 연결 정보를 만들기 때문에 이렇게 하면 생성 전략에 맞게 행 객체가 잘 생성되는지 확인할 수 있다고 생각했었습니다.

해당 테스트 코드를 봤을때 상황이 true, false, true 일때만 판단되서 그 외의 경우에는 테스트가 성공할까?

다시 한번 테스트 코드만 봤을 때는 커버리지에 대한 의문이 드는 것 같습니다. 다양한 입력 상황을 고려하여 테스트를 작성하여 테스트의 신뢰도를 높이는 것이 중요한 것 같습니다. 말씀해주신 방법으로 고민해보겠습니다!

- 재사용성이 낮고 과도한 메서드 분리라고 생각하는 부분을 수정합니다.
- 기존 정해진 값으로 테스트를 진행하여 다른 상황에 대한 의문이 들었습니다.
- 랜덤한 값으로 수정하여 어떤 경우라도 정상적으로 작동하는 것을 알 수 있도록 수정합니다.
- 기존에는 Stream을 활용하여 모든 이름을 확인한 후 중복을 검증했습니다.
- Set 자료구조와 for 문을 활용하여 중복된 이름 발견 시 즉시 예외를 던지도록 개선합니다.
- 생성자가 모든 검증 메서드 대신 검증을 한다는 것만 알도록 수정합니다.
- 모호한 메서드명 직관적으로 수정합니다.
- 고정 생성 전략을 사용하여 테스트 신뢰도를 향상시킵니다.
- StringBuilder를 사용하여 출력 내용을 버퍼링하도록 수정합니다.
@YehyeokBang
Copy link
Author

개선 사항

  • 중복된 이름을 가진 참가자가 있는지 확인하는 로직을 개선했습니다.
    • 기존 Stream을 활용하여 모든 이름을 그룹핑한 후 카운팅하여 중복된 이름이 있는지 확인(항상 모든 이름을 확인해야 함)하던 로직을 Set 자료구조와 for 문을 활용하여 중복된 이름이 발견될 경우 즉시 예외를 발생시키도록 수정했습니다.
  • 참가자 클래스의 생성자가 모든 검증 로직을 알고 있던 상황에서 메서드 분리를 통해 검증을 한다는 것만 알도록 수정했습니다.
  • 어떠한 상황에서도 해당 객체의 행위를 테스트가 가능하도록 개선했습니다.
    • 값이 고정된 연결 정보로 행이 생성되면 고정된 값으로 생성되는지 확인
      -> 랜덤하게 생성된 연결 정보로 행이 생성되어도 동일하게 생성되는지 확인
  • 재사용성이 매우 낮고 과도한 분리라고 판단된 메서드를 제거했습니다.

기타

validation에 관련한 함수들은 View쪽에 처리하는 것이 적합해 보여요. MVC 패턴을 기준으로 봤을때 뷰단에서 처리 못한 에러가 model까지 가게되면 예상치 못한 문제가 발생할 수 있지 않을까요?

저는 모델의 정합성을 높이기 위해 스스로 검증하고 생성되는 것이 좋다고 생각했었습니다.

MVC 패턴에서 데이터의 무결성을 유지하는 것은 매우 중요한 과제인 것은 분명합니다.
이번 과제에서는 모델을 만들기 위한 뷰가 하나이기 때문에 어디서 하더라도 어렵지 않게 정합성을 유지할 수 있을 것 같다고 생각합니다. 하지만 모델이 여러 뷰와 컨트롤러에서 사용될 때, 각 뷰와 컨트롤러에서 검증을 반복하는 것보다는 모델 자체에서 검증을 수행함으로써 모델의 일관성을 보장할 수 있다고 생각했습니다.

물론, 뷰에서도 기본적인 입력 검증을 수행하여 모델 레이어 자체에 예상하지 못한 값이 전달되지 않도록 하는 것도 좋은 것 같습니다. 하지만 View와 Model 모두에서 검증을 수행할 때 개발자의 실수로 검증 조건에 모순이 생길 수도 있다고 판단하여 모델의 정합성을 최종적으로 보장하는 역할은 모델 자체가 담당하는 것이 좋다고 생각했었습니다.

위 주제와 관련된 다른 의견도 듣고 싶습니다!

@YehyeokBang YehyeokBang requested a review from HanHyunsoo May 21, 2024 05:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants