Kurzusok
/
Julia
Julia
/
Feladatok
/
Gyári érzékelők
Gyári érzékelők

Gyári érzékelők

Tanulófeladat

Bevezetés

A programozók többnyire tökéletes szoftvert igyekeznek írni, és többnyire kudarcot vallanak.

A dolgok váratlanul elromlanak, és tudnunk kell kezelni az ilyen helyzeteket.

Egyes nyelvtervezők úgy gondolják, hogy a legfontosabb a hiba minél gyorsabb felismerése, majd a végrehajtás leállítása egy informatív üzenettel a hibakeresés segítésére.

Az adattudományi nyelvek hajlamosak árnyaltabb megközelítést választani. Egyes hibák olyan súlyosak, hogy az azonnali leállás szükséges, de gyakran jobb egy problémát később kezelendő dologként megjelölni, majd folytatni a végrehajtást.

A Semmisség fogalomban láttuk, hogy a Julia különféle helyőrzőket biztosít problémás értékekhez: missing, NaN és Inf. Az, hogy ezek jobb megközelítést jelentenek-e a program leállításánál egy adott helyzetben, a programozó megítélésének kérdése.

Egy megjegyzés a nevezéktanról mielőtt belemegyünk a részletekbe: a Julia dokumentációja a „hiba” és a „kivétel” szavakat nagyrészt felcserélhetőnek tekinti. Az alábbi tartalom is lehet ugyanilyen következetlen.

Szabványos hibatípusok

A tantervben eddig eljutva már biztosan láttál jó néhány hibaüzenetet a Juliától. Például:

julia> Int(3.14)
ERROR: InexactError: Int64(3.14)

Ha egy tizedes törtet egész számmá alakítunk, az pontosságvesztéssel jár, ezért InexactError hibát kapunk.

Az InexactError egy típus, amely a Juliába szabványosként beépített számos hiba egyike (jelenleg 25). Mind az Exception altípusai:

julia> supertype(InexactError)
Exception

throw()

A szabványos hibatípusok némelyike hasznos lehet, ha a saját kódodban szeretnéd előidézni.

Mint minden konkrét típusnak, a hibáknak is vannak konstruktoraik. Különféle argumentumokat fogadnak, ezért nézd meg a dokumentációt ahhoz, amelyiket használni szeretnéd.

julia> DomainError(42, "out of range")
DomainError(42, "out of range")

A hiba használatához csomagold a konstruktort egy throw() függvénybe:

julia> throw(DomainError(42, "out of range"))
ERROR: DomainError with 42:
out of range

error()

Ha gyorsan, kevésbé elegánsan akarsz megoldani valamit, az error() függvény kényelmes lehet. Egy stringet (vagy egy string összetevőit) vesz argumentumként:

julia> happy = false;
julia> happy || error("😞 something went wrong")
ERROR: 😞 something went wrong

Egyéni hibák

Új hibatípusokat létrehozni elvileg nagyon egyszerű. Egyszerűen vedd fel az Exception egy újabb altípusát:

julia> struct MyError <: Exception end

julia> throw(MyError)
ERROR: MyError

Állítások

Az állítás alapgondolata: „Ennek az állításnak igaznak kell lennie, ezért jelezd hangosan, ha hamis.” Ennek értéke főleg a hibakeresés során mutatkozik meg, mivel az éles kódnak soha nem szabad elbuknia egy állításon.

A Típusok fogalomban láttuk, hogy típusállításokat adhatunk hozzá, például egy függvény visszatérési típusának ellenőrzéséhez.

julia> 42::Number
42

julia> "two"::Number
ERROR: TypeError: in typeassert, expected Number, got a value of type String

Általánosabban a @assert makróval bármilyen olyan kifejezést tesztelhetünk, amely Boolean értéket ad:

julia> n = 22;
julia> @assert isodd(n) "n must be odd"
ERROR: AssertionError: n must be odd

try...catch

Egyes hibák szükségszerűen végzetesek, de gyakran azt várjuk, hogy a program kecsesen helyreálljon.

Alapértelmezés szerint egy hiba azonnal leállítja az aktuális függvényt, és a hiba (az esetleges informatív üzenettel együtt) átadódik a hívó függvénynek.

Ez folytatódik a hívási vermen felfelé, amíg a legfelső szintű kód le nem áll egy hibaüzenettel.

