0Pricing
Lua Academy · Ders

Yapılandırılmış Hata Nesneleri

Türü ve bağlamı aktarmak için tabloları hata nesnesi olarak geçirin.

Yapılandırılmış Hata Nesneleri, CoddyKit'te ücretsiz bir Lua Academy dersidir. Bu, 4 dersinin 4. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Lua Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Lua Academy kursu toplamda 4 dersten oluşur.

Yapılandırılmış Hatalar Neden Kullanılır?

Düz dize hatalarını program aracılığıyla işlemek zordur. Yapılandırılmış hata nesneleri (tablolar) tür bilgileri ve bağlam verileri taşır; çağıranlar tarafından incelenip işlenebilir. Bu, dize ayrıştırmaya gerek kalmadan hataya dayalı yönlendirme yapılmasını sağlar.

-- Plain string: hard to handle programmatically
error("database error: connection refused")

-- Structured: type + data
error({
  type = "DatabaseError",
  code = "CONN_REFUSED",
  host = "localhost",
  port = 5432,
  message = "connection refused"
})

Hata Oluşturucu Örüntüsü

Her hata türü için bir hata oluşturucu işlevi oluşturun. Oluşturucu, tutarlı alanlara sahip bir tablo oluşturur: tür, mesaj ve ilgili bağlam. Bir __tostring meta yöntemi, hatanın düzgün biçimde yazdırılmasını sağlar.

local ErrorMT = {__tostring = function(e)
  return string.format("[%s] %s", e.type, e.message)
end}

local function makeError(errType, msg, data)
  local e = {type=errType, message=msg}
  if data then for k,v in pairs(data) do e[k]=v end end
  return setmetatable(e, ErrorMT)
end

local E = {
  notFound = function(name) return makeError("NOT_FOUND","not found: "..name,{name=name}) end,
  badInput = function(msg,field) return makeError("BAD_INPUT",msg,{field=field}) end,
}

local ok, err = pcall(error, E.notFound("user:42"))
print(tostring(err))   -- [NOT_FOUND] not found: user:42

Hata Nesnelerinin Türünü Denetleme

Bir hatayı yakaladıktan sonra, bilinen bir tür alanına sahip bir tablo olup olmadığını denetleyin. Bu, dize örüntüsü eşleştirmesine güvenmeden hata türüne göre farklı kurtarma stratejileri seçmenizi sağlar.

local function handleRequest(fn)
  local ok, err = pcall(fn)
  if ok then return true end
  if type(err) == "table" then
    if err.type == "NOT_FOUND" then
      print("404: " .. err.message)
    elseif err.type == "BAD_INPUT" then
      print("400: " .. err.message .. " (field: " .. (err.field or "?") .. ")")
    else
      print("500: unhandled error: " .. tostring(err))
    end
  else
    print("500: " .. tostring(err))
  end
  return false
end

Hata Hiyerarşisi

is_a alanlarını denetleyerek veya meta tabloları kullanarak bir hata hiyerarşisini taklit edin. Alt hata türleri, üst türün alanlarını devralır ve ayrıntılara ihtiyaç duymayan kod tarafından üst tür olarak ele alınabilir.

local function isError(e, errType)
  if type(e) ~= "table" then return false end
  return e.type == errType or e.parentType == errType
end

local function makeDbError(code, msg)
  return {type="DbError:"..code, parentType="DbError", code=code, message=msg}
end

local err = makeDbError("TIMEOUT","query timed out")
print(isError(err, "DbError"))          -- true
print(isError(err, "DbError:TIMEOUT"))  -- true
print(isError(err, "NetworkError"))     -- false

Hataları Sarmalama

Yakalayıp yeniden fırlatırken, özgün hatayı kaybetmeden bağlam eklemek için onu sarın. Sarıcı kendi türüne sahiptir ve özgün hatayı neden olarak taşır.

local function wrapError(msg, cause)
  return {
    type = "WrappedError",
    message = msg,
    cause = cause,
  }
end

local function loadConfig(path)
  local ok, err = pcall(function()
    local f = assert(io.open(path,"r"))
    local content = f:read("a")
    f:close()
    return content
  end)
  if not ok then
    error(wrapError("failed to load config: "..path, err))
  end
end

local ok2, e = pcall(loadConfig, "missing.cfg")
if not ok2 then
  print(e.message)
  print("Caused by:", tostring(e.cause))
end

Hata Kodları ve Hata Türleri

Yaygın iki kural vardır: hata kodları (HTTP durum kodları gibi sayısal) ve hata türü dizeleri (anlamsal adlar). Hata kodlarını sayısal olarak karşılaştırmak kolaydır; tür dizeleri ise kendi anlamını açıkça belirtir. Birçok sistem ikisini birlikte kullanır.

local STATUS = {OK=200, NOT_FOUND=404, SERVER_ERROR=500, BAD_REQUEST=400}

local function makeStatusError(status, msg)
  return {status=status, message=msg, type="HTTPError"}
end

local function handleError(e)
  if e.status == STATUS.NOT_FOUND then
    print("Resource not found:", e.message)
  elseif e.status >= 500 then
    print("Server error:", e.message)
  else
    print("Error", e.status, e.message)
  end
