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

Round4[step1] - 멘태 #159

Closed
wants to merge 2 commits into from

Conversation

cty7574
Copy link

@cty7574 cty7574 commented Jan 25, 2024

@mint3382 step1 pr입니다.

최대한 많은 피드백을 받고 마무리하고 싶어서 속도를 내봤는데 완성도가 어떨지 모르겠어요..

상속을 사용할 때 접근제어자를 어떻게 해주어야 할지 모르겠습니다. Person의 visitHospital 메서드가 BodyCondition의 healedInjury 메서드를 호출하도록 만들고 싶었는데 healedInjury를 private으로 두면 Person에서 접근할 수 없고 기본값인 internal로 두면 제 의도처럼 visitHospital을 거치는게 아니라 바로 healedInjury에 접근이 가능하게 되어 버리더라구요. 당장 생각나는 방법은 두개의 클래스를 한 파일 안에 두고 접근제어자를 fileprivate으로 설정하는 것인데 이 외에는 다른 방법이 없나요? 이런 상황에서는 예외적으로 파일을 분리하지 않고 한 파일에 두어도 되는걸까요? 상속 관계에 있는 경우에 허용이 되는 접근제어자가 있으면 좋을텐데 swift에는 없는 것 같네요.

switch문에서 default case에서는 어떤 동작을 하도록 해야할지 모르겠어요. 예시로 BodyCondition의 updateCondition 메서드에서 원래는
0에서 100 까지는 .good, 100에서 150까지는 .bad 150 이상부터는 .injury로 두려고 했는데 그러면 default에는 뭐라고 적어야 하지? 하는 의문이 생기더라구요. 그래서 그냥 default가 150이상의 경우를 처리하도록 했는데 이렇게 되면 모르는 사람이 제 코드를 보았을때 직관적이지 못할 것 같아서 좀 찜찜합니다..

<<윗몸일으키기를 시작합니다>> 문구를 출력할때 하드코딩 하지 않고 후행 클로저 내부에서 name 프로퍼티를 사용해 출력하고 싶었는데 어떻게 접근이 되도록 해야 하는지 그 방법을 잘 모르겠습니다..

@mint3382 mint3382 self-assigned this Jan 26, 2024
// Created by 맨태 on 1/25/24.
//

import Foundation

Choose a reason for hiding this comment

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

import Foundation은 어떨 때 필요할까요?

Copy link
Author

Choose a reason for hiding this comment

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

새 파일을 만들어주면 항상 import Foundation이 추가되어 있어서 별 생각 없이 그 밑줄부터 코드를 작성했던 것 같은데 지금 보니 제대로 알고 쓴 게 아니었다는걸 깨닫게 되었습니다. 원래는 Foundation에 대해서 막연히 swift 언어를 쓰기 위해 필요한 라이브러리 라고만 생각했었는데 공식문서를 읽어보면서 한번 정리해 볼 수 있었어요. 맞게 이해했는지에 대한 자신은 없지만요 ㅎㅎ

제가 이해한 바에 따르면 다음과 같이 크게 세 계층으로 나눌 수 있는 것 같아요. UIKit > Foundation > Swift Standard Library
Swift Standard Library: swift 언어의 기본적인 내용(기본 데이터 타입, 구조체, 컬렉션, 프로토콜, ...)
Foundation: Swift Standard Library + (클래스, 파일입출력, ...)
UIKit: Foundation + (앱개발을 위한 요소들)

본론으로 돌아와서 구조체만 선언된 해당 파일에서는 굳이 Foundation이 import 될 필요는 없을 것 같네요!


import Foundation

class BodyCondition {

Choose a reason for hiding this comment

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

bodyCondition은 왜 class로 만드셨나요?

Copy link
Author

Choose a reason for hiding this comment

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

Person에 상속해주기 위해서 클래스로 정의해 주었습니다.

Comment on lines +11 to +14
private var condition: Health = .good
private var upperBody: Int = 50
private var lowerBody: Int = 50
private var stamina: Int = 50

Choose a reason for hiding this comment

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

기본값을 주셨습니다! 이유를 알 수 있을까요? 사람마다 몸상태가 다를 것 같은데 initializer를 사용해보는 건 어떨까요?

Copy link
Author

Choose a reason for hiding this comment

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

저는 게임을 개발한다고 생각하면서 접근을 해서 그런지 기본값을 주는 식으로 작성하게 되었던 것 같아요. 게임을 처음에 시작하면 모두가 다 공평하게 레벨 1에서 시작하는 것처럼 동일한 스펙에서 시작이 되게끔이요.
여기서 질문이 하나 생기는데 외부에서 임의로 값을 넣어 생성하는 것을 방지해야 하는 이런 경우에는 생성자를 어떻게 작성해야 하나요? 모든 프로퍼티에 기본값이 존재한다면 기본 생성자에 의존해 인스턴스를 생성하게 하고 다른 생성자는 private으로 호출을 막아두면 되는 걸까요?

Comment on lines +16 to +19
didSet {
if fatigue < 0 { fatigue = 0 }
updateCondition()
}

Choose a reason for hiding this comment

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

property observer의 사용🥰❤️

Comment on lines +23 to +27
switch fatigue {
case 0..<100: condition = .good
case 100..<150: condition = .bad
default: condition = .injury
}

Choose a reason for hiding this comment

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

왜 switch를 사용하셨는지 알 수 있을까요?
여기서는 if와 같은 조건문이 더 어울리는 것 같다는 생각이 듭니다.

Copy link
Author

Choose a reason for hiding this comment

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

뭔가 열거형을 처리해 줄 때는 switch를 써야 한다는 생각이 있어서 무심코 사용했어요. 지금 보니 좌우가 바뀐 상황인 것 같네요. 열거형을 처리해 주는 것이 아니라 인트형을 처리해 주는 건데 말이죠.. 제 생각에도 조건문이 좀 더 어울리지 않을까 하는 생각이 듭니다


import Foundation

final class Person: BodyCondition {

Choose a reason for hiding this comment

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

Person이 BodyContion을 상속 받고 있군요!
왜 상속을 사용하셨나요? 이 둘은 상하관계가 명확한 객체인가요?
고민이 필요한 부분인 것 같습니다.

Copy link
Author

@cty7574 cty7574 Jan 26, 2024

Choose a reason for hiding this comment

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

이번 스텝을 진행하면서는 꼭 상속을 써먹어봐야지! 하는 생각이 있어서 �두 클래스의 상하관계를 크게 신경쓰지는 않았던 것 같습니다.
하지만 위에서도 언급한 것처럼 이번 스텝은 게임을 개발한다는 느낌으로 진행을 했고 그런 관점에서 상속을 사용한 것이 아주 틀린 것은 아니지 않을까 생각합니다. BodyCondition 이라는 네이밍 때문에 그 관계가 좀 와닿지 않는 것 같아요. (이 네이밍은 이번 스텝의 요구사항 이었습니다.) 게임이라고 생각해보면 BodyCondition 보다는 Unit 이나 Creature와 같은 네이밍도 괜찮을 것 같아요. 이 클래스를 상속받는 �person, monster 와 같은 자식 클래스도 있을 것 같구요. 지금 생각해보니 person 보다는 mankind 가 좀 더 낫겠다는 생각이 드네요.

Comment on lines +11 to +14
private var name: String
private var weight: Int
private var height: Int
private var nationality: String

Choose a reason for hiding this comment

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

프로퍼티들에 전부 private 키워드를 붙여 주셨어요.
은닉화를 하는 것, 아주 좋습니다. 그런데 name도 private 키워드가 필요할까요?
외부에서 알아도 되는 정보이지 않을까요? 어느 것들에 private 키워드로 은닉화를 시켜주어야 할지에 대한 고민도 해보시면 좋겠습니다!

Copy link
Author

@cty7574 cty7574 Jan 26, 2024

Choose a reason for hiding this comment

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

접근제어자를 결정하는 제 기본적인 과정은 다음과 같습니다.

  1. 일단 private으로 선언
  2. 외부에서 값을 얻어와야 할 일이 있는 변수는 private(set)으로 변경
  3. 외부에서 값을 변경해야 하는 경우에 set 메서드를 작성

외부로 노출되는 경우를 최소한으로 줄이려고 노력을 하다보니 이런 과정을 거치는 것 같아요.
Person 이라는 객체의 관점에서 본다면 name 과 같은 프로퍼티는 열어주는 것에 동의하지만 프로그램의 흐름을 봤을 때 외부로 노출이 될 일이 없는 변수를 굳이 공개할 필요가 있을까 하는 생각이 드는 것 같습니다.
민트님은 어떻게 생각하시나요?


import Foundation

struct Activity {

Choose a reason for hiding this comment

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

Activity는 왜 구조체로 만들어 주셨나요?

Copy link
Author

@cty7574 cty7574 Jan 26, 2024

Choose a reason for hiding this comment

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

이번 스텝의 설명을 읽어보니 Activity를 구조체로 구현해 두셨더라구요!
그래서 Activity를 구조체로 구현하는게 요구사항이구나 라고 생각했습니다


struct Activity {
let name: String
let action: (BodyCondition) -> Void

Choose a reason for hiding this comment

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

closure 선언 👍

Comment on lines +11 to +17
let sitUp: Activity = Activity(name: "윗몸일으키기") { body in
print("<<윗몸일으키기를 시작합니다>>")

body.updateHealthPoint(to: .upper, with: Int.random(in: 10...20))
body.updateHealthPoint(to: .fatigue, with: Int.random(in: 10...20))
body.printStatus()
}

Choose a reason for hiding this comment

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

클로저의 개념과 사용하는 방법을 잘 알고 계신 것 같아요! 아주 좋습니다 👍

@mint3382
Copy link

@mint3382 step1 pr입니다.

최대한 많은 피드백을 받고 마무리하고 싶어서 속도를 내봤는데 완성도가 어떨지 모르겠어요..

안녕하십니까 멘태님!
지난 5주간, 성실하게 아주 멋진 코드들을 작성해 주신 것에 대해 감사드립니다.
멘태님의 코드를 리뷰하면서 저도 많은 것을 배우고, 또 자극도 받았습니다.
이번 코드 역시 빠르게 작성해 주셨음에도 높은 완성도를 보여 주셨어요!
정말 멋집니다. 앞으로 멘태님의 행보도 기대합니다👍

상속을 사용할 때 접근제어자를 어떻게 해주어야 할지 모르겠습니다. Person의 visitHospital 메서드가 BodyCondition의 healedInjury 메서드를 호출하도록 만들고 싶었는데 healedInjury를 private으로 두면 Person에서 접근할 수 없고 기본값인 internal로 두면 제 의도처럼 visitHospital을 거치는게 아니라 바로 healedInjury에 접근이 가능하게 되어 버리더라구요. 당장 생각나는 방법은 두개의 클래스를 한 파일 안에 두고 접근제어자를 fileprivate으로 설정하는 것인데 이 외에는 다른 방법이 없나요? 이런 상황에서는 예외적으로 파일을 분리하지 않고 한 파일에 두어도 되는걸까요? 상속 관계에 있는 경우에 허용이 되는 접근제어자가 있으면 좋을텐데 swift에는 없는 것 같네요.

상속 관계에만 허용되는 접근 제어자는 저도 swift에는 존재하지 않는 걸로 알고 있습니다. 아무리 상속 관계에 있다고 하더라도 둘은 별개의 객체입니다. 부모 자식의 관계라도 타입이 다르니까요. 부모 클래스 내부에서만 쓰기 위해 private를 붙인 건데, 자식 클래스에서 사용할 수 없죠. 사실 이런 상황에서는 파일은 별도로 분리하고, private 키워드를 제거할 것 같네요.

switch문에서 default case에서는 어떤 동작을 하도록 해야할지 모르겠어요. 예시로 BodyCondition의 updateCondition 메서드에서 원래는 0에서 100 까지는 .good, 100에서 150까지는 .bad 150 이상부터는 .injury로 두려고 했는데 그러면 default에는 뭐라고 적어야 하지? 하는 의문이 생기더라구요. 그래서 그냥 default가 150이상의 경우를 처리하도록 했는데 이렇게 되면 모르는 사람이 제 코드를 보았을때 직관적이지 못할 것 같아서 좀 찜찜합니다..

오히려 그러한 경우에는 if -else 문이 더 직관적일 수 있다고 생각합니다.

<<윗몸일으키기를 시작합니다>> 문구를 출력할때 하드코딩 하지 않고 후행 클로저 내부에서 name 프로퍼티를 사용해 출력하고 싶었는데 어떻게 접근이 되도록 해야 하는지 그 방법을 잘 모르겠습니다..

후행 클로저가 있는 곳은 아직 해당 Activity 객체가 생성되기 전입니다. 생성이 되기 않았기에 접근할 수도 없죠.

@cty7574
Copy link
Author

cty7574 commented Jan 26, 2024

후행 클로저가 있는 곳은 아직 해당 Activity 객체가 생성되기 전입니다. 생성이 되기 않았기에 접근할 수도 없죠.

음.. 그렇다면 하드코딩을 하는 방법 말고는 없는걸까요... 좀 더 고민을 해봐야 겠네요

@jaemuYeo jaemuYeo closed this Mar 20, 2024
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.

None yet

3 participants