本文へ移動
cccskills
無料GitHub で公開

introduce-assertion

암묵적 가정(null 아님·범위·상태)을 Assert/Validate로 명시하여 가정 위반 시 즉시 발견. "assertion 추가", "전제 조건 명시", "가정을 코드로", "/introduce-assertion" 요청 시 사용. 단, 반복되는 null 검사를 객체로 대체하는 것은 /introduce-special-case가 적합. /introduce-assertion [commit-ref]로 호출.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md6.7 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Introduce Assertion

GOAL

코드가 암묵적으로 가정하는 조건을 assertion으로 명시하여:

  • 가정 위반 시 즉시 발견 (원인과 증상의 거리 단축)
  • 주석보다 강력한 실행 가능한 문서
  • 계약 기반 프로그래밍의 경량 버전

CONSTRAINTS

  • 계열: Tidy — 후보 보고 후 승인 없이 적용 (../../references/refactoring-procedure.md §0·§3-A)
  • 동작 변경 금지: assertion 추가만 수행 (기존 로직 변경 없음)
  • 테스트 수정 금지: assertion 추가가 테스트를 실패시키면 되돌리기
  • 명시적 git add: git add -A 금지, 변경된 파일만 명시

Assertion 도구 선택 (프로젝트 의존성 자동 감지)

프로젝트의 빌드 파일(build.gradle 또는 pom.xml)을 확인하여 자동 선택:

  1. Spring 의존성 있음 → org.springframework.util.Assert
  2. Apache Commons 있음 → org.apache.commons.lang3.Validate
  3. 둘 다 없음 → java.util.Objects.requireNonNull + IllegalArgumentException

Java assert 키워드는 -ea 플래그가 필요하여 프로덕션에서 비활성화될 수 있으므로 사용하지 않음

적용 패턴

Before: 암묵적 가정 (Spring Assert)

public double calculateDiscount(double price, double rate) {
    // price는 양수, rate는 0~1 사이여야 함 (주석 또는 아무것도 없음)
    return price * rate;
}

After: assertion으로 가정 명시

import org.springframework.util.Assert;

public double calculateDiscount(double price, double rate) {
    Assert.isTrue(price > 0, "price must be positive: " + price);
    Assert.isTrue(rate >= 0 && rate <= 1, "rate must be between 0 and 1: " + rate);
    return price * rate;
}

추가 예시: Apache Commons Validate

import org.apache.commons.lang3.Validate;

public String formatName(Customer customer) {
    Validate.notNull(customer, "customer must not be null");
    Validate.notBlank(customer.getFirstName(), "firstName must not be blank");
    return customer.getFirstName() + " " + customer.getLastName();
}

추가 예시: 사후 조건 (결과 검증)

public int allocateSlots(int requested, int available) {
    int allocated = Math.min(requested, available);
    Assert.isTrue(allocated >= 0, "allocated slots must not be negative: " + allocated);
    Assert.isTrue(allocated <= available, "allocated exceeds available: " + allocated + " > " + available);
    return allocated;
}

적용 기준

적용 대상

  • 메서드가 특정 조건을 가정하지만 명시하지 않은 경우
  • 내부 메서드(private/package-private)의 전제 조건
  • 계산 결과의 사후 조건 (결과값 범위 검증)
  • 알고리즘의 불변식 (invariant)
  • null이 아닌 것을 암묵적으로 가정하는 경우

적용 제외

  • public API의 입력 검증: assertion이 아니라 명시적 예외(IllegalArgumentException 등)를 사용해야 함
  • 비즈니스 규칙 검증: 도메인 로직으로 처리해야 할 것
  • 이미 Guard Clause나 예외로 처리된 조건: 중복
  • 외부 입력(사용자, API 응답): 시스템 경계는 명시적 검증 필요

주의사항

  • assertion 실패 = 프로그래머의 버그 (예상치 못한 상황)
  • 예외(Exception) = 예상 가능한 오류 상황 (사용자 입력 오류 등)
  • 이 구분이 모호하면 사용자에게 질문

OUTPUT FORMAT

실행 절차

공통 골격(대상 파일 수집 → 후보 제시(계열별 승인 규칙) → 적용 → 테스트 → 커밋/되돌리기, 브랜치·PR이 필요한 조건)은 이 스킬 디렉터리 기준 ../../references/refactoring-procedure.md가 정본이다. 아래는 이 기법에 고유한 부분만 규정한다.

사전 확인: 프로젝트 의존성 (공통 절차 1단계 앞)

# Gradle 프로젝트
grep -l "spring" build.gradle 2>/dev/null || grep -l "commons-lang3" build.gradle 2>/dev/null

# Maven 프로젝트
grep -l "spring" pom.xml 2>/dev/null || grep -l "commons-lang3" pom.xml 2>/dev/null

결과에 따라 assertion 도구를 선택하고 사용자에게 안내:

프로젝트에서 Spring 의존성이 감지되었습니다.
org.springframework.util.Assert를 사용합니다.

후보 식별 (공통 절차 2단계)

  • 암묵적 가정 패턴 탐지:
    • null 참조 없이 메서드 호출하는 경우
    • 범위 가정 (양수, 0~1, 비어있지 않음 등)
    • 상태 가정 (초기화 완료, 특정 상태 등)
  • 각 후보에 대해:
    • 파일명 및 라인 번호
    • 가정 내용 설명
    • 추가할 assertion 코드

후보 제시 예시 (공통 절차 3단계)

발견된 후보 3개 (Spring Assert 사용):

