Menu
CoddyTech

Trình xác thực và hàm hỗ trợ

Thuộc phần Lập trình hướng đối tượng trong hành trình R của Coddy. Bài học 5 trên 57.

Hàm khởi tạo kiểm tra kiểu dữ liệu, còn bộ kiểm tra xác thực giá trị. Theo quy ước, validate_money() nhận một đối tượng, gọi stop() kèm thông báo rõ ràng cho từng quy tắc mà đối tượng vi phạm, rồi trả về đối tượng nếu mọi thứ đều ổn. call. = FALSE giúp loại lời gọi hàm khỏi thông báo:

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"))

Đầu ra:

Error: amount must not be negative
Execution halted

Hàm trợ giúp là hàm mà code khác gọi. Hàm này được đặt tên theo lớp, chuyển đầu vào sang đúng kiểu dữ liệu, điền các giá trị mặc định và truyền kết quả qua hàm khởi tạo cùng hàm xác thực:

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)

Đầu ra:

12 USD

Code đọc dữ liệu đầu vào của người dùng bắt lỗi của hàm kiểm tra với tryCatch() và hiển thị conditionMessage(e), văn bản được truyền vào 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")
}

Đầu ra:

ok 30 
age must not be negative 
age is too large 

Mỗi hàm có một nhiệm vụ. new_money() nghiêm ngặt và nhanh, dành cho code đã có đúng kiểu dữ liệu. validate_money() chứa các quy tắc về giá trị, có thể chậm hoặc nhiều. money() thân thiện và là hàm mà phần còn lại của chương trình sử dụng:

new_money()       # Chỉ kiểm tra kiểu dữ liệu; tạo đối tượng bằng structure()
validate_money()  # Kiểm tra giá trị; gọi stop() kèm thông báo nếu không hợp lệ, nếu không thì trả về x
money()           # Chuyển đổi đầu vào, rồi gọi validate_money(new_money(...))
challenge icon

Thử thách

Dễ

new_score(points, max) trong Score.R tạo một đối tượng score. Hoàn thiện các hàm còn lại trong cùng tệp:

  • validate_score(x) dừng lại với thông báo points must not be negative, max must be positive hoặc points must not exceed max, theo đúng thứ tự kiểm tra đó, nếu không thì trả về x.
  • score(points, max = 100) chuyển đổi cả hai đối số bằng as.double() và trả về validate_score(new_score(...)).
  • format.score(x, ...) trả về 45/50 (90%), với phần trăm được làm tròn đến số nguyên.

Dùng call. = FALSE trong mọi stop(). Code được cung cấp đọc các dòng 45 50, in điểm đã định dạng hoặc error: cùng với thông báo.

Viết code trong Score.R. main.R chứa code đầu vào/đầu ra được cung cấp và bạn không thể chỉnh sửa tệp này.

Tự làm thử

source("Score.R")

# Đoạn code đầu vào/đầu ra được cung cấp sẵn: giữ nguyên
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 iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch R online