Bármelyik szakaszban elkapható a hiba egy try...catch blokkal, amely megpróbálja kezelni.

julia> n = -1;
julia> try
           log_n = log(n)
       catch problem
           if problem isa DomainError # number out of range
               # See next section for more on @warn and @info
               @warn "you may have supplied a negative real number: $n"
               @info "trying with complex argument"
               log_n = log(Complex(n))  # fallback calculation

           elseif problem isa MethodError # no idea what n is
               @error "please supply a valid argument"
 
           else
              rethrow() # the error could be anything else
           end
      end
┌ Warning: you may have supplied a negative real number: -1
└ @ Main REPL[3]:5
[ Info: trying with complex argument
0.0 + 3.141592653589793im  # success

A fenti példában a log(n) függvényhez n-nek vagy pozitív valós értéknek, vagy bármilyen komplex értéknek kell lennie. A try ... catch elkapja a negatív valós értékekkel kapcsolatos problémákat, és visszaadja a helyes komplex választ (iπ) matematikai jelöléssel.

Ha például egy string argumentumot adsz meg, nincs helyreállás, csak ha megkéred a felhasználót, hogy javítsa ki.

Végső mentőhálóként hozzáadtuk a rethrow() hívást minden olyan esethez, amely sem DomainError, sem MethodError.

Megjegyzés: Néha a try...catch az, amire szükséged van, de kérlek, kerüld a túlzott használatát. Ha helyette egy if...else blokk használható, az sokkal hatékonyabb lesz, mint a kivételek elkapása.

Naplózás

Ne keverd össze a fentebb tárgyalt error() függvényt a @error makróval.

A függvény kivételt hoz létre, amely elkapás híján felkerül a hívási vermen.

A @error makró, valamint a @debug, @info és @warn társai a Logging modul részei, és céljuk, hogy informatív üzeneteket hozzanak létre anélkül, hogy megváltoztatnák a program futását.

A kimenet alapértelmezés szerint a terminálra kerül (a súlyosság szerint színezve), bár egy valódi alkalmazásban sok más lehetőség is van.

julia> @warn "Something looks not quite right"
┌ Warning: Something looks not quite right
└ @ Main REPL[55]:1

julia> @error "Panic!"
┌ Error: Panic!
└ @ Main REPL[56]:1

Lásd még a korábbi példát a try...catch alatt.

Utasítások

Elena egy újságüzemben az új minőségügyi vezető. Mivel épp most érkezett a céghez, úgy döntött, hogy átnézi a gyár néhány folyamatát, hogy lássa, min lehetne javítani. Felfedezte, hogy a technikusok rengeteg minőségellenőrzést végeznek kézzel. Úgy látja, jó lehetőség kínálkozik az automatizálásra, ezért megkér téged, egy szabadúszó fejlesztőt, hogy fejlessz egy szoftvert néhány gép felügyeletére.

1. Ellenőrizd a helyiség páratartalmát

Az első feladatod, hogy írj egy szoftvert, amely a gyártóterem páratartalmát felügyeli. A cég szoftveréhez már csatlakozik egy érzékelő, amely rendszeresen visszaadja a helyiség páratartalmát százalékban.

A szoftverben meg kell valósítanod egy függvényt, amely hibát dob, ha a páratartalom túl magas. Ha a páratartalom elfogadható szinten van, egy Info naplóbejegyzés kerül hozzáadásra. A függvény neve humiditycheck legyen, és argumentumként a páratartalmat kapja meg.

Ha a százalék meghaladja a 70%-ot, állj le egy ErrorException hibával (a pontos üzenet nem fontos, de tartalmaznia kell a mért páratartalmat). Egyébként adj hozzá egy Info naplóbejegyzést a "humidity level check passed: h%" üzenettel, ahol a h a páratartalom százaléka.

julia> humiditycheck(60)
[ Info: humidity level check passed: 60%
julia> humiditycheck(100)
ERROR: humidity check failed: 100%

2. Ellenőrizd a túlmelegedést

Elena nagyon elégedett az első feladatoddal, és megkér, hogy foglalkozz a gépek hőmérsékletének felügyeletével. Miközben egy technikussal, Greggel beszélgetsz, megtudod, hogy ha egy gép hőmérséklete meghaladja az 500 °C-ot, a technikusok aggódni kezdenek a túlmelegedés miatt.

A gépet egy érzékelővel szerelték fel, amely a belső hőmérsékletét méri. Tudd, hogy az érzékelő nagyon érzékeny, és gyakran elromlik. Ilyenkor a technikusoknak ki kell cserélniük.

A feladatod, hogy megvalósíts egy temperaturecheck függvényt, amely argumentumként a hőmérsékletet kapja, és vagy naplóbejegyzést ad hozzá, ha minden rendben van, vagy hibát dob, ha az érzékelő elromlott, illetve ha a gép túlmelegedni kezd. Mivel később a hiba típusától függően másképp kell majd reagálnod, szükséged lesz egy mechanizmusra, amellyel meg tudod különböztetni a kétféle hibát.

  • Ha az érzékelő elromlott, a hőmérséklet nothing lesz. Ebben az esetben állj le egy ArgumentError hibával (az üzenet nem fontos).
  • Ha az érzékelő működik, és a hőmérséklet meghaladja az 500 °C-ot, dobj egy DomainError hibát, amely tartalmazza a mért hőmérsékletet.
  • Egyébként minden rendben van, ezért adj hozzá egy Info naplóbejegyzést a "temperature check passed: t °C" üzenettel, ahol a t a hőmérséklet.
julia> temperaturecheck(nothing)
ERROR: ArgumentError: sensor is broken

julia> temperaturecheck(800)
ERROR: DomainError with 800:
"overheating detected"

julia> temperaturecheck(500)
[ Info: temperature check passed: 500 °C

3. Definiálj egyéni hibát

A következő feladathoz definiálnod kell egy általánosabb, mindent elkapó hibát. A megvalósítás részletei nem fontosak azon túl, hogy hiba legyen, és hogy a neve MachineError legyen. Nyugodtan adhatsz hozzá mezőket és üzeneteket, ha az segít.

4. Felügyeld a gépet

Most, hogy a géped fel tudja ismerni a hibákat, és van egy egyéni MachineError hibád, hozzáadsz egy burkolófüggvényt, amely beszámol róla, hogy minden hogyan működik. Amellett, hogy visszaadja a korábbi függvények naplóbejegyzéseit, ennek a burkolófüggvénynek a fellépő hiba típusától (típusaitól) függően további naplóbejegyzéseket is hozzá kell adnia.

  • Ellenőrizd a páratartalmat és a hőmérsékletet.
  • Ha a páratartalom-ellenőrzés ErrorException hibát dob, egy Error naplóbejegyzést kell hozzáadni a "humidity level check failed: h%" üzenettel, ahol a h a páratartalom százaléka.
  • Ha a hőmérséklet-ellenőrzés ArgumentError hibát dob, egy Warn naplóbejegyzést kell hozzáadni a "sensor is broken" üzenettel.
  • Ha a hőmérséklet-ellenőrzés DomainError hibát dob, egy Error naplóbejegyzést kell hozzáadni a "overheating detected: t °C" üzenettel, ahol a t a hőmérséklet.
  • Ha az egyik vagy mindkét ellenőrzés sikertelen, a naplóbejegyzések hozzáadása után egyetlen MachineError hibát kell dobni.
  • Ha minden rendben van, csak a humiditycheck és a temperaturecheck naplóbejegyzései kerülnek hozzáadásra.

Valósítsd meg a machinemonitor() függvényt, amely argumentumként a páratartalmat és a hőmérsékletet kapja.

julia> machinemonitor(42, 450)
[ Info: humidity level check passed: 42%
[ Info: temperature check passed: 450 °C

julia> machinemonitor(42, 550)
[ Info: humidity level check passed: 42%
┌ Error: overheating detected: 550 °C
└ @ Main # output truncated

Error: MachineError

julia> machinemonitor(82, 521)
┌ Error: humidity level check failed: 82%
└ @ Main # output truncated
┌ Error: overheating detected: 521 °C
└ @ Main # output truncated

Error: MachineError

julia> machinemonitor(42, nothing)
[ Info: humidity level check passed: 42%
┌ Warning: sensor is broken
└ @ Main # output truncated

Error: MachineError
Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg
Julia Exercism

Készen állsz elkezdeni a(z) Gyári érzékelők feladatot?

Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Julia nyelvet 35 fogalom128 feladat segítségével, valódi emberi mentorálással, mindez ingyen.