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

[산타] 미니언 미션 제출합니다. #13

Open
wants to merge 2 commits into
base: gusah009-main
Choose a base branch
from

Conversation

gusah009
Copy link
Collaborator

@gusah009 gusah009 commented Feb 24, 2024

구현하면서 고민되었던 점

스프링을 사용하지 않다 보니 스프링처럼 사용하기 위해 injection을 사용하다가 생기는 여러 boiler plate 코드가 걱정이었는데, 코틀린에서 제공해주는 object를 쓰니까 훨씬 간결해지네요. 그런데 좋은 패턴인진 모르겠습니다 ㅎㅎ... 실제로 실무에서도 익명 객체 외에 object를 사용한 케이스는 못 본 것 같아요. (거기선 스프링을 쓰다 보니까...?)

처음에 이벤트 정책들이나 메뉴들을 sealed class로 사용하려고 했는데, 그러다 보니 sealed class를 구현하고 있는 구현 객체들을 가져 올 때 reflection 외에 방법이 없더라구요... 근데 문제 조건에 라이브러리 추가는 안돼서 reflection을 사용 못했기 때문에 enum 객체로 모두 바꿔버렸습니다. 혹시 sealed class로 사용하신 분들 계시면 코드 한 번 보고 싶네용

객체지향적으로 짜다 보니 클래스는 줄어들고 Controller, Service 코드는 눈에 띄게 줄었는데 도메인 객체들의 코드량이 완전 뻠핑됐습니다... 이 코드가 전부 Service에 있었다고 생각하면 쳐다도 보기 싫을 것 같긴 한데, 도메인 코드가 엄청 커지니 도메인 코드를 쳐다 보기 싫어지네요. 다른 분들은 어떻게 했는 지도 궁금합니다.

(금액)이라는 도메인이 양수와 음수를 넘나들어서 너무 힘들었습니다... 때문에 막판에 상수로 넣었던 Int형들을 모두 Price value class로 만들어서 치환해줬습니다. 이 과정에서 operator도 써봐서 좋았는데 이게 어디까지 operator를 구현해야 할 지도 고민이더라구요...

enum에 한글 객체를 만들 수 있어서 작명을 더 고민하지 않아도 되어서 좋았습니다.

자랑스러운점

3번째 과제만에 드디어 테스트 코드를 짰습니다!

코드를 다 짜고 테스트 없이 딱 돌려봤을 때 README의 예시랑 똑같이 나올 때 그 쾌감... 짜릿하네요 👍👍

각 도메인 객체를 역할과 책임에 맞게 잘 분리한 것 같습니다.

죄송한점

모킹이 너무 하고싶어서 라이브러리를 추가해버렸습니다...

내일 일정이 있어서 오늘 급하게 PR을 올립니다~!

@gusah009 gusah009 self-assigned this Feb 24, 2024
@gusah009 gusah009 changed the base branch from main to gusah009-main February 25, 2024 01:06
Copy link

@KIJUNG-CHAE KIJUNG-CHAE left a comment

Choose a reason for hiding this comment

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

현장실습 일지가 밀리는 바람에.. 정신없이 시간이 지나갔네요. 늦은 피드백 죄송합니다!!

고민하신 부분과 코드를 보니 어떻게 클래스를 잘 쓰지? 엄청 고민했던 게 느껴집니다 👍🏻
코틀린 클래스를 상황에 맞게 잘 사용하신 것 같고 덕분에 코드보면서 저도 많이 생각해봤던 것 같아요.

객체지향적으로 짜다 보니 클래스는 줄어들고 Controller, Service 코드는 눈에 띄게 줄었는데 도메인 객체들의 코드량이 완전 뻠핑됐습니다... 이 코드가 전부 Service에 있었다고 생각하면 쳐다도 보기 싫을 것 같긴 한데, 도메인 코드가 엄청 커지니 도메인 코드를 쳐다 보기 싫어지네요. 다른 분들은 어떻게 했는 지도 궁금합니다.

제 생각엔 추상화와 객체를 나눠서 책임을 부여하는 만큼 도메인 코드가 많아지는 것은 어쩔 수 없는 것 같습니다 ㅠ 요구사항에 따라 가독성 좋게 도메인,서비스 계층에 코드를 적절하게 분배하는 것도 어쩌면 개발 능력일 수도 있을 것 같아요.