end

handleError(makeStatusError(404, "user not found"))

Hata Yığını (Neden Zinciri)

Bir hata başka bir hatadan kaynaklandığında bunları zincirleyin. Bu, uygulamanın her katmanında neyin yanlış gittiğine dair eksiksiz bir görünüm sağlar. Hata zincirini açarak tüm hata öyküsünü günlüğe kaydedin veya görüntüleyin.

local function unwindCause(e, depth)
  depth = depth or 0
  local pad = string.rep("  ", depth)
  if type(e) == "table" then
    print(pad .. (e.type or "Error") .. ": " .. (e.message or "?"))
    if e.cause then unwindCause(e.cause, depth+1) end
  else
    print(pad .. tostring(e))
  end
end

local inner = {type="IoError", message="permission denied"}
local outer = {type="ConfigError", message="cannot load config", cause=inner}
unwindCause(outer)
-- ConfigError: cannot load config
--   IoError: permission denied

Geri Çağırma Bağlamında Hata

Geri çağırmaların (olay işleyicileri veya yineleyiciler gibi) içinde hatalar oluştuğunda, bu hatalar geri çağırmayı çağıran koda yayılır. Bunları yakalamak ve hangi geri çağırmanın başarısız olduğuna ilişkin bağlamla raporlamak için pcall kullanın.

local function runCallbacks(callbacks, data)
  local errors = {}
  for name, fn in pairs(callbacks) do
    local ok, err = pcall(fn, data)
    if not ok then
      errors[#errors+1] = {callback=name, error=err}
    end
  end
  return errors
end

local cbs = {
  validate = function(d) assert(d.name, "name required") end,
  transform = function(d) d.name = d.name:upper() end,
}

local errs = runCallbacks(cbs, {})
for _, e in ipairs(errs) do
  print(e.callback, "->", e.error)
end

Hata Ayrıntılarını Yazdırma

Hem dize hem de tablo türündeki hataları ele alarak bir hata nesnesini yapılandırılmış ve okunabilir biçimde yazdıran bir yardımcı oluşturun. Bu, hataların günlüğe kaydedildiği veya kullanıcılara gösterildiği uygulama sınırlarında kullanışlıdır.

local function printError(err, prefix)
  prefix = prefix or "Error"
  if type(err) ~= "table" then
    print(prefix .. ": " .. tostring(err))
    return
  end
  print(prefix .. " [" .. (err.type or "unknown") .. "]")
  print("  Message: " .. (err.message or "?"))
  for k, v in pairs(err) do
    if k ~= "type" and k ~= "message" and k ~= "cause" then
      print("  " .. k .. ": " .. tostring(v))
    end
  end
  if err.cause then printError(err.cause, "  Caused by") end
end

Yapılandırılmış Hatalarla Doğrulama

Düz bir dize yerine yapılandırılmış bir hata fırlatan bir assertT (tür bilgili assert) oluşturun. Bu, çağıran kodda belirli hata türlerini sınamayı kolaylaştırır.

local function assertT(cond, errType, msg, data)
  if not cond then
    local e = {type=errType, message=msg}
    if data then for k,v in pairs(data) do e[k]=v end end
    error(e, 2)
  end
  return cond
end

local function createUser(name, age)
  assertT(type(name)=="string", "BAD_INPUT", "name must be string", {field="name"})
  assertT(age >= 0 and age <= 150, "BAD_INPUT", "invalid age", {field="age", value=age})
  return {name=name, age=age}
end

local ok, err = pcall(createUser, "Alice", -5)
if not ok then print(err.type, err.field, err.value) end

Kısa Kontrol

error() işlevine dize yerine tablo geçirmenin temel avantajı nedir?

Özet: Yapılandırılmış Hatalar

Özet:

  • Yapılandırılmış ve incelenebilir hatalar için error() işlevine tablolar geçirin
  • Tür, mesaj ve ilgili bağlam alanlarını ekleyin
  • Okunabilir çıktı için __tostring ekleyin
  • Nedeni kaybetmeden bağlam eklemek için hataları sarın
  • İşleyicilerde tür yönlendirmesi yapın: dize örüntüleri yerine err.type denetleyin

Sıkça Sorulan Sorular

“Yapılandırılmış Hata Nesneleri” dersi ücretsiz mi?

Evet — “Yapılandırılmış Hata Nesneleri” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Lua Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Lua Academy kursu toplamda 4 dersten oluşur.

“Yapılandırılmış Hata Nesneleri” dersinde ne öğreneceğim?

Türü ve bağlamı aktarmak için tabloları hata nesnesi olarak geçirin. Lua Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

Lua Academy öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te Lua Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 4. dersidir.

“Yapılandırılmış Hata Nesneleri” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu Lua Academy dersinde kod yazıp çalıştırabilir miyim?

Evet. Her Lua Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. error() İşlevi
  2. pcall ile Korumalı Çağrılar
  3. xpcall ve İleti İşleyicileri
  4. Yapılandırılmış Hata Nesneleri
← Lua Academy Sayfasına Dön