Menu
Coddy logo textTech

バリデーションロジック

CoddyのLuaジャーニー「Object Oriented Programming」セクションの一部 — レッスン 47/70。

これまで、データを保護するためのさまざまな方法を探索してきました。命名規則は意図を示し、クロージャは変数を完全に隠蔽し、読み取り専用テーブルはすべての変更を防ぎます。しかし、多くの場合、その中間のようなものが必要になります。それは、変更を許可しつつ、有効な変更のみを許可するというものです。

ここでセッターメソッドが強力になります。単に値を代入するのではなく、セッターは新しい値を受け入れる前に、その値が適切かどうかをチェックできます。

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) を呼び出すと、メソッドは無効な入力をキャッチし、更新を拒否します。オブジェクトの状態は一貫性を保ちます。この保護がないと、不正なデータによってプログラムが密かに破損する可能性があります。負の年齢で退職給付を計算することを想像してみてください。

バリデーション(検証)は、必要に応じて単純にすることも複雑にすることもできます。範囲をチェックしたり、型を検証したり、値が期待される形式に一致することを確認したりする場合があるでしょう。重要な原則は、セッターがゲートキーパー(門番)として機能し、適切なデータのみがオブジェクトに入るようにすることです。

challenge icon

チャレンジ

簡単

セッターメソッドのバリデーションロジックを使用して、体力(health)とレベル(level)の属性を保護する Player クラスを作成しましょう!これにより、ゲームキャラクターが不可能なステータスになるのを防ぐことができます。

コードは2つのファイルに分けて構成します:

  • Player.lua: 適切なバリデーションを行いながらプレイヤーのステータスを管理するクラスを作成します。コンストラクタ :new(name) は、名前、100 に設定された _health、および 1 に設定された _level でプレイヤーを初期化する必要があります。以下のメソッドを含めてください:
    • :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モジュールを読み込み、プレイヤー名と、セッターをテストするための2つの値を読み取ります。プレイヤーを作成し、1つ目の値で体力を設定し、2つ目の値でレベルを設定しようと試みた後、プレイヤーの最終的なステータスを出力します。

3つの入力を受け取ります:

  1. プレイヤーの名前
  2. 設定を試みる体力の値(数値、有効または無効な場合があります)
  3. 設定を試みるレベルの値(数値、有効または無効な場合があります)

出力には、無効な試行によるエラーメッセージを表示し、その後にプレイヤーの最終的なステータスを表示する必要があります:

Name: {name}
Health: {finalHealth}
Level: {finalLevel}

例えば、入力が Hero-205 の場合、出力は以下のようになります:

Error: Health must be between 0 and 100
Name: Hero
Health: 100
Level: 5

体力のセッターは -20 を拒否し(体力を100のまま維持)、レベルのセッターは 5 を有効として受け入れました。

入力が Warrior750 の場合、出力は以下のようになります:

Error: Level must be at least 1
Name: Warrior
Health: 75
Level: 1

チートシート

セッターメソッドを使用すると、オブジェクトのプロパティを更新する前にデータを検証し、有効な値のみが受け入れられるようにすることができます。

バリデーション(検証)機能を備えた基本的なセッターの例:

function Person:setAge(newAge)
    if newAge < 0 then
        print("Error: Age cannot be negative")
        return
    end
    self._age = newAge
end

セッターはゲートキーパー(門番)として機能します。内部プロパティを更新する前に、新しい値が有効かどうかをチェックします。バリデーションに失敗した場合は、エラーを出力し、データを変更せずに早期リターンします。

バリデーションには以下のようなものが含まれます:

  • 範囲チェック(例: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}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

Object Oriented Programmingのすべてのレッスン