1. PricingService.java:20
   가정: price > 0, rate는 0~1
   → Assert.isTrue(price > 0, ...)
   → Assert.isTrue(rate >= 0 && rate <= 1, ...)

2. OrderProcessor.java:45
   가정: order != null, order.getItems() 비어있지 않음
   → Assert.notNull(order, ...)
   → Assert.notEmpty(order.getItems(), ...)

→ 승인 없이 적용 (Tidy 계열)

리팩토링 적용 (공통 절차 4단계)

  • import 문 추가
  • 메서드 시작 부분에 assertion 추가
  • (사후 조건인 경우) return 직전에 assertion 추가

커밋 메시지: refactor: introduce assertions in <클래스명> (공통 절차 6단계)

출력 예시

완료: Introduce Assertion (Spring Assert)

변경 내용:
- PricingService.java:20
  전제 조건: Assert.isTrue(price > 0), Assert.isTrue(rate >= 0 && rate <= 1)

- OrderProcessor.java:45
  전제 조건: Assert.notNull(order), Assert.notEmpty(order.getItems())

테스트: 모든 테스트 통과 (23 tests)
커밋: refactor: introduce assertions in PricingService, OrderProcessor

FAILURE CONDITIONS

공통 실패 조건(계열별 승인 규칙 위반, 테스트 실패 방치, 테스트 수정, 커밋 단위, git add -A, heredoc 한글 메시지)은 ../../references/refactoring-procedure.md에 있다. 아래는 이 기법에 고유한 것만.

  • 테스트가 실패함 (assertion 추가 후)
  • public API의 입력 검증에 assertion을 사용함 (예외를 써야 함)
  • Java assert 키워드를 사용함 (프로덕션 비활성화 위험)
  • 이미 Guard Clause로 보호된 조건에 중복 assertion 추가

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

동일한 결과를 내는 여러 조건문(OR 나열·중첩 AND)을 하나로 통합하고 의미 있는 boolean 메서드로 추출. "조건문 합쳐", "같은 결과 반환하는 if 정리", "중첩 if 평탄화", "/consolidate-conditional" 요청 시 사용. 단, 여러 메서드에 흩어진 동일 조건을 호출자 쪽으로 올리는 것은 /lift-up-conditional, 복잡한 조건식·분기를 메서드로 쪼개는 것은 /decompose-conditional이 적합. /consolidate-conditional [commit-ref]로 호출.

日本語の概要は準備中です。原文の説明を表示しています。

msbaek/msbaek-claude-plugins82026年10月1日 更新

기능의 external behavior를 Cucumber 인수 테스트(주 검증층)로 구축 — .feature 실행으로 문서↔코드 드리프트를 구조적으로 차단, Four Layer(Steps→Protocol Driver→SUT), 태그 기반 가역 제외, 기존 JUnit 인수 테스트 이관. "인수 테스트 도입", "Gherkin을 실행 가능하게", "cucumber 셋업" 요청 시 사용. /cucumber-acceptance로 호출.

日本語の概要は準備中です。原文の説明を表示しています。

msbaek/msbaek-claude-plugins82026年10月1日 更新

복잡한 if/then/else의 조건식과 각 분기를 의미 있는 메서드로 추출하여 가독성 향상. "조건문 분해", "if 가독성", "복잡한 조건식에 이름 붙여", "/decompose-conditional" 요청 시 사용. 단, 같은 결과를 내는 조건문들을 하나로 합치는 것은 /consolidate-conditional, 타입별 분기를 클래스로 바꾸는 것은 /replace-conditional-with-poly가 적합. /decompose-conditional [commit-ref]로 호출.

日本語の概要は準備中です。原文の説明を表示しています。

msbaek/msbaek-claude-plugins82026年10月1日 更新

Primitive Obsession 제거 — 검증·연산이 따라다니는 primitive 필드(금액+통화, 이메일 문자열 등)를 도메인 개념을 담은 Value Object로 치환. "값 객체 도입", "primitive obsession", "Money 클래스로", "/discover-value-object" 요청 시 사용. 단, 함께 전달되는 파라미터 묶음을 객체로 바꾸는 것은 /introduce-parameter-object, 컬렉션을 감싸는 것은 /first-class-collection이 적합. /discover-value-object [commit-ref]로 호출.

日本語の概要は準備中です。原文の説明を表示しています。

msbaek/msbaek-claude-plugins82026年10月1日 更新

컬렉션 getter가 내부 List/Set을 직접 노출하는 것을 방지 — unmodifiable 반환 + add/remove 메서드 제공. "컬렉션 캡슐화", "getter가 List 그대로 노출", "unmodifiable로", "/encapsulate-collection" 요청 시 사용. 단, 컬렉션과 관련 로직을 전용 클래스로 뽑는 것은 /first-class-collection이 적합. /encapsulate-collection [commit-ref]로 호출.

日本語の概要は準備中です。原文の説明を表示しています。

msbaek/msbaek-claude-plugins82026年10月1日 更新

암묵적 의존성(전역 변수·클래스 필드·싱글턴 접근)을 명시적 파라미터로 전환하여 메서드 투명성 향상. "숨은 의존성 드러내", "필드 대신 파라미터로", "전역 참조 제거", "/explicit-parameters" 요청 시 사용. 단, 파라미터가 많아져 묶어야 하면 /introduce-parameter-object, I/O와 계산 분리는 /segregate-functional-core가 적합. /explicit-parameters [commit-ref]로 호출.

日本語の概要は準備中です。原文の説明を表示しています。

msbaek/msbaek-claude-plugins82026年10月1日 更新

msbaek のスキルをすべて見る

このスキルの問題を報告する