Skip to content

20260616_19_윤우상#56

Open
ssa25879 wants to merge 5 commits into
SurvivalCodingCampus:student/19_윤우상from
ssa25879:master
Open

20260616_19_윤우상#56
ssa25879 wants to merge 5 commits into
SurvivalCodingCampus:student/19_윤우상from
ssa25879:master

Conversation

@ssa25879

@ssa25879 ssa25879 commented Jun 16, 2026

Copy link
Copy Markdown

20260616_19_윤우상

📝 과제 정보

  • 교육 주제: 상속과 UML

📋 체크리스트

  • 코드 컨벤션 준수 (Formatter 적용)
  • 모든 테스트 케이스 통과 (JUnit)
  • 클래스 다이어그램 작성

📷 실행 결과 (또는 테스트 결과)

/image/ClassDiagram.png

❓질문 및 어려웠던 점

🔄 자체 평가 & 회고

  1. UML을 처음 작성하다 보니 작성 요령이 부족해서 어려웠다.
  2. PPT에 다중 상속이 Java는 불가능하다 하여 C++과 Python 에서는 가능하다는 것을 AI와 검색을 통해 알게되었다.

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1145ca3e-b03f-4d5a-bd86-ecfcace89a87

📥 Commits

Reviewing files that changed from the base of the PR and between c8c1374 and 6dbe3fb.

📒 Files selected for processing (5)
  • game/game.puml
  • game/src/main/java/com/survivalcoding/GreatWizard.java
  • game/src/main/java/com/survivalcoding/Hero.java
  • game/src/main/java/com/survivalcoding/Slime.java
  • game/src/test/java/com/survivalcoding/GreatWizardTest.java
🚧 Files skipped from review as they are similar to previous changes (5)
  • game/src/main/java/com/survivalcoding/Slime.java
  • game/src/main/java/com/survivalcoding/GreatWizard.java
  • game/game.puml
  • game/src/test/java/com/survivalcoding/GreatWizardTest.java
  • game/src/main/java/com/survivalcoding/Hero.java

코드 리뷰 및 피드백

안녕하세요! 상속과 UML 개념을 담은 좋은 과제 제출입니다. 전반적으로 기본기가 잘 다져져 있으나, 몇 가지 생각해볼 점들을 제시합니다.

칭찬할 점 ✨

  1. 캡슐화의 올바른 이해: 모든 클래스에서 필드를 private으로 선언하고 getter/setter를 통해 접근하도록 한 점이 좋습니다. 특히 setHP(), setMP()에서 Math.clamp()를 사용하여 범위를 자동으로 제한한 설계는 데이터 무결성을 보장합니다.

  2. 상속 구조의 명확한 설계: SuperHero extends Hero, GreatWizard extends Wizard, PoisonSlime extends Slime 등 적절한 "is-a" 관계를 정의했습니다.

  3. 오버라이드의 활용: PoisonSlimeattack() 메서드에서 super.attack(hero)를 먼저 호출한 후 추가 로직을 구현한 방식은 다형성을 잘 이해하고 있음을 보여줍니다.

  4. 테스트 코드 개선: @BeforeEach를 활용하고 getter/setter로 테스트하는 방식으로 변경한 점은 캡슐화 원칙을 잘 따릅니다.

  5. 학습 문서: 상속 개념을 정리한 TIL 문서와 PlantUML 다이어그램은 훌륭한 문서화입니다.

생각해볼 점 💭

1. 메서드 오버라이드의 의도 확인

SuperHero 클래스의 attack() 메서드를 보면:

`@Override`
public void attack() {
    super.attack();
}

질문: 이 메서드가 단순히 부모의 attack()을 호출하기만 한다면, 굳이 오버라이드할 필요가 있을까요? 오버라이드는 자식 클래스가 부모의 동작을 다르게 구현하고 싶을 때 하는 것입니다. 혹시 SuperHero만의 특별한 공격 로직이 추가되어야 할까요?

2. 부모-자식 클래스 간 메서드 구현 비교

WizardGreatWizardheal() 메서드를 비교하면:

  • Wizard.heal(): 기본 회복량 계산 및 MP 차감
  • GreatWizard.heal(): 고정 recoverPoint 사용 및 MP 차감

질문: GreatWizardWizard를 상속한다면, 왜 Wizardheal() 메서드와 완전히 다르게 구현하는 것일까요? 설계 관점에서 보면, 자식 클래스가 부모의 메서드 로직을 유지하면서 일부를 확장하는 것이 상속의 장점입니다. 다시 한 번 설계를 검토해 보세요.

