Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 25 additions & 6 deletions src/main/java/webserver/http/attribute/Attributes.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,55 @@ public static Attributes from(Map<String, String> attributes) {
}

public static Attributes from(String headerText) {
Map<String, String> attributes = new LinkedHashMap<>();
Attributes attributes = new Attributes();

String[] splittedHeaderTexts = headerText.split(Const.CRLF);
for (String splittedHeaderText : splittedHeaderTexts) {
HttpRequestUtils.Pair pair = HttpRequestUtils.parseHeader(splittedHeaderText);

if (pair != null) {
attributes.put(pair.getKey(), pair.getValue());
attributes.add(pair.getKey(), pair.getValue());
}
}

return from(attributes);
return attributes;
}

public Attributes add(String key, String value) {
for (String k : attributes.keySet()) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

직접 사용할 변수면 명시적으로 이름을 짓는 것도 좋아보여요
eachKey currentKey 같은거라도 좋을 것 같고
그게 힘들면 매개변수 이름을 targetKey 같은 걸로 나눠줘도 좋을 것 같습니다.

Copy link
Owner Author

Choose a reason for hiding this comment

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

앗.. 너무 막지었네요.
지적 감사합니다.

if (k.equalsIgnoreCase(key)) {
return this;
}
}

attributes.put(key, value);
return this;
}

public Attributes addAll(Map<String, String> attributes) {
this.attributes.putAll(attributes);
for (String key : attributes.keySet()) {
add(key, attributes.get(key));
}

return this;
}

public String get(String key) {
return attributes.get(key);
for (String k : attributes.keySet()) {
if (k.equalsIgnoreCase(key)) {
return attributes.get(k);
}
}
return null;
Copy link
Owner Author

Choose a reason for hiding this comment

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

null이 조금 걸리네요..ㅎㅎ

Copy link
Owner Author

Choose a reason for hiding this comment

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

exception
null을 받아야할 이유가 있다면: optional

Copy link
Collaborator

Choose a reason for hiding this comment

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

getDefault가 있는데 굳이 null을 리턴해줄 필요는 없다고 보여집니다.
꼭 써야한다면 Optional로 제공해주는 것도 고려해볼 수 있을 것 같아요

Copy link
Collaborator

Choose a reason for hiding this comment

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

그리고 null을 명시적으로 리턴해준다면 get이 null인 케이스도 테스트에서 확인을 해봐야할 것 같습니다!

Copy link
Owner Author

@sanhee sanhee Dec 10, 2021

Choose a reason for hiding this comment

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

이부분 작성하면서도 이상하다 생각했는데 감사합니다!

}

public String getOrDefault(String key, String defaultValue) {
return attributes.getOrDefault(key, defaultValue);
for (String k : attributes.keySet()) {
if (k.equalsIgnoreCase(key)) {
return attributes.get(k);
}
}
return defaultValue;
Copy link
Collaborator

Choose a reason for hiding this comment

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

코드 중복이 되는데 get이나 getOrDefault 둘 중 하나를 기준으로 중복 제거를 해볼 수 있겠네요

}

