Kurzusok
/
Elm
Elm
/
Feladatok
/
Biztonságos kincsesláda
Biztonságos kincsesláda

Biztonságos kincsesláda

Tanulófeladat

Bevezetés

Opaque típusok

Bevezetés

Az opaque típusok egy enkapszulációs technika az Elmben. Egyesek információelrejtésnek vagy az implementációs részletek elrejtésének is nevezik. Gyakran használják az érvényesítés kikényszerítésére is, a Parse, dont validate mintát követve. Például lehet egy EmailAddress opaque típusod, amely csak érvényes e-mail-címeket tartalmazhat (ellentétben a String-gel, amely bármit tartalmazhat).

Opaque típus létrehozása

A custom type-oknak egy vagy több változatuk van, és a fordító automatikusan létrehoz egy-egy függvényt minden változat létrehozásához, a változat nevének felhasználásával. Ez az egyetlen módja annak, hogy custom type-okat létrehozzunk. A fordító ezen változatok destrukturálását is lehetővé teszi.

type Maybe a
    = Nothing --> Variant implies a 'Nothing' function, with type 'Maybe a', and destructuring of 'Nothing'
    | Just a  --> Variant implies a 'Just' function, with type 'a -> Maybe a', and destructuring of 'Just _'

Alapértelmezés szerint mindez a fájlon / modulon belül marad, és az exposing kulcsszóval választjuk ki, mit exportálunk. Opaque típus létrehozásához egyszerűen csak nem exportálod a változatokat.

Amikor ezt teszed, szinte mindig szükség van egy másik módra a változatok létrehozásához és eléréséhez, méghozzá saját függvények exportálásával. Ezek a saját függvények lehetővé teszik, hogy valamilyen logikát alkalmazz a változatok létrehozásakor és elérésekor. Ez elrejti a modul belső implementációs részleteit, és azt jelenti, hogy az implementációs részleteket tetszés szerint módosíthatod, amíg az exportált függvények ugyanazok maradnak.

Parse, don't validate

Az opaque típusok talán leggyakoribb felhasználása az érvényesítés kikényszerítése a Parse, dont validate mintával. Ebben a mintában exportálsz egy függvényt, amely egy nálad kevésbé strukturált / típusbiztos bemenetet kap, például egy String-et, majd ezt egy strukturáltabb típussá alakítja, például EmailAddress-dé, és vagy visszaadja a típust, vagy hibát ad vissza (általában Maybe-t vagy Result-ot).

Például az alábbi kódban a külső modulok csak a parseEmailAddress függvénnyel hozhatnak létre EmailAddress típust, így amikor az EmailAddress típussal dolgozol, biztos lehetsz benne, hogy érvényes.

module EmailAddress exposing ( EmailAddress, parseEmailAddress, getEmailAddress )

-- The `EmailAddress` custom type has one variant, also called `EmailAddress`
-- When a custom type has one variant, it is idiomatic to use the same name for both.
type EmailAddress = 
  EmailAddress String

-- create an EmailAddress variant
parseEmailAddress: String -> Maybe EmailAddress
parseEmailAddress candidateEmailAddress =   
  if isValidEmailAddress candidateEmailAddress then
    Just (EmailAddress candidateEmailAddress)
  else
    Nothing

-- get an EmailAddress variant
getEmailAddress: EmailAddress -> String
getEmailAddress ( EmailAddress  emailAdress ) =
  emailAdress

isValidEmailAddress: String -> bool
-- ... 

Utasítások

Ebben a feladatban egy általános (varázslatos!) SecureTreasureChest-et fogsz írni, hogy némi kincset tárolj benne. A szemfüles tanulók észrevették, hogy a korábbi TreasureChest nem volt annyira biztonságos! Ha a getTreasure függvényt használtad, meg kellett adnod a jelszót, de a TreasureChest típust egyszerűen destrukturálva így is megszerezhetted a kincset, anélkül hogy ismerted volna a jelszót. Sőt, ami még rosszabb: ugyanígy magát a jelszót is kiolvashattad! Javítsuk ki ezt egy opaque típus használatával.

1. Definiáld a Password opaque típust a „Parse, don't validate” minta segítségével

Definiálj egy Password egyedi típust egyetlen változattal.

A változathoz tartozzon egy String érték, a jelszó.

A Password típust tedd közzé, a változatot viszont ne. Ettől a Password opaque típus lesz, és azt jelenti, hogy többé nem tudod destrukturálással megszerezni a jelszót. Azt, hogy egy típus opaque-e vagy sem, nem lehet tesztelni, ezért éles kódban a elm-review (egy statikus elemzőeszköz) segítségével kényszerítheted ki.

Definiálj és tegyél közzé egy createPassword függvényt típusdefinícióval, amely egy String-et vár és egy Maybe Password-t ad vissza.

Az Owasp azt javasolja, hogy a jelszavak legalább 8 karakter hosszúak legyenek, ezért a Parse, don't validate mintát használjuk ennek az invariánsnak a kikényszerítésére.

Ha a jelszó rövidebb 8 karakternél, a createPassword Nothing-ot adjon vissza, egyébként pedig Just Password-t.

2. Tedd közzé a SecureTreasureChest-et, de a változatát ne

A SecureTreasureChest típust tedd közzé, a változatát viszont ne. Ettől a SecureTreasureChest opaque típus lesz, és azt jelenti, hogy többé nem tudod destrukturálással megszerezni sem a jelszót, sem a kincset.

3. Definiáld a createTreasure függvényt

Ez a függvény két paramétert vegyen át, és legyen típusdefiníciója.

  • egy generikus típus (a kincsnek)
  • egy Password (a jelszónak)

A függvény egy SecureTreasureChest-et adjon vissza.

Tedd közzé ezt a függvényt, hogy más modulok is létre tudjanak hozni SecureTreasureChest példányokat.

4. Definiáld a getTreasure függvényt

Ez a függvény két paramétert vegyen át, és legyen típusdefiníciója.

  • egy String (a jelszónak)
  • egy SecureTreasureChest generikus egyedi típus

A függvény hasonlítsa össze a megadott jelszót a SecureTreasureChest-ben lévő Password-dal.

A függvény egy Maybe-t adjon vissza.

Ha a jelszavak megegyeznek, akkor a Just-ot add vissza a SecureTreasureChest-ben lévő generikus értékkel (a kinccsel!).

Ha a jelszavak nem egyeznek meg, akkor a Nothing-ot add vissza.

Tedd közzé ezt a függvényt, hogy más modulok is ki tudják venni a kincset a SecureTreasureChest-ből, feltéve hogy a helyes jelszót adják meg.

Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg
Elm Exercism

Készen állsz elkezdeni a(z) Biztonságos kincsesláda feladatot?

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