3. Cleric 클래스의 설계 검토

현재 Cleric 클래스가 Person을 상속하지 않고 독립적으로 존재합니다.

질문: Cleric도 실제로는 "사람"의 한 종류입니다. "Cleric is a Person" 관계가 성립하지 않을까요? 더 나은 상속 구조를 생각해 볼 여지가 있는지 검토해 보세요.

4. Hero 클래스의 attack() 메서드

현재 Heroattack() 메서드는:

public void attack() {
    hp -= 1;
    System.out.println("공격했다");
}

질문: 공격할 때마다 HP가 1씩 깎인다는 것이 맞는 설계일까요? 일반적인 게임 설계 관점에서 "공격하는 주체"가 피해를 입는 것이 합리적일까요? 혹은 매개변수를 통해 "누구에게" 공격하는지 명시하는 것이 더 나을까요?

5. 매직 넘버(Magic Number) 검토

여러 클래스에서 하드코딩된 숫자들(예: hp / 5, Math.clamp(hp, 0, maxHP))이 사용됩니다.

질문: 이러한 상수들(예: POISON_DAMAGE_RATIO = 5, ATTACK_COST = 1 등)을 클래스 변수로 선언하면 코드의 가독성과 유지보수성이 더 좋아질까요?

제언

  • setMP(int mp) 호출 후 즉시 getMP()로 조회하는 패턴이 반복되고 있습니다. 필요시 더 간결한 방식이 있는지 검토해 보세요.
  • 각 클래스의 책임(Responsibility)이 명확한지 다시 한 번 확인해 보세요. 예를 들어, Hero 클래스는 진정 공격 시 자신의 HP가 깎여야 하는지, 아니면 피해를 받아야 하는지 등을 생각해 봅시다.

이번 과제는 상속의 기본을 잘 이해하고 있음을 보여줍니다. 위의 질문들을 통해 더욱 견고한 설계를 만들 수 있을 것 같습니다! 🎯

Walkthrough

Hero에 maxHP 바운딩 API와 생성자 체이닝을 추가하고, Slime/PoisonSlime, SuperHero, Wizard/GreatWizard 신규 상속 계층을 구현했다. Cleric 필드를 private으로 변경하고 Math.clamp 기반 setter를 도입했다. 각 클래스에 대응하는 JUnit 테스트, PlantUML 다이어그램, TIL 문서도 함께 추가되었다.

Changes

게임 캐릭터 상속 계층 구현

Layer / File(s) Summary
Hero 기반 클래스: maxHP 모델 및 공개 API 정비
game/src/main/java/com/survivalcoding/Hero.java, game/src/test/java/com/survivalcoding/HeroTest.java
defaultHeroName/defaultHeroHP 상수와 maxHP 필드를 추가하고, setHP()maxHP 범위로 클램핑되도록 변경한다. 생성자를 체이닝 방식으로 재편하고 attack()을 public으로 변경하며 run(), final slip()을 추가한다. HeroTestgetHp() 호출을 getHP()로 수정한다.
Slime/PoisonSlime 신규 구현 및 테스트
game/src/main/java/com/survivalcoding/Slime.java, game/src/main/java/com/survivalcoding/PoisonSlime.java, game/src/test/java/com/survivalcoding/SlimeTest.java, game/src/test/java/com/survivalcoding/PoisonSlimeTest.java
Slime을 신규 구현하여 Math.clamp 기반 setHP와 null 검증 attack(Hero)를 제공한다. PoisonSlimeSlime을 상속하여 poisonCount(초기값 5)와 독 데미지 attack 오버라이드(super.attack 후 HP * 4/5)를 추가한다. 경계값 및 독 카운트 소진 흐름을 각각 테스트한다.
SuperHero 신규 구현
game/src/main/java/com/survivalcoding/SuperHero.java
Hero를 상속하는 SuperHero를 추가한다. isFlying 상태 필드/getter/setter, 생성자 오버로드 3종, run() 오버라이드(빠른 달리기 출력), attack() 오버라이드(super.attack() 위임)를 구현한다.
Wizard MP 조건부 힐 로직 및 GreatWizard 신규 구현
game/src/main/java/com/survivalcoding/Wizard.java, game/src/main/java/com/survivalcoding/GreatWizard.java, game/src/test/java/com/survivalcoding/GreatWizardTest.java
WizarddefaultWizardMP/defaultWizardHP 상수를 추가하고 heal(Hero)이 MP 10 소모 조건부로 동작하도록 변경한다. GreatWizardWizard를 상속하여 recoverPoint(25) 기반 heal 오버라이드(MP 5 소모)와 superHeal(MP 50 이상 시 최대 HP 회복)을 구현한다. 생성, heal, overHeal, null 예외, superHeal을 테스트로 검증한다.
Cleric 필드 캡슐화 및 Math.clamp 기반 setter 추가
game/src/main/java/com/survivalcoding/Cleric.java, game/src/test/java/com/survivalcoding/ClericTest.java
Clericname/hp/mp 필드를 private으로 변경하고 생성자를 setter 위임 방식으로 전환한다. IllegalArgumentException throw 대신 Math.clamp로 범위 보정하는 setter를 추가한다. selfAid()를 getter/setter 기반으로 전환한다. ClericTest의 필드 직접 접근을 getter/setter 호출로 전면 교체한다.
PlantUML 다이어그램, TIL 문서, 주석 정리
game/game.puml, TIL/2026-06-16-inheritance.md, game/src/main/java/com/survivalcoding/Person.java, game/src/main/java/com/survivalcoding/Wand.java, game/src/test/java/com/survivalcoding/WandTest.java
game.puml에 전체 클래스 계층의 필드/메서드/상속 관계를 PlantUML로 기술한다. TIL 문서에 상속 개념, 오버라이드, 생성자 호출 순서, super() 암묵적 삽입, UML 예시를 기록한다. Person.javaWand.java의 과제 안내 주석을 제거하고 WandTest의 람다 형식을 다중 줄로 정리한다.