아 그리고 제가 도메인이라는 용어의 범위에 대해 모호해서 그런데, 미니언님께서 말하신 도메인의 범위가 궁금합니다! (서비스에서 사용되는 객체뿐만 아니라 inputView, Menu, UserOrderInfo 등 각종 클래스들을 모두 일컫으시는 걸까요?)

이상입니다! 일 다니시면서 미션 구현하시느라 고생하셨습니다!!!

abstract fun getBenefit(userOrderInfo: UserOrderInfo): EventType

protected abstract fun getPolicyName(): String
}
Copy link

@KIJUNG-CHAE KIJUNG-CHAE Mar 4, 2024

Choose a reason for hiding this comment

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

enum 클래스로 각 할인정책을 공통적으로 관리하는 방법이 있었네요!
접근 제한을 둔 부분도 좋은 것 같습니다.
배워갑니다 👍🏻

;

}

Choose a reason for hiding this comment

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

버디가 메뉴를 sealed 클래스로 구현했던 것 같습니다! 참고하시면 좋을 것 같습니다!
https://github.com/BDD-CLUB/kotlin-study/pull/15/files#diff-3b5a6a13c08ef3879d046a5270b468cd23fcabfb622a6a4bca5da265bde58b4a


@JvmInline
value class Price(val value: Int) {
init {

Choose a reason for hiding this comment

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

금액 도메인의 연산을 따로 만드셨군요!
민감한 도메인인만큼 이렇게 관리하는 것도 안정성이 좋을 것 같다는 생각이 드네요.
고민에 적어주신 내용처럼 막상보니 operator구현을 어디까지 해야할지 난감하네요 😅 제 생각엔 구현하신 것처럼 당장 필요한, 자주 사용하는 것만 구현하면 된다고 생각합니다!

import christmas.view.InputView
import christmas.view.OutputView

object ChristmasController {

Choose a reason for hiding this comment

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

object에 대해 이리저리 서칭하면서 생각해봤습니다.

스프링-코틀린에서는 단순히 모듈성 기능을 하는, 즉 상태가 필요하지 않은 경우 object를 사용하여 싱글턴으로 관리할 수 있을 것 같아요. (미니언님이 만든 InputView, OutputView 처럼요!)

또한 말씀대로 object를 사용하면 인스턴스를 생성하는 코드를 따로 적지않아도 관리되는 측면에선 좋은 것 같으나, 생성 흐름을 제어하지 못한다는 점에서 단점이 있을 수 있을 것 같습니다. 따라서 인스턴스의 생명주기에 대한 흐름을 제어할 필요가 없다면 충분히 object를 사용해도 좋은 것 같다고 생각합니다!

import christmas.model.Price
import christmas.validation.ChristmasException

enum class Badge(val minBenefitAmount: UInt) {

Choose a reason for hiding this comment

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

한글 객체 직관적이고 재미있네요 ㅎㅎ
저도 다음에 직관성이 필요하거나, 귀찮은(?) 요구사항이 있으면 한글로 만들어봐야겠습니다 ⚡️

requireChristmas(value) { "Failed requirement." }
}

inline fun requireChristmas(value: Boolean, lazyMessage: () -> Any) {

Choose a reason for hiding this comment

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

제가 고민하던 부분이었는데 이렇게 하면 init에서도 exception을 제어할 수 있네요🤨

println("안녕하세요! 우테코 식당 12월 이벤트 플래너입니다.")
}

fun printUserEventBenefit(userOrderInfo: UserOrderInfo, benefitInfo: UserBenefitInfo) {
Copy link

@KIJUNG-CHAE KIJUNG-CHAE Mar 4, 2024

Choose a reason for hiding this comment

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

한번에 print하는 코드 좋은 것 같습니다 ㅎㅎ 굿!!!

@gusah009
Copy link
Collaborator Author

gusah009 commented Mar 5, 2024

아 그리고 제가 도메인이라는 용어의 범위에 대해 모호해서 그런데, 미니언님께서 말하신 도메인의 범위가 궁금합니다! (서비스에서 사용되는 객체뿐만 아니라 inputView, Menu, UserOrderInfo 등 각종 클래스들을 모두 일컫으시는 걸까요?)

@KIJUNG-CHAE 범용적으로 쓰이는 MVC 패턴의 클래스들을 제외하고 이번 과제의 도메인 (Christmas)에 해당하는 클래스들입니다. MenuUserOrderInfo 모두 도메인 클래스라고 봐주시면 될 것 같아요.

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.

2 participants