검증 로직
Coddy Lua 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 70개 중 47번째.
지금까지 우리는 데이터를 보호하는 다양한 방법들을 살펴보았습니다. 명명 규칙은 의도를 나타내고, 클로저는 변수를 완전히 숨기며, 읽기 전용 테이블은 모든 수정을 방지합니다. 하지만 때로는 그 중간 단계의 무언가가 필요합니다. 바로 변경을 허용하되, 유효한 변경만 허용하는 방식입니다.
이것이 바로 setter 메서드가 강력해지는 지점입니다. 단순히 값을 할당하는 대신, setter는 새로운 값을 수락하기 전에 해당 값이 타당한지 확인할 수 있습니다:
local Person = {}
Person.__index = Person
function Person:new(name, age)
local obj = {
_name = name,
_age = age
}
setmetatable(obj, Person)
return obj
end
function Person:setAge(newAge)
if newAge < 0 then
print("Error: Age cannot be negative")
return
end
self._age = newAge
end누군가 person:setAge(-5)를 호출할 때, 메서드는 유효하지 않은 입력을 포착하고 업데이트를 거부합니다. 객체의 상태는 일관되게 유지됩니다. 이러한 보호 조치가 없다면, 잘못된 데이터가 프로그램에 조용히 손상을 입힐 수 있습니다. 음수 나이로 퇴직 연금을 계산하는 상황을 상상해 보세요.
유효성 검사는 필요에 따라 간단할 수도 있고 복잡할 수도 있습니다. 범위를 확인하거나, 타입을 검증하거나, 값이 예상된 형식과 일치하는지 확인할 수 있습니다. 핵심 원칙은 세터(setter)가 문지기 역할을 하여, 합리적인 데이터만 객체에 들어오도록 보장하는 것입니다.
챌린지
쉬움세터(setter) 메서드 내의 유효성 검사 로직을 사용하여 체력(health)과 레벨(level) 속성을 보호하는 Player 클래스를 만들어 봅시다! 이를 통해 게임 캐릭터가 불가능한 능력치를 갖지 않도록 보장할 수 있습니다.
코드는 두 개의 파일로 구성됩니다:
Player.lua: 적절한 유효성 검사를 통해 플레이어의 능력치를 관리하는 클래스를 생성합니다. 생성자:new(name)는 이름을 초기화하고,_health를100으로,_level을1로 설정해야 합니다. 다음 메서드들을 포함하세요::getName()— 플레이어의 이름을 반환합니다.:getHealth()— 현재 체력을 반환합니다.:getLevel()— 현재 레벨을 반환합니다.:setHealth(value)— 값이 0에서 100 사이(포함)인 경우에만 체력을 업데이트합니다. 유효하지 않은 경우,Error: Health must be between 0 and 100를 출력하고 값을 변경하지 않습니다.:setLevel(value)— 값이 1 이상인 경우에만 레벨을 업데이트합니다. 유효하지 않은 경우,Error: Level must be at least 1를 출력하고 값을 변경하지 않습니다.
main.lua: Player 모듈을 불러오고(require) 플레이어 이름과 세터를 테스트할 두 개의 값을 읽습니다. 플레이어를 생성하고, 첫 번째 값으로 체력을 설정하고, 두 번째 값으로 레벨 설정을 시도한 후 플레이어의 최종 능력치를 출력합니다.
세 가지 입력을 받게 됩니다:
- 플레이어의 이름
- 설정을 시도할 체력 값 (숫자, 유효할 수도 있고 유효하지 않을 수도 있음)
- 설정을 시도할 레벨 값 (숫자, 유효할 수도 있고 유효하지 않을 수도 있음)
출력에는 유효하지 않은 시도에 대한 오류 메시지가 표시되어야 하며, 이어서 플레이어의 최종 능력치가 표시되어야 합니다:
Name: {name}
Health: {finalHealth}
Level: {finalLevel}예를 들어, 입력값이 Hero, -20, 5라면 출력은 다음과 같아야 합니다:
Error: Health must be between 0 and 100
Name: Hero
Health: 100
Level: 5체력 세터는 -20을 거부하여(체력을 100으로 유지) 처리했고, 레벨 세터는 5를 유효한 값으로 받아들였습니다.
입력값이 Warrior, 75, 0이라면 출력은 다음과 같아야 합니다:
Error: Level must be at least 1
Name: Warrior
Health: 75
Level: 1치트 시트
Setter 메서드를 사용하면 객체 속성을 업데이트하기 전에 데이터를 검증하여 유효한 값만 수락되도록 보장할 수 있습니다.
검증 기능이 포함된 기본적인 setter:
function Person:setAge(newAge)
if newAge < 0 then
print("Error: Age cannot be negative")
return
end
self._age = newAge
endSetter는 게이트키퍼 역할을 합니다. 내부 속성을 업데이트하기 전에 새 값이 유효한지 확인합니다. 검증에 실패하면 오류를 출력하고 데이터를 수정하지 않은 채 조기에 반환합니다.
검증에는 다음이 포함될 수 있습니다:
- 범위 확인 (예: age >= 0)
- 경계 제한 (예: 0 <= health <= 100)
- 타입 확인
- 형식 검증
이를 통해 유효하지 않은 데이터가 객체의 상태를 손상시키는 것을 방지하고 프로그램의 일관성을 유지할 수 있습니다.
직접 해보기
-- Player 모듈을 불러옵니다
local Player = require('Player')
-- 입력을 읽습니다
local name = io.read()
local healthValue = tonumber(io.read())
local levelValue = tonumber(io.read())
-- TODO: 주어진 이름으로 새로운 플레이어를 생성합니다
-- TODO: 플레이어의 체력을 healthValue로 설정을 시도합니다
-- TODO: 플레이어의 레벨을 levelValue로 설정을 시도합니다
-- TODO: 플레이어의 최종 스탯을 다음 형식으로 출력합니다:
-- 이름: {name}
-- 체력: {finalHealth}
-- 레벨: {finalLevel}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.