Sequence Diagram(s)

sequenceDiagram
  rect rgba(70, 130, 180, 0.5)
    Note over PoisonSlime,Hero: PoisonSlime 공격 흐름
  end
  participant PoisonSlime
  participant Slime
  participant Hero
  PoisonSlime->>Slime: super.attack(hero)
  Slime->>Hero: setHP(getHP() - slimeAttackPoint)
  alt poisonCount > 0
    PoisonSlime->>Hero: setHP(getHP() * 4 / 5)
    PoisonSlime->>PoisonSlime: poisonCount--
  else poisonCount == 0
    PoisonSlime->>PoisonSlime: 독 소모 완료 메시지 출력
  end
Loading
sequenceDiagram
  rect rgba(60, 179, 113, 0.5)
    Note over GreatWizard,Hero: GreatWizard heal / superHeal 흐름
  end
  participant GreatWizard
  participant Hero
  alt heal: getMP() >= 5
    GreatWizard->>Hero: setHP(getHP() + recoverPoint)
    GreatWizard->>GreatWizard: setMP(getMP() - 5)
  else heal: getMP() < 5
    GreatWizard->>GreatWizard: "마나가 부족합니다." 출력
  end
  alt superHeal: getMP() >= 50
    GreatWizard->>Hero: setHP(getMaxHP())
    GreatWizard->>GreatWizard: 슈퍼 힐 메시지 출력
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning PR 제목이 학생 이름과 날짜만 포함하고 있으며, 상속/UML 과제의 핵심 내용을 구체적으로 설명하지 못하고 있습니다. PR 제목을 '상속 구현 및 UML 클래스 다이어그램 작성' 또는 유사한 형태로 변경하여 실제 변경 사항의 주요 내용을 명확히 드러내주세요.
Docstring Coverage ⚠️ Warning Docstring coverage is 2.74% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed PR 설명이 대부분의 필수 섹션(과제 정보, 체크리스트, 실행 결과, 자체 평가)을 포함하고 있으며 구조적으로 완성되어 있습니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
game/src/test/java/com/survivalcoding/ClericTest.java (1)

33-47: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

경계값 테스트가 clamp 정책과 충돌합니다.

현재는 범위 이탈 입력에서 예외를 기대하지만, Cleric 구현은 범위 내 보정(clamp)으로 바뀌었습니다. 예외 검증 대신 보정된 값 검증으로 바꿔야 합니다.

