Jó napot, jó kódolást!
Mai versenyzőnk a „hogyan írjunk instabil kódot” kategória dobogósa. Hangolódjunk rá a témára ezzel a frappáns képsorral:
Ezzel el is érkeztünk a témához – az inputok ellenőrzése. Lám az alábbi kódrészlet, milyen ártalmatlan:
...
_attributeInfoList = new List<AttrInfo>();
string attrs = AppConfigHelper.Get("AvidAttributes");
string[] al = attrs.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string s in al)
{
string[] ae = s.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
_attributeInfoList.Add(new AttrInfo() { attrScope = ae[0].Trim(), attrName = ae[1].Trim() });
}
_attributeList = new StringList();
foreach (AttrInfo ai in _attributeInfoList)
_attributeList.Add(ai.attrName);
...
Aki megtalálta benne a patás részletet, szokás szerint NEM kap pirospontot – ez a mi szintünkön elvárható.
A probléma akkor kezdődik, amikor történetesen eme kódrészlet egy olyan alkalmazásban hívódik meg, amiben nincsen definiálva az AvidAttributes nevű app setting.
Első körben a kód 3. sorában kapunk egy végzetes kivételt (lánykori neve ArgumentNullException).
Ha valami csoda folytán lenne ilyen setting, de nincs értéke, máris jobb lenne a helyzet.
Ámde itt nem áll meg a gépezet, hiszen ugye arról vagyunk híresek, hogy emberből vagyunk, és néha elgépelünk dolgokat.
Mondjuk nem kettőspontot használunk a fránya inputban, hanem vesszőt. Ebben az esetben a 6. sorban, ahol feltételezzük, hogy volt kettőspont a szövegben és ezért 2 elemű a tömbünk (hivatkozás: ae[1].Trim())
Nos, célszerű egy ellenőrzést beiktatni, valahogy így:
_attributeInfoList = new List<AttrInfo>();
string attrs = AppConfigHelper.Get("AvidAttributes");
if (null != attrs) // Ez a sor a lényeg
{
string[] al = attrs.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string s in al)
{
string[] ae = s.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
_attributeInfoList.Add(new AttrInfo() { attrScope = ae[0].Trim(), attrName = ae[1].Trim() });
}
_attributeList = new StringList();
foreach (AttrInfo ai in _attributeInfoList)
_attributeList.Add(ai.attrName);
}
Azután, ha tényleg tutira akarunk menni, csekkoljuk le, hogy valóban van 2 elemünk a második split után. A legvégén, valami ilyesmit kapunk:
_attributeInfoList = new List<AttrInfo>();
string attrs = AppConfigHelper.Get("AvidAttributes");
if (null != attrs)
{
string[] al = attrs.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string s in al)
{
string[] ae = s.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
if(ae.Length > 1)
{
_attributeInfoList.Add(new AttrInfo() { attrScope = ae[0].Trim(), attrName = ae[1].Trim() });
}else
{
_attributeInfoList.Add(new AttrInfo() { attrScope = ae[0].Trim(), attrName = string.Empty });
}
}
_attributeList = new StringList();
foreach (AttrInfo ai in _attributeInfoList)
_attributeList.Add(ai.attrName);
}
Itt nyilván a string.Empty helyett használhatunk értelmes default-ot, és illik is.
Tanulság
Röviden tehát a lényeg:
- SOSE bízzunk abban, hogy a felhasználó MEGAD egy input értéket
- SOSE bízzunk abban, hogy a felhasználó JÓL ad meg bármilyen input értéket
- Használjunk értelmes default értékeket