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

[FEAT]: 프로필 수정 api 구현 #62

Merged
merged 29 commits into from
Aug 5, 2023
Merged

[FEAT]: 프로필 수정 api 구현 #62

merged 29 commits into from
Aug 5, 2023

Conversation

twoosky
Copy link
Member

@twoosky twoosky commented Jul 31, 2023

Issue number

  • resolved #0

작업 사항

  • 프로필 정보 임베디드 타입으로 분리
  • 프로필 수정 api 구현

@twoosky twoosky self-assigned this Jul 31, 2023

@Entity
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
Copy link
Member Author

@twoosky twoosky Jul 31, 2023

Choose a reason for hiding this comment

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

Lombok을 사용해 equals, hashcode 를 재정의 했습니다.

@Column(name = "personality")
private List<Personality> personalities = new ArrayList<>();
@Embedded
private Profile profile;
Copy link
Member Author

Choose a reason for hiding this comment

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

유저의 프로필 관련 정보를 임베디드 타입으로 선언하였습니다. 이유는 프로필 수정 시 필드 업데이트 로직을 분리하기 위함입니다.

private String introduce;

@Convert(converter = EnumArrayConverter.class)
@Default
Copy link
Member Author

Choose a reason for hiding this comment

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

@builder 사용 시 초기값을 무시하기 때문에, @Builder.Default 어노테이션을 사용해 초기값을 설정해줬습니다.

@twoosky twoosky changed the title [Feat]: 프로필 수정 api 구현 [FEAT]: 프로필 수정 api 구현 Jul 31, 2023
@jihwan2da
Copy link
Member

수고하셨습니다!!
우선 코드를 전체적으로 본 결과 저는 아래 항목에 대해 지켜지지 않은거 같습니다!
아래 항목들을 지켜 좀 더 객체지향 및 안전한 코드를 짜보는건 어떨까요?!

  1. VO - 불변객체로 생성하자! 객체 생성 시 불변식 검증을 하도록 하자!@!
  2. 좀 더 선언적으로 코드를 짜보자!~!@

@Embeddable
@NoArgsConstructor
@AllArgsConstructor
public class Profile {
Copy link
Member

Choose a reason for hiding this comment

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

Profile이라는 개념을 따로 빼어 User내의 값 객체로 둔거는 좋은 것 같습니다.
하지만 값 객체는 가변성이 있을 경우 많은 문제 상황이 발생할 수 있습니다. 따라서 불변객체로 만드는 것을 지향합니다.
이를 setter 같은 함수를 사용하지 않고 불변객체로 만들어 보면 어떨까요?

또한 이 객체가 생성될 때 불변식을 검증하는 로직도 들어갔으면 좋겠습니다!!..
예를들어 Personality의 갯수는 3개여야 한다든가..등등....

Copy link
Member Author

Choose a reason for hiding this comment

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

불변객체 너무 좋네요. 사실 메모리 누수 문제로 고민하고 있었는데, 단점보다 장점이 더 큰거 같네요 바로 반영하겠습니다 🫡

기획 확인 후 불변식 검증도 반영해볼게요

Copy link
Member Author

Choose a reason for hiding this comment

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

validation을 활용해 request dto를 검증했습니다