수정 제안 diff
-        // 최대, 최소 값을 지키지 않는 경우 생성이 안되는지 검증
-        assertAll("최대값, 최소값을 지키지 않았을 경우 확인",
-                () -> assertThrows(IllegalArgumentException.class, () -> {
-                    Cleric overflowHPCase = new Cleric(testName, overflowHP);
-                }, "HP 최대값 초과 예외처리가 발생하지 않음"),
-                () -> assertThrows(IllegalArgumentException.class, () -> {
-                    Cleric overflowMPCase = new Cleric(testName, testHP, overflowMP);
-                }, "MP 최대값 초과 예외처리가 발생하지 않음"),
-                () -> assertThrows(IllegalArgumentException.class, () -> {
-                    Cleric underflowHPCase = new Cleric(testName, underflowHP);
-                }, "HP 음수, 0 입력 예외처리가 발생하지 않음"),
-                () -> assertThrows(IllegalArgumentException.class, () -> {
-                    Cleric underflowMPCase = new Cleric(testName, testHP, underflowMP);
-                }, "MP 음수 입력 예외처리가 발생하지 않음")
-        );
+        // clamp 정책 검증: 범위를 벗어난 값은 경계값으로 보정
+        Cleric overflowHPCase = new Cleric(testName, overflowHP);
+        Cleric overflowMPCase = new Cleric(testName, testHP, overflowMP);
+        Cleric underflowHPCase = new Cleric(testName, underflowHP);
+        Cleric underflowMPCase = new Cleric(testName, testHP, underflowMP);
+
+        assertAll("최대값/최소값 보정 확인",
+                () -> assertEquals(Cleric.maxHP, overflowHPCase.getHP()),
+                () -> assertEquals(Cleric.maxMP, overflowMPCase.getMP()),
+                () -> assertEquals(0, underflowHPCase.getHP()),
+                () -> assertEquals(0, underflowMPCase.getMP())
+        );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@game/src/test/java/com/survivalcoding/ClericTest.java` around lines 33 - 47,
The test in the ClericTest class is verifying that IllegalArgumentException is
thrown for out-of-range HP and MP values, but the actual Cleric implementation
uses value clamping instead of throwing exceptions. Replace the four
assertThrows blocks (for overflowHPCase, overflowMPCase, underflowHPCase, and
underflowMPCase) with positive assertions that verify the Cleric object is
created successfully with the values properly clamped to their valid ranges. For
each case, construct a Cleric instance and assert that its HP or MP values equal
the expected clamped boundaries rather than expecting an exception to be thrown.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@game/game.puml`:
- Around line 17-31: The Hero class UML diagram is missing the name field that
corresponds to the existing getName() and setName() methods, and it also lacks
the slip() method mentioned in the PR description. Add a private String field
named name to the Hero class attributes section, and add the public void slip()
method to the operations section to synchronize the UML specification with the
actual code implementation.

In `@game/src/main/java/com/survivalcoding/Cleric.java`:
- Around line 50-59: The code uses Math.clamp in the setHP and setMP methods of
the Cleric class (and also in Slime.java at line 26), but Math.clamp is only
available in Java 21 and above. To fix this, do one of the following: (1) Update
game/build.gradle by adding sourceCompatibility = '21' and targetCompatibility =
'21' to explicitly require Java 21 as the minimum version, or (2) if Java 20 or
lower must be supported, create a custom clamp utility method that implements
the same logic (constraining a value between a minimum and maximum) and replace
all Math.clamp calls in Cleric.java's setHP and setMP methods and in Slime.java
with calls to this custom method.

In `@game/src/main/java/com/survivalcoding/GreatWizard.java`:
- Around line 55-58: The superHeal method in GreatWizard checks if sufficient MP
is available but does not consume the MP after successfully healing the hero,
and it lacks an else branch to handle insufficient MP. After setting the hero's
HP to maximum within the if block where MP >= 50 is confirmed, you must also
deduct 50 MP from the caster (using a setMP method or similar). Additionally,
add an else branch that prints "마나가 부족합니다." to handle the case when MP is less
than 50.

In `@game/src/main/java/com/survivalcoding/Hero.java`:
- Around line 43-45: The HP validation invariant is being bypassed through
multiple code paths. At the anchor location in the setHP method
(game/src/main/java/com/survivalcoding/Hero.java, lines 43-45), add a lower
bound check using Math.max to ensure hp is never set below 0, complementing the
existing upper bound check with Math.min. At the sibling locations (lines 51-53,
55-58, and 69-81), replace all direct assignments to the hp field with calls to
the setHP setter method to ensure validation is applied consistently.
Additionally, in the setMaxHP method around lines 51-53, after reducing maxHP,
recalculate hp by calling setHP with the current hp value to re-clamp it in case
it now exceeds the new maximum.