public String toHeaderText() {
Expand Down
19 changes: 14 additions & 5 deletions src/main/java/webserver/http/statusline/RequestStatusLine.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package webserver.http.statusline;

import webserver.http.attribute.Attributes;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.StringJoiner;

public class RequestStatusLine extends StatusLine {

Expand All @@ -13,12 +18,16 @@ public RequestStatusLine(Map<String, String> statusLineAttributes) {
super(statusLineAttributes);
}

public RequestStatusLine(Attributes statusLineAttributes) {
super(statusLineAttributes);
}

public static RequestStatusLine from(List<String> statusLine) {
Map<String, String> statusLineAttributes = new HashMap<>();
Attributes statusLineAttributes = new Attributes();

statusLineAttributes.put(METHOD_KEY, statusLine.get(0));
statusLineAttributes.put(PATH_KEY, statusLine.get(1));
statusLineAttributes.put(PROTOCOL_VERSION_KEY, statusLine.get(2));
statusLineAttributes.add(METHOD_KEY, statusLine.get(0));
statusLineAttributes.add(PATH_KEY, statusLine.get(1));
statusLineAttributes.add(PROTOCOL_VERSION_KEY, statusLine.get(2));
Comment on lines +26 to +
Copy link
Collaborator

Choose a reason for hiding this comment

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

이 부분도 Attributes를 만들면서 자연스럽게 검증이 될 테니 Map으로 받아줘도 괜찮을 것 같아요

Copy link
Collaborator

Choose a reason for hiding this comment

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

그게 아니라 생성자로 Attributes를 넣어주는게 더 바람직하다고 생각하신거면 좋은 방법인 것 같습니다
만약 그렇다면 Map<String, String>을 받는 생성자를 완전히 대체해주는게 좋을 것 같습니다.


return new RequestStatusLine(statusLineAttributes);
}
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/webserver/http/statusline/StatusLine.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ public StatusLine(Map<String, String> statusLineAttributes) {
this.statusLineAttributes = Attributes.from(statusLineAttributes);
}

public StatusLine(Attributes statusLineAttributes) {
this.statusLineAttributes = statusLineAttributes;
}

public String getProtocol() {
return statusLineAttributes.get(PROTOCOL_VERSION_KEY);
}
Expand Down
17 changes: 16 additions & 1 deletion src/test/java/webserver/http/attribute/AttributesTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package webserver.http.attribute;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
Expand All @@ -11,6 +12,8 @@
import java.util.stream.Stream;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;

class AttributesTest {

Expand Down Expand Up @@ -40,12 +43,20 @@ void fromHeaderText() {
}

@Test
@DisplayName("add 테스트: key의 대소문자 관계 없이 Attributes를 꺼내올 수 있음")
void add() {
Attributes attributes = new Attributes();
attributes.add("key", "value");

assertAll(
() -> assertEquals("value", attributes.get("KEY")),
() -> assertEquals("value", attributes.get("key")),
() -> assertEquals("value", attributes.get("kEy"))
);
Copy link
Collaborator

Choose a reason for hiding this comment

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

한 번에 여러개의 케이스를 테스트 하는 것 보다는 매개변수화 시키는게 더 좋을 것 같습니다

Copy link
Owner Author

Choose a reason for hiding this comment

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

혹시 매개변수화 시켜서 테스트를 하면 어떤 장점이 있는건가요??
아직 정확하게 와닿지 못해서 이런 방식으로 작성했습니다!

Copy link
Collaborator

Choose a reason for hiding this comment

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

기본적으로 저는 assertAll은 같은 테스트에 대한 그룹을 묶어주는 것이라 생각했습니다. 예를 들어 검증해야 될 객체에 여러개의 필드가 들어있고 각각 검증을 해야 하는 상황이라면 묶어주는게 의미가 있을거라 생각합니다.
하지만, assertAll로 여러개의 테스트 케이스를 묶어주면 여러개의 테스트가 하나의 테스트 안에 들어가있는 느낌이라 좋지 못하다고 생각한 것 같습니다. 기본적으로 하나의 테스트는 한 가지 테스트를 수행하는게 가장 좋다고 알고 있기 때문입니다.
마지막으로 가독성에 대한건 개인 취향이긴 한데, RequestHandlerTest에 있는 케이스들을 저런 식으로 처리한다면 가독성이 매우 떨어질 것 같습니다.

}

@Test
@DisplayName("addAll 테스트: key의 대소문자 관계 없이 Attributes를 꺼내올 수 있음")
void addAll() {
Attributes attributes = new Attributes();
Map<String, String> attributeMap = new LinkedHashMap<>();
Expand All @@ -55,7 +66,11 @@ void addAll() {
Attributes expectedAttributes = new Attributes();
expectedAttributes.add("key", "value");

assertThat(attributes).isEqualTo(expectedAttributes);
assertAll(
() -> assertEquals(expectedAttributes.get("key"), attributes.get("KEY")),
() -> assertEquals(expectedAttributes.get("KEY"), attributes.get("kEY")),
() -> assertEquals(expectedAttributes.get("kEy"), attributes.get("key"))
Copy link
Collaborator

Choose a reason for hiding this comment

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

키가 중복돼서 들어가지 않는 케이스를 추가해주는게 좋을 것 같습니다

Copy link
Collaborator

Choose a reason for hiding this comment

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

size같은걸로 검증해볼 수 있을 것 같네요

Copy link
Owner Author

Choose a reason for hiding this comment

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

예외상황 추가해주셔서 감사합니다!

);
}

@Test
Expand Down