  • personalities : 3개 이상
  • introduce : notBlank
  • name : notBlank

User user = userFindService.findById(userId);
Profile profile = user.getProfile();

profile.setProfile(
Copy link
Member

Choose a reason for hiding this comment

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

앞의 불변객체에 대한 수정 후 이 부분의 코드를 좀 더 선언적으로 작성하는 건 어떨까요?

UserUpdateService의 입장에서는 User에 대한 Profile어떻게 update 하는지에 대해서는 별로 궁금하지 않고, 무엇을 하는지에 대해서만 궁금할거에요. 이 부분은 1. user에서 profile을 찾고(user.getProfile()) 2. proflie을 update(profile.setProfile()) 하겠다라고 어떻게 하는지에 초점이 맞춰져 있는 것 같애요.

또한 Profile은 User내의 소속되어 있는 값 객체입니다. 이렇게 User 외부에 Profile을 명시적으로 처리하는 것은 캡슐화와 은닉화를 지키지 못한 것 같애요!(Profile에 대한 처리는 User 내부에서 처리하도록 해서 캡슐화 및 은닉화...! -> 외부에서는 user의 무엇을에만 관심이 있겠죠?!) 따라서 아래와 같이 수정하는 건 어떨까요???!?

user.updateProfile(request.getImageUrl, request.Name, ....);

updateProfile 메소드 내부에는 새로운 Profile 값 객체를 생성한 후 profile 필드 갈아 끼우는 로직...

Copy link
Member Author

Choose a reason for hiding this comment

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

Profile을 어떻게 update 하는지에 대해서는 별로 궁금하지 않고, 무엇을 하는지에 대해서만 궁금할거에요.

!! 오 너무나도 맞는말이네요. 프로필 데이터 업데이트 로직을 분리하는 것이 좋을거 같습니다.

그리고, 제 생각에는 user 내부에서 프로필 객체를 생성하고 업데이트하는 것 또한, 관심사 분리가 필요한거 같아요. 어떤 프로필인지는 궁금하지 않을거 같다는 생각입니다! (user.updateProfile 메소드 내 프로필 객체 생성 로직)

따라서, 프로필 업데이트에 대한 domain service를 생성해 domain service 내부에서 Profile 객체를 생성하고, user.updateProfile(Profile profile) 을 호출하는 것은 어떨까요?

Copy link
Member

@jihwan2da jihwan2da Aug 2, 2023

Choose a reason for hiding this comment

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

Profile객체는 불변객체이기 때문에 업데이트 에 대한 domain service는 따로 두지 말고 기존에 두었던 ProfileFactory domain service를 재활용하면 될 것 같습니다.

새로운 Profile 생성 -> User의 Profile 갈아 끼우기

이를 구현할 때는
Service단에 명시적으로 Profile은 생성한 후 user.updateProfile(proflie); 를 하는 방법이 있을 것 같구

// Service 단
Profile profile = profileFactory.create(profileDto);
user.updateProfile(profile);

Profile에 대한 노출을 외부(여기에서는 Servcie단 이겠죵?)에 시키지 않고 User 내부에서 새로운 Profile에 대한 생성을 처리할 수 있을 것 같습니다.(은닉화)

//Service 단
user.updateProfile(profileFactory, profileDto);

두개의 방법을 활용하거나 하늘님의 개인적으로 생각나는 방법으로 수정해주시구 그렇게 수정한 이유를 커멘트 달아주세용!@~

Copy link
Member Author

@twoosky twoosky Aug 5, 2023

Choose a reason for hiding this comment

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

user.updateProfile(profileFactory, profileDto)

위 코드의 경우, 관심사 분리의 목적과는 맞지 않다고 생각했어요. 제가 생각한 user의 관심사는 [user는 어떤 프로필 객체인지 궁금하지 않고, 프로필 필드를 교체하는 것에만 관심이 있다] 였습니다. 위 코드도 결과적으로는 user.updateProfile 메서드 내부에서 프로필 객체를 생성하기 때문에 관심사 분리의 목적과 맞지 않다고 생각했습니다.

하지만, 제가 생각하는 관심사 분리를 위해선 profile 값 객체가 외부에 노출되어야 했고, 지환님이 말씀해주신 것처럼 은닉화 및 캡슐화에 위배되는 로직이 될 수 밖에 없다고 생각했어요.

따라서 관심사 분리보다는 캡슐화, 은닉화가 객체지향 프로그래밍에서 더 중요한 개념이라고 생각해 아래와 같이 수정했습니다.

public void updateProfile(String imageUrl, String nickname, LocalDate birth,
                              Gender gender, String introduce, List<Personality> personalities
  ) {
      this.profile = Profile.builder()
              .imageUrl(imageUrl)
              .nickname(nickname)
              .birth(birth)
              .gender(gender)
              .introduce(introduce)
              .personalities(personalities)
              .build();
  }

사실 맨 처음 지환님이 제안한 코드입니다 ㅎㅎㅎ
덕분에 객체지향 프로그래밍에 대해 더 깊게 고민해볼 수 있었어요 ~~~!
감사합니다 머지 고?

Copy link
Member

Choose a reason for hiding this comment

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

고고~

@twoosky twoosky merged commit f0b604a into dev Aug 5, 2023
1 check passed
@jihwan2da jihwan2da deleted the feature/update-profile branch August 30, 2023 18:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants