Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

أدوات التحقق والمساعدة

جزء من قسم البرمجة كائنية التوجه في رحلة R على Coddy. الدرس 5 من 57.

يتحقق المُنشئ من الأنواع؛ بينما يتحقق المُدقِّق من القيم. وفقًا للعرف، تأخذ validate_money() كائنًا، وتستدعي stop() برسالة واضحة لكل قاعدة يخالفها، وتُعيد الكائن عندما يكون كل شيء على ما يرام. تحافظ call. = FALSE على استبعاد استدعاء الدالة من الرسالة:

new_money <- function(amount = double(), currency = character()) {
  stopifnot(is.double(amount), is.character(currency))
  structure(list(amount = amount, currency = currency), class = "money")
}
validate_money <- function(x) {
  if (x$amount < 0) stop("amount must not be negative", call. = FALSE)
  if (nchar(x$currency) != 3) stop("currency must have 3 letters", call. = FALSE)
  x
}
m <- validate_money(new_money(-5, "EUR"))

الناتج:

Error: amount must not be negative
Execution halted

إن المساعد هو الدالة التي تستدعيها تعليمات برمجية أخرى. وتُسمّى باسم الفئة، وتحول مدخلاتها إلى الأنواع الصحيحة، وتملأ القيم الافتراضية، وتمرر النتيجة عبر المُنشئ ومدقّق الصحة:

new_money <- function(amount = double(), currency = character()) {
  stopifnot(is.double(amount), is.character(currency))
  structure(list(amount = amount, currency = currency), class = "money")
}
validate_money <- function(x) {
  if (x$amount < 0) stop("amount must not be negative", call. = FALSE)
  x
}
money <- function(amount, currency = "EUR") {
  validate_money(new_money(as.double(amount), toupper(currency)))
}
m <- money("12", "usd")
cat(m$amount, m$currency)

الناتج:

12 USD

يلتقط الكود الذي يقرأ إدخال المستخدم أخطاء أداة التحقق باستخدام tryCatch() ويعرض conditionMessage(e)، وهو النص المُمرَّر إلى stop():

validate_age <- function(x) {
  if (x$years < 0) stop("age must not be negative", call. = FALSE)
  if (x$years > 150) stop("age is too large", call. = FALSE)
  x
}
age <- function(years) validate_age(structure(list(years = as.double(years)), class = "age"))
for (input in c("30", "-2", "200")) {
  result <- tryCatch(paste("ok", age(input)$years), error = function(e) conditionMessage(e))
  cat(result, "\n")
}

الناتج:

ok 30 
age must not be negative 
age is too large 

لكل واحدة من الدوال الثلاث مهمة واحدة. new_money() صارمة وسريعة، ومخصّصة للتعليمات البرمجية التي تحتوي بالفعل على الأنواع الصحيحة. validate_money() تتولى القواعد المتعلقة بالقيم، والتي قد تكون بطيئة أو كثيرة. money() ودودة، وهي ما يستخدمه باقي البرنامج:

new_money()       # أنواع فقط؛ يبني الكائن باستخدام structure()
validate_money()  # قواعد القيمة؛ stop() مع رسالة، وإلا أرجع x
money()           # يحول المدخل، ثم validate_money(new_money(...))
challenge icon

التحدي

سهل

تُنشئ new_score(points, max) في Score.R كائن score. أكمل الدوال الأخرى في الملف نفسه:

  • تتوقف validate_score(x) مع points must not be negative أو max must be positive أو points must not exceed max، مع التحقق منها بهذا الترتيب، وإلا تُرجع x.
  • تحوّل score(points, max = 100) الوسيطتين باستخدام as.double() وتُرجع validate_score(new_score(...)).
  • تُرجع format.score(x, ...) القيمة 45/50 (90%)، مع تقريب النسبة المئوية إلى عدد صحيح.

استخدم call. = FALSE في كل استدعاء لـ stop(). يقرأ الكود المُزوَّد الأسطر 45 50، ويطبع النتيجة المنسَّقة، أو error: والرسالة.

ضع الكود في Score.R. يحتوي main.R على كود الإدخال/الإخراج المُزوَّد، ولا يمكن تعديله.

جرّب بنفسك

source("Score.R")

# كود الإدخال/الإخراج المُزوَّد: أبقه كما هو
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  s <- tryCatch(score(p[1], p[2]), error = function(e) conditionMessage(e))
  if (is.character(s)) cat("error: ", s, "\n", sep = "") else cat(format(s), "\n", sep = "")
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم R عبر الإنترنت