it-swarm-eu.dev

Měla by metoda ověřit její parametry?

Řekněme, že navrhujete metodu Square root. Dáváte přednost ověření, že předaný parametr není záporné číslo, nebo necháte volajícímu, aby se ujistil, že předaný parametr je platný. Jak se vaše odpověď liší, pokud je metoda/API určena pro spotřebu třetí stranou nebo pokud bude použita pouze pro konkrétní aplikaci, na které pracujete

Byl jsem toho názoru, že metoda by měla potvrdit svůj parametr, ale Pragmatic Programmer ve své sekci Návrh podle smlouvy (kapitola 4) říká, že je odpovědností volajícího předat dobrá data (str. 111 a 115) a navrhuje použít v této metodě tvrzení ověřit to samé. Chci vědět, co si o tom ostatní myslí.

44
Amit Wadhwa

Obecně navrhuji své API takto:
1. Dokumentujte metody dobře a povzbuzujte volající, aby předávali dobrá/platná data.
2. Ověření parametrů přesto! - vyvolání výjimek, pokud nejsou splněny předpoklady.

Řekl bych, že u většiny API orientovaných na veřejnost je nutné ověření parametrů. Ověření parametrů u neveřejných metod není tak důležité - je často žádoucí, aby k ověření došlo pouze jednou, ve veřejném „vstupním bodě“ - ale pokud můžete žít s potenciálním zásahem do výkonu, rád bych validoval parametry všude, protože to usnadňuje údržbu kódu a refaktoring.

34
Matthew King

Pokud vždy ověřujete parametry, děláte další práci, která nemusí být nutná.

Přemýšlejte o situaci, kdy byl vstup již ověřen před zahájením hovoru a nyní znovu ověřujete data v hovoru. OK jedna další ověřovací kontrola je v pořádku, ale nyní tuto logiku rozšířte na všechny funkce ve vaší aplikaci. Každé volání funkce potvrdí data, i když byla již dříve ověřena (nyní vícekrát).

Data by měla být ověřena na ONE point. To je místo, kde data vstupují do programu (nebo subsystému (to dává určitou volnost, protože definice subsystému může být flexibilní)). Pokud neexistují žádné programovací chyby, pak by váš kód měl nyní fungovat (Poznámka: tvrzení pro kontrolu chybného kódu se liší od ověřování parametrů).

Pokud opravdu chcete ověřit parametry, pak máte dvě verze funkce. Jeden k ověření a druhý k ověření. Podívejte se na std :: vector (operátor [] neověřuje, zatímco na () ověřuje).

Takže kdybych musel navrhnout funkci sqrt (), tak by ne validoval její vstupy, protože ve většině situací by data byla stejně dobrá a malá menšina situací, kde je potenciálně špatný, uživatel může proveďte rychlou kontrolu (podobně jako vstup uživatele by to mohlo být špatné a bylo by nutné jej před použitím ověřit). Jedinýkrát, co je špatné, je chyba programátora (a testy jednotek by je měly zachytit).

26
Martin York

Kolik redundance/robustnosti by měl komplexní software implementovat? zeptá se na související otázku.

Moje odpověď je, že funkce, které interagují s vnějším světem (veřejné API, metody uživatelského rozhraní, čtečky souborů atd.), By měly validovat vstup a informovat uživatele o chybách co možná zdvořile a nejjasněji. Chybová zpráva/návratový kód by měl přinejmenším uvádět, kde došlo ke špatnému zadání a jaký typ omezení byl porušen. Čím konkrétnější, tím lepší.

Na druhé straně soukromé funkce, které se zabývají pouze interně generovanými daty nebo daty již zpracovanými jednou z externích funkcí, by měly mít tvrzení o jakýchkoli předpokladech požadovaných pro úspěšné fungování. Pokud programátor zapíše kód, který je porušuje, měl by program selhat a tvrdě selhat. Tento typ chyby by jej nikdy neměl dostat přes počáteční fáze testování.

Motivací je zde být co nejpříjemnější pro uživatele a zároveň omezovat rozhodnutí o tom, jak zacházet se špatnými vstupy na co nejvyšší úroveň. Nechcete, aby jste přišli na další část strategie zpracování chyb na úrovni programu pokaždé, když napíšete funkci nízké úrovně.

Takže: ověřte vstup uživatele, potvrďte vstup programátora.

17
AShelly

Pokud máte typový systém, použijte jej.

Tvrzení pomohou chytit zlo brzy.

neúčinná omezení jsou rozumná věc.

sqrt (-1) není chyba v některých programovacích jazycích. Smalltalk s komplexní podporou čísel se vrátí i.

10
Tim Williscroft

Myslím, že to záleží na aplikaci metody, spíše než na teorii implementace.

Mám na mysli to, že pokud stavíte rychlou matematickou knihovnu, i když ji může použít kdokoli, nechcete mít běhové kontroly, alespoň ne když jsou zabudovány v režimu „uvolnění“, protože rychlost je posuzování kritérium. Kontroly můžete implementovat v režimu ladění pomocí tvrzení, protože chcete, aby bylo chování mezi režimy shodné. Samozřejmě byste chtěli dokumentovat takové chování velmi dobře, takže uživatelé vaší knihovny (i když jste to vy za tři měsíce!) Vědí, co kontroly mají by měli dělat.

Nyní, pokud vytváříte síťovou komunikační knihovnu, chcete přidat co nejvíce zabezpečení, protože 1) bude to krmeno převážně uživatelským vstupem, tedy nebezpečí 2) hrubý výkon bude vázán většinou síťovými I/O, ve většině případů ne operací CPU, takže ani přidání nějaké validace nebude ani zaznamenáno.

8
jv42

Každá funkce by měla ověřit svůj vstup, dokonce i ty vnitřní funkce, které nejsou součástí žádného API ani veřejného rozhraní.

Programátoři jsou lidé a lidé jsou notoricky neschopní udržovat související omezení v synchronizaci s tím, jak se vyvíjejí velké kódové základny - nakonec se část „check input“, ke které dojde před „call function“ , bude zmizí nebo se pohybují jinde nebo se stanou neúplnými a funkce bude volána s nesprávným vstupem. Když k tomu dojde, budou vaše dva hlavní cíle:

  • Zjištění problému co nejrychleji (nejlepší možností je kompilace)
  • Nic nepřerušujte, dokud nebude problém vyřešen

Pro mnoho věcí můžete použít jazykové funkce nebo typový systém pro přenos informací o tom, jaké vlastnosti byly ověřeny. To je extrémně rychlé (bez sankce za běhu) a detekuje chyby při kompilaci. Většina mých ověření je například v této kategorii.

Pokud váš jazyk nepodporuje ověření kompilace pro to, co děláte (což je v moderních jazycích docela vzácné), přidejte výraz run-time.

Pouze v případě, že by selhání vašeho kódu nemohlo mít nepříznivé důsledky za snadno detekovatelnou a neškodnou chybu a očekáváte, že tento kód bude vyvolán velmi často a ověření není přirozenou součástí kód funkce , můžete vynechat ověření. sqrt by tu pravděpodobně byl.

2
Victor Nicollet

Pro C/C++ a další jazyky, které poskytují funkční preprocesor, můžete validovat vstupní parametry pouze při vytváření pro ladění/testování a vytváření neověřeného sestavení vydání.

Visual C++ knihovna MFC je jedním z dobrých příkladů.

Níže je ukázkový kód z veřejných vzorků MFC:

void CServerNode::CalcBounding(CDC* pDC, CPoint& ptStart, CSize& sizeMax)
{
    ASSERT(sizeMax.cx >= 0 && sizeMax.cy >= 0);
    ASSERT(ptStart.x >= 0 && ptStart.y >= 0);

    CSize sizeNode;
    CalcNodeSize(pDC, sizeNode);

    ptStart.y += sizeNode.cy + CY_SEPARATOR;
    if (ptStart.y > sizeMax.cy)
        sizeMax.cy = ptStart.y;

    if (ptStart.x + sizeNode.cx > sizeMax.cx)
        sizeMax.cx = ptStart.x + sizeNode.cx;
    ptStart.x += CX_INDENT;
    // add in the kids
    if (!m_bHideChildren)
    {
        POSITION pos = m_listChild.GetHeadPosition();
        while (pos != NULL)
        {
            CServerNode* pNode = (CServerNode*)m_listChild.GetNext(pos);
            pNode->CalcBounding(pDC, ptStart, sizeMax);
        }
    }
    ptStart.x -= CX_INDENT;
}
2
9dan

Ověřování vždy uvádím v blízkosti zdroje příchozích dat, ať už jde o data z databáze, data z HTTP POST nebo data ze síťového soketu).

Důvody jsou následující:

  • snížení kódu
  • eliminace zbytečných operací
  • jednodušší kód (obvykle)

Vždy však existují výjimky z většiny programovacích pravidel nebo osvědčených postupů. Klíčem k rozpoznání těchto výjimek je pečlivé zamyšlení a zvážení každé situace, spíše než slepé dodržování souboru pravidel.

1
dietbuddha

Myslím si, že každá funkce by měla ověřit platnost vstupních parametrů, a je lepší, pokud ji lze ověřit při kompilaci (pomocí systému typů, pokud používáte staticky zadaný jazyk).

Myšlenka použití tvrzení, aby se zajistilo, že vstupní parametry jsou platné, se mi zdá trochu divná - v podstatě to znamená, že musíte stejné kontroly psát dvakrát - jednou ve funkci volajícího a podruhé v metodě sám ve formě tvrzení. To také znamená, že když se změní požadavky na vstupní parametry, budete muset změnit kontroly všude ve volajících funkcích, nejen v callee.

Proč tedy nejen validovat parametry v samotné metodě a vyvolat výjimku (nebo udělat cokoli, co je vhodné), když je zjištěna nekonzistence?

1
user21125

Vždy používám jednoduché schéma: UI a jednoduchý kód pro volání metod (Validate UI parametry) -> Metody (ověřuje ne UI parametry) -> Doplňkové funkce (nic neověřují)

0
cnd