In `@game/src/main/java/com/survivalcoding/Slime.java`:
- Around line 33-35: The setMaxHP() method sets the new maximum HP but does not
recalibrate the current hp value when the new maxHP is lower than the existing
hp, potentially leaving the object in an invalid state where hp exceeds maxHP.
After setting this.maxHP in the setMaxHP() method, add a line to ensure that the
current hp is capped to not exceed the new maxHP value by reassigning this.hp to
the minimum of its current value and the new maxHP.
- Line 26: The Math.clamp method used in the Slime.java file (in the assignment
to this.hp) is only available in Java 21 and later, but the build.gradle does
not specify a Java version requirement. Either update build.gradle to set
sourceCompatibility and targetCompatibility to Java 21 or higher, or replace the
Math.clamp(hp, 0, maxHP) call with an equivalent implementation compatible with
older Java versions such as Math.max(Math.min(hp, maxHP), 0) to ensure the code
compiles in your target environment.

In `@game/src/test/java/com/survivalcoding/GreatWizardTest.java`:
- Around line 45-56: The heal and superHeal test methods only verify HP recovery
but do not validate that MP is properly consumed during the healing action,
which allows MP deduction bugs to go undetected. For both the heal method test
(lines 45-56) and superHeal method test (lines 83-94), add assertions that
verify the MP was correctly deducted (comparing MP before the heal call to MP
after minus the expected consumption amount). Additionally, add separate test
cases for each healing method to verify the behavior when the caster has
insufficient MP to perform the heal, ensuring both the normal path MP
consumption and the MP insufficiency edge case are properly tested.

In `@TIL/2026-06-16-inheritance.md`:
- Around line 89-92: The method signature for isFlying() in the SuperHero class
has an incorrect return type notation. The current signature shows "+void
boolean isFlying()" with both void and boolean listed as return types, which is
invalid UML notation. Remove the "void" keyword from the isFlying() method
signature so it reads "+boolean isFlying()" to correctly indicate that the
method returns a boolean value.

---

Outside diff comments:
In `@game/src/test/java/com/survivalcoding/ClericTest.java`:
- Around line 33-47: The test in the ClericTest class is verifying that
IllegalArgumentException is thrown for out-of-range HP and MP values, but the
actual Cleric implementation uses value clamping instead of throwing exceptions.
Replace the four assertThrows blocks (for overflowHPCase, overflowMPCase,
underflowHPCase, and underflowMPCase) with positive assertions that verify the
Cleric object is created successfully with the values properly clamped to their
valid ranges. For each case, construct a Cleric instance and assert that its HP
or MP values equal the expected clamped boundaries rather than expecting an
exception to be thrown.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4bb53d2b-3740-412d-af3a-2d2d27b27874

📥 Commits

Reviewing files that changed from the base of the PR and between 966944d and c8c1374.

⛔ Files ignored due to path filters (1)
  • image/ClassDiagram.png is excluded by !**/*.png
📒 Files selected for processing (17)
  • TIL/2026-06-16-inheritance.md
  • game/game.puml
  • game/src/main/java/com/survivalcoding/Cleric.java
  • game/src/main/java/com/survivalcoding/GreatWizard.java
  • game/src/main/java/com/survivalcoding/Hero.java
  • game/src/main/java/com/survivalcoding/Person.java
  • game/src/main/java/com/survivalcoding/PoisonSlime.java
  • game/src/main/java/com/survivalcoding/Slime.java
  • game/src/main/java/com/survivalcoding/SuperHero.java
  • game/src/main/java/com/survivalcoding/Wand.java
  • game/src/main/java/com/survivalcoding/Wizard.java
  • game/src/test/java/com/survivalcoding/ClericTest.java
  • game/src/test/java/com/survivalcoding/GreatWizardTest.java
  • game/src/test/java/com/survivalcoding/HeroTest.java
  • game/src/test/java/com/survivalcoding/PoisonSlimeTest.java
  • game/src/test/java/com/survivalcoding/SlimeTest.java
  • game/src/test/java/com/survivalcoding/WandTest.java
💤 Files with no reviewable changes (2)
  • game/src/main/java/com/survivalcoding/Wand.java
  • game/src/main/java/com/survivalcoding/Person.java

Comment thread game/game.puml
Comment on lines +50 to +59
public void setHP(int hp) {
this.hp = Math.clamp(hp, 0, maxHP);
}

public int getMP() {
return mp;
}

public void setMP(int mp) {
this.mp = Math.clamp(mp, 0, maxMP);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Potential Java toolchain files =="
fd -HI 'pom.xml|build.gradle|build.gradle.kts|gradle.properties|settings.gradle|mvnw|.tool-versions|.java-version|.sdkmanrc' | sort

echo
echo "== Java version declarations =="
TOOLCHAIN_FILES="$(fd -HI 'pom.xml|build.gradle|build.gradle.kts|gradle.properties|settings.gradle|.tool-versions|.java-version|.sdkmanrc' || true)"
if [ -n "${TOOLCHAIN_FILES}" ]; then
  rg -n --no-heading 'sourceCompatibility|targetCompatibility|toolchain|languageVersion|maven.compiler.source|maven.compiler.target|<release>|java.version|--release' ${TOOLCHAIN_FILES} || true
else
  echo "No toolchain declaration files found."
fi

echo
echo "== Math.clamp usage sites =="
rg -n --no-heading 'Math\.clamp\s*\('

Repository: SurvivalCodingCampus/polytech_java2

Length of output: 541


🏁 Script executed:

#!/bin/bash

echo "=== game/build.gradle ===" 
cat game/build.gradle

echo -e "\n=== root build.gradle ===" 
cat build.gradle

echo -e "\n=== settings.gradle ===" 
cat settings.gradle

Repository: SurvivalCodingCampus/polytech_java2

Length of output: 931


🏁 Script executed:

#!/bin/bash

echo "=== Checking for gradle.properties ==="
if [ -f gradle.properties ]; then
    cat gradle.properties
else
    echo "No gradle.properties found"
fi

echo -e "\n=== Checking for JAVA_HOME or java version in system ==="
which java && java -version 2>&1 || echo "Java not available in sandbox"

echo -e "\n=== Double-checking all Math.clamp usages with context ==="
rg -B 2 -A 2 'Math\.clamp\s*\(' game/src/

Repository: SurvivalCodingCampus/polytech_java2

Length of output: 1412


Math.clamp 사용을 위해 Java 21 이상으로 빌드 버전을 명시해야 합니다.

현재 build.gradlesourceCompatibility 또는 targetCompatibility가 선언되어 있지 않습니다. Math.clamp는 Java 21 이상에서만 사용 가능하므로, 다음 중 하나를 수행하세요:

  • game/build.gradle에 명시적으로 Java 버전을 선언: sourceCompatibility = '21'targetCompatibility = '21' 추가
  • 또는 Java 20 이하를 지원해야 하면 별도의 clamp 구현으로 대체
현재 Math.clamp 사용 위치
game/src/main/java/com/survivalcoding/Slime.java:26
game/src/main/java/com/survivalcoding/Cleric.java:51
game/src/main/java/com/survivalcoding/Cleric.java:59
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@game/src/main/java/com/survivalcoding/Cleric.java` around lines 50 - 59, The
code uses Math.clamp in the setHP and setMP methods of the Cleric class (and
also in Slime.java at line 26), but Math.clamp is only available in Java 21 and
above. To fix this, do one of the following: (1) Update game/build.gradle by
adding sourceCompatibility = '21' and targetCompatibility = '21' to explicitly
require Java 21 as the minimum version, or (2) if Java 20 or lower must be
supported, create a custom clamp utility method that implements the same logic
(constraining a value between a minimum and maximum) and replace all Math.clamp
calls in Cleric.java's setHP and setMP methods and in Slime.java with calls to
this custom method.

Comment thread game/src/main/java/com/survivalcoding/GreatWizard.java Outdated
Comment on lines 43 to +45
public void setHP(int hp) {
this.hp = hp;
this.hp = Math.min(hp, maxHP);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

HP/이름 검증 불변식이 여러 경로에서 우회됩니다.

Line 44는 하한(0) 보정이 없고, Line 56-57/70/80은 setter를 거치지 않아 검증·클램프가 깨집니다. Line 52도 maxHP 축소 시 현재 hp를 재보정하지 않아 hp > maxHP 상태가 남습니다.

수정 예시
 public void setHP(int hp) {
-    this.hp = Math.min(hp, maxHP);
+    this.hp = Math.max(0, Math.min(hp, maxHP));
 }

 public void setMaxHP(int maxHP) {
     this.maxHP = Math.max(maxHP, 0);
+    this.hp = Math.min(this.hp, this.maxHP);
 }

 public Hero(String name, int hp) {
-    this.name = name;
-    this.hp = hp;
+    setName(name);
+    setHP(hp);
 }

 public void attack() {
-    hp -= 1;
+    setHP(this.hp - 1);
     System.out.println("공격했다");
 }

 public final void slip() {
-    hp -= 5;
+    setHP(this.hp - 5);
     System.out.println("미끄러졌다!");
 }

Also applies to: 51-53, 55-58, 69-81

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@game/src/main/java/com/survivalcoding/Hero.java` around lines 43 - 45, The HP
validation invariant is being bypassed through multiple code paths. At the
anchor location in the setHP method
(game/src/main/java/com/survivalcoding/Hero.java, lines 43-45), add a lower
bound check using Math.max to ensure hp is never set below 0, complementing the
existing upper bound check with Math.min. At the sibling locations (lines 51-53,
55-58, and 69-81), replace all direct assignments to the hp field with calls to
the setHP setter method to ensure validation is applied consistently.
Additionally, in the setMaxHP method around lines 51-53, after reducing maxHP,
recalculate hp by calling setHP with the current hp value to re-clamp it in case
it now exceeds the new maximum.


public void setHP(int hp) {
// 체력이 음수가 될 경우 0 으로, maxHP를 초과할 경우 maxHP로 보정
this.hp = Math.clamp(hp, 0, maxHP);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "[1] Java 타깃/툴체인 선언 확인"
for f in $(fd -HI 'pom.xml|build.gradle|build.gradle.kts|gradle.properties|.tool-versions|.java-version|.sdkmanrc'); do
  echo "=== $f ==="
  rg -n "maven-compiler-plugin|<release>|sourceCompatibility|targetCompatibility|toolchain|languageVersion|java\\.version" "$f" || true
done

echo
echo "[2] Math.clamp 사용 위치 확인"
rg -n "Math\\.clamp\\(" --type java

Repository: SurvivalCodingCampus/polytech_java2

Length of output: 496


🏁 Script executed:

cat -n game/build.gradle

Repository: SurvivalCodingCampus/polytech_java2

Length of output: 570


🏁 Script executed:

cat -n build.gradle

Repository: SurvivalCodingCampus/polytech_java2

Length of output: 570


🏁 Script executed:

rg -i "java.*version|javaTarget|release" --type gradle -A 2 -B 2

Repository: SurvivalCodingCampus/polytech_java2

Length of output: 61


🏁 Script executed:

find .github/workflows -name '*.yml' -o -name '*.yaml' 2>/dev/null | head -20

Repository: SurvivalCodingCampus/polytech_java2

Length of output: 61


🏁 Script executed:

cat -n gradle.properties 2>/dev/null || echo "No gradle.properties found"

Repository: SurvivalCodingCampus/polytech_java2

Length of output: 106


🏁 Script executed:

rg -i "sourceCompatibility|targetCompatibility" . --type gradle --type properties

Repository: SurvivalCodingCampus/polytech_java2

Length of output: 114


🏁 Script executed:

fd -HI 'README|readme' | head -5 | xargs cat 2>/dev/null || echo "No README found"

Repository: SurvivalCodingCampus/polytech_java2

Length of output: 61


🏁 Script executed:

cat -n game/src/main/java/com/survivalcoding/Slime.java | head -35

Repository: SurvivalCodingCampus/polytech_java2

Length of output: 1019


🏁 Script executed:

rg -i "java.*21|jdk.*21" . 2>/dev/null || echo "No Java 21 references found"

Repository: SurvivalCodingCampus/polytech_java2

Length of output: 107


Java 21 이상의 버전 설정이 필수입니다.

Math.clamp는 Java 21에서 추가된 메서드로, 현재 build.gradle에 Java 버전이 명시되어 있지 않습니다. 컴파일 환경에 따라 Java 21 미만에서는 컴파일 실패가 발생할 수 있습니다. build.gradle에 sourceCompatibility 또는 targetCompatibility를 Java 21 이상으로 명시하거나, Java 21 미만을 지원해야 한다면 Math.max(Math.min(hp, maxHP), 0) 등으로 변경해야 합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@game/src/main/java/com/survivalcoding/Slime.java` at line 26, The Math.clamp
method used in the Slime.java file (in the assignment to this.hp) is only
available in Java 21 and later, but the build.gradle does not specify a Java
version requirement. Either update build.gradle to set sourceCompatibility and
targetCompatibility to Java 21 or higher, or replace the Math.clamp(hp, 0,
maxHP) call with an equivalent implementation compatible with older Java
versions such as Math.max(Math.min(hp, maxHP), 0) to ensure the code compiles in
your target environment.

Comment on lines +33 to +35
public void setMaxHP(int maxHP) {
this.maxHP = Math.max(maxHP, 0);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

setMaxHP() 호출 후 현재 HP 재보정이 필요합니다.

Line 34에서 maxHP를 낮춰도 현재 hp가 그대로라 hp > maxHP 상태가 남을 수 있습니다.

수정 예시
 public void setMaxHP(int maxHP) {
     this.maxHP = Math.max(maxHP, 0);
+    this.hp = Math.min(this.hp, this.maxHP);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public void setMaxHP(int maxHP) {
this.maxHP = Math.max(maxHP, 0);
}
public void setMaxHP(int maxHP) {
this.maxHP = Math.max(maxHP, 0);
this.hp = Math.min(this.hp, this.maxHP);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@game/src/main/java/com/survivalcoding/Slime.java` around lines 33 - 35, The
setMaxHP() method sets the new maximum HP but does not recalibrate the current
hp value when the new maxHP is lower than the existing hp, potentially leaving
the object in an invalid state where hp exceeds maxHP. After setting this.maxHP
in the setMaxHP() method, add a line to ensure that the current hp is capped to
not exceed the new maxHP value by reassigning this.hp to the minimum of its
current value and the new maxHP.

Comment on lines +45 to +56
@DisplayName("heal 정상 작동 여부 확인")
void heal() {
// Given
// testGreatWizard는 setUp에서 준비됨
testHero.setHP(testHero.getMaxHP() - GreatWizard.recoverPoint);

// when
testGreatWizard.heal(testHero);

// then
assertEquals(testHero.getMaxHP(), testHero.getHP());
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

heal/superHeal 테스트가 MP 소모 계약을 검증하지 않습니다.

현재 테스트는 HP 회복만 확인해서, MP 차감 누락 회귀를 통과시킬 수 있습니다. 각 테스트에 “호출 전 MP - 소모량” 검증과 MP 부족 분기 케이스를 추가해 주세요.

보강 예시 diff
     void heal() {
         // Given
         // testGreatWizard는 setUp에서 준비됨
         testHero.setHP(testHero.getMaxHP() - GreatWizard.recoverPoint);
+        int beforeMP = testGreatWizard.getMP();

         // when
         testGreatWizard.heal(testHero);

         // then
         assertEquals(testHero.getMaxHP(), testHero.getHP());
+        assertEquals(beforeMP - 5, testGreatWizard.getMP());
     }
@@
     void superHeal() {
         // given
         // testGreatWizard는 setUp에서 준비됨
         testHero.setHP(superHealTestHP);
+        int beforeMP = testGreatWizard.getMP();

         // when
         testGreatWizard.superHeal(testHero);

         // then
         assertEquals(testHero.getMaxHP(), testHero.getHP());
+        assertEquals(beforeMP - 50, testGreatWizard.getMP());
     }

Also applies to: 83-94

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@game/src/test/java/com/survivalcoding/GreatWizardTest.java` around lines 45 -
56, The heal and superHeal test methods only verify HP recovery but do not
validate that MP is properly consumed during the healing action, which allows MP
deduction bugs to go undetected. For both the heal method test (lines 45-56) and
superHeal method test (lines 83-94), add assertions that verify the MP was
correctly deducted (comparing MP before the heal call to MP after minus the
expected consumption amount). Additionally, add separate test cases for each
healing method to verify the behavior when the caster has insufficient MP to
perform the heal, ensuring both the normal path MP consumption and the MP
insufficiency edge case are properly tested.

Comment on lines +89 to +92
class SuperHero extends Hero {
+void setFlying(boolean Flying)
+void boolean isFlying()
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

UML 예시 메서드 시그니처 표기를 수정해 주세요.

Line 91의 +void boolean isFlying()는 반환형 표기가 잘못되었습니다. +boolean isFlying()로 고쳐야 예시가 올바른 형태가 됩니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@TIL/2026-06-16-inheritance.md` around lines 89 - 92, The method signature for
isFlying() in the SuperHero class has an incorrect return type notation. The
current signature shows "+void boolean isFlying()" with both void and boolean
listed as return types, which is invalid UML notation. Remove the "void" keyword
from the isFlying() method signature so it reads "+boolean isFlying()" to
correctly indicate that the method returns a boolean value.

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.

1 participant