MorzelProgramming

a programozásról

Ikon keresése

with one comment

 

Megakadt a szemem egy menüponton, a menüpont felirata: ‘Felhasználók egyesítése’. A hangulatom már egész jó volt úgyhogy neki is álltam ikont keresni neki. Kipróbáltam hogy az eredeti ikon helyett én vajon milyet is tennék a helyére.
Amikor végeztem, újfent megállapítottam hogy nincs semmi baj azzal hogy nem én vagyok _’A designer_, lássuk az eredményeket:

 

1.: Kedves, mosolygó emberkék:

01_Smiles

 

 

2.: Finoman utalunk arra hogy milyen nemű felhasználókat szeretnénk egyesíteni:

02_Sexes

 

 

3.: Finoman utalunk arra, hogy milyen nemű felhasználókat milyen módon szeretnénk egyesíteni:

03_SexesTogetherInLove

 

 

4.: Finoman utalunk arra, hogy egyszerre talán több felhasználót is szeretnénk egyesíteni:

04_GummyBears

 

 

5.: Pontosítunk, ha valakinek nem lett volna elég az előző verzió:

05_PeopleInLove

 

 

Tényleg nem értem miért nem mentem designernek…

Reklámok

Written by Morzel

augusztus 4, 2011 at 11:05 de.

LOL kategória

Asp.Net GridView–Sor kiválasztása kulcs alapján

leave a comment »

 

A minap kénytelen voltam egy oldal visszatöltésekor egy megadott azonosító alapján kiválasztani egy GridView az azonosítónak megfelelő sorát. Nos, mit is mondjak, ez annyira triviális mint a természetes levezetés (nem két ember bukott meg miatta logikából)…

 

A kényelmes megoldás: adatkötöttük a GridView-t, ismerjük a kulcsot valamint mivel adatkötöttünk, ismert az összes kulcs (igen, még a GridView számára is) és beállítjuk a SelectedDataKey tulajdonságot:

  1. grid.SelectedDataKey = …;

Király. ReadOnly, ne is próbálkozzunk.

 

Keresni kell megoldás: Van egy Rows nevű tulajdonságunk. Ez tartalmazza a GridView _összes_ sorát:

A GridViewRowCollection that contains all the data rows in a GridView control.

Király. Kár, hogy a lapozható gridem esetében 4 sorból áll egy lap, két oldal van, összesen 6 elem és a Rows kollekció számossága 4. Az is szomorú hogy az általam keresett kulcs a második lapon van. Itt megjegyzendő, hogy amennyiben a GridView nem lapozható, tökéletesen alkalmazható az a módszer, hogy megkeressük hogy melyik sorban van az adott kulcs, és ennek az indexére beállítjuk a táblázatunkat.

Továbbá megjegyzendő, hogy az előző állítás igaz a DataKeys tulajdonságra is.

 

 

Ezek után nézzük hogy mi az a tényleges megoldás, ami a számomra működött:

  1. public static void SelectRowByKey(string key, GridView grid)
  2. {
  3.     int idx;
  4.  
  5.     int i = 0, j = 0;
  6.  
  7.     while (j < grid.PageCount && null != grid.DataKeys[i].Value && grid.DataKeys[i].Value.ToString() != key)    /// A kulcsot itt is ellenorizni kell, különben a grid elso lapjának elso sorában nem adna vissza semmit sem.
  8.     {
  9.         grid.PageIndex = j++;   // Beállítjuk az aktuális lap sorszámát és növeljük a számláló értékét.
  10.         grid.DataBind();        // Ha nem bindolunk akkor a lapok (így az DataKeys értéke is) megmarad a hívási állapotban.
  11.         i = 0;
  12.         while (i < grid.DataKeys.Count && null != grid.DataKeys[i].Value && grid.DataKeys[i].Value.ToString() != key)   // Kulcs ellenorzése.
  13.             ++i;
  14.     }
  15.  
  16.     // Ha nem találtuk meg a keresett kulcsot akkor nem csinálunk semmit.
  17.     // Itt másik megoldás lehetne hogy kivételt dobunk, szerintem mindenki igazítsa a saját igényeihez.
  18.     if ((i == grid.DataKeys.Count && j == grid.PageCount) || (null != grid.DataKeys[i].Value && grid.DataKeys[i].Value.ToString() != key))
  19.         return;
  20.  
  21.     idx = i;
  22.  
  23.     //grid.PageIndex = idx / grid.PageSize;             // ezt már beállítottuk a keresés során. Mindenesetre jó fejben tartani hogy ezt is be kell állítani.
  24.     grid.SelectedIndex = idx;                           // beállítjuk az aktuális lapon az aktuális sort
  25.     grid.SelectedPersistedDataKey = grid.DataKeys[i];   // be kell állítani a kiválasztott kulcsot is
  26.  
  27.     grid.DataBind();/// Akkora kalap szar ez a gridview hogy ezt nehéz szavakkal kifejezni… Mindenesetre úgy tunik, databindból sosem elég. 😦
  28. }

A dallam viszonylag egyszerű. Laponként végignézzük a GridViewt és lap váltásonként DataBindolunk. Az élet szép. Így tudjuk frissíteni a DataKeys tulajdonság értékeit is.
Ha egyszer megtaláltuk a keresett sort, beállítjuk a SelectedIndex és a PersistedDataKey tulajdonságokat és DataBindolunk mivel már úgy belejöttünk. Ezt az utolsó DataBind kifejezést az istennek sem értem meg, szerintem mennie kéne nélküle is. Ennek ellenére ha kikommentezem a sort akkor szép HttpUnhandleExceptiont kapok.

 

Morzel

ui.:
Felhívás: Ha bárki tud értelmesebb, egyszerűbb, szebben kinéző, folyamatos DataBind() mentes megoldást, kérem ne tartsa vissza!

Written by Morzel

július 25, 2011 at 11:57 de.

Asp.Net, C# kategória

Sql szerver 2008 – Tempdb átmeneti táblák összegyűlhetnek tábla értékű változók használata esetén

leave a comment »

 

Ha sok tábla típusú változót használunk, észrevehetjük hogy a tempdb-ben a táblák száma hajlamos megnőni és előbb-utóbb azt vehetjük észre hogy a tempdb tele van ilyen generált nevekkel:

#782DD898
#7A16210A
#7B0A4543
#7CF28DB5
#7DE6B1EE
#7EDAD627
#7FCEFA60
#00C31E99
#01B742D2
#0493AF7D
#0587D3B6
#067BF7EF
#0958649A
#0B40AD0C
#0D28F57E

 

Így tudjuk lekérdezni a tempdb-ben található táblák listáját:

  1.  
  2. select * from tempdb.sys.tables
  3. order by create_date

 

Nézzük meg ezt a táblát: #7FCEFA60. Ezt természetesen az Sql szerver generálja, nem tudunk selectálni belőle és droppolni se lehet. Elméletileg a batch-ek futtatása során ezekbe vannak lementve a tábla értékű változók értékei. Természetesen ezeket az értékeket időnként szereti az Sql szerver cachelni is.

És természetesen ha már szereti cacheelni akkor nem szeret megszabadulni se tőlük. Én a fenti selectből ezeknek a tábláknak a create_date oszlopát szoktam figyelni. Előbb-utóbb azt lehet észrevenni hogy van a nap végén 3 bejegyzés ami az aktuális naphoz tartozik és 120 bejegyzés amik között akár több hetes is lehet.

Na, én ilyenkor szoktam szépen kipucolni a tempdb-t.

 

A tempdb kipucolása persze nyűgös dolog. Bár tudjuk hogy az sql szerver minden indításakor a tempdb újra felépül és így tiszta lappal kezdhetünk, nem sok ember teheti meg azt hogy leállítja az egész adatbázisszervert csak úgy, amikor kedve van. Mint írtam, droppolni kézzel nem tudjuk ezeket a táblákat.

 

Én az alábbi megoldást találtam:

  1. DBCC SHRINKDATABASE (tempdb)

 

A shrinknek van egy olyan jótékony hatása hogy ezeket a régi vackokat kitakarítja. Másik jótékony hatása meg hogy mehet teljesen online, a userek semmit se vesznek észre belőle, a tranzakcióinkat békében hagyja.

Én személy szerint azt csináltam hogy megfigyeltem hogy mennyi idő alatt éri el a régi és új átmeneti táblák aránya azt a szintet hogy már ne nagyon legyen hely az újaknak és betettem egy jobot ami ennyi időnként lefut (ez az én esetemben egy hét).

 

Megjegyzés: temp táblák használata esetében nem tapasztaltam hasonlót, azok gond nélkül kikerülnek a tempdb-ből használat után.

 

Morzel

Written by Morzel

július 13, 2011 at 9:17 de.

Hogyan készítsünk olyan skalár értékű függvényt, ami nem létező táblára hivatkozik?

leave a comment »

 

Egy mai szösszenet. Találtam egy érdekeset és készítettem egy rövid demót, örüljön mindenki. Lehet tippelni, mi az alábbi kis script futásának az eredménye?

  1. create function dbo.valami () returns int
  2. as begin
  3.     declare @result int
  4.     select top 1 @result = a from b
  5.     
  6.     return @result
  7. end
  8. go
  9.  
  10. drop function dbo.valami

 

Megjegyzés: Az igazi hatás akkor érhető el, ha nem rendelkezünk az adatbázisunkban ‘b’ nevezetű táblával.

 

Sql szerver verzió amin sikerült produkálni:

Microsoft SQL Server 2008 (SP2) – 10.0.4064.0 (Intel X86)   Feb 25 2011 14:22:23   Copyright (c) 1988-2008 Microsoft Corporation  Enterprise Edition on Windows NT 6.1 <X86> (Build 7601: Service Pack 1)

 

Morzel

Written by Morzel

július 1, 2011 at 7:19 de.

Session és Viewstate változók kezelése

leave a comment »

 

 

I. Session változók

A minap olvastam a CodeProject hírlevélben egy érdekes cikket, arról szólt hogy hogyan érdemes kikerülni azt a problémát, hogy a Session változókra string jelzőkkel hivatkozunk (tulajdonképpen mind a session, mind a ViewState kuls-érték párokat tartalmaz). A kulcs-érték párokkal stringes kulcs esetében tipikusan a legnagyobb probléma a folyamatos elgépelés és természetesen az, hogy ezen hibák futás időben derülnek ki.

Maga a cikkíró azt az elvet vallja, hogy enumokat hoz létre és a felsorolás elemeire való hivatkozással oldja meg az intellisense használatának kérdését. Érdekességként talán érdemes lehet elolvasni ezt is, bár véleményem szerint szörnyű megoldás. Egyszerűen nem tetszik. Persze ízlések és pofonok…

 

Az alternatívák között viszont a 4. (amit mellesleg az olvasók is a legjobb alternatívának értékeltek, egész pofás megközelítés:

 

1.: Készítsünk egy saját típust:

  1. public class SessionVariable<T>
  2. {
  3.     private string VariableName { get; set; }
  4.     private System.Web.SessionState.HttpSessionState Session { get; set; }
  5.     public T Value
  6.     {
  7.         get
  8.         {
  9.             object sessionValue = this.Session[this.VariableName];
  10.             if (sessionValue == null)
  11.             {
  12.                 sessionValue = default(T);
  13.             }
  14.             return (T)sessionValue;
  15.         }
  16.         set
  17.         {
  18.             this.Session[this.VariableName] = value;
  19.         }
  20.     }
  21.     public SessionVariable(string variableName,
  22.         System.Web.SessionState.HttpSessionState session)
  23.     {
  24.         this.VariableName = variableName;
  25.         this.Session = session;
  26.     }
  27. }

Ebben eddig nincs semmi extra. Készítünk egy típust amiben hivatkozunk az aktuális Sessionre és eltárolunk egy nevet a változónknak. A típus a Sessionból a VariableName alapján kezeli az adatainkat. Van egy konstruktorunk is, erre végülis az inicializáló kifejezések megléte óta már csak megszokásból van szükségünk.

 

2.: Kell egy helper class amiben inicializáljuk a változókat:

  1. public class SessionHelper
  2. {
  3.     public static void InitializeSessionVariables(object instance,
  4.         System.Web.SessionState.HttpSessionState session, string prefix)
  5.     {
  6.         foreach (var property in instance.GetType().GetProperties(
  7.             BindingFlags.Public | BindingFlags.Instance))
  8.         {
  9.             if (property.PropertyType.IsGenericType &&
  10.                 property.PropertyType.GetGenericTypeDefinition() ==
  11.                 typeof(SessionVariable<>))
  12.             {
  13.                 property.SetValue(instance, Activator.CreateInstance(
  14.                     property.PropertyType, prefix + property.Name, session),
  15.                     new object[] { });
  16.             }
  17.         }
  18.     }
  19. }

Itt látható a dolog hátránya. Sajnos a GetProperties metódus csak a publikus propertiket adja vissza nekünk. Így ez annyit jelent hogy ha propertit készítünk akkor annak publicnak kell lennie (Természetesen ha létrehozunk kézzel egy változót akkor használhatjuk a konstruktort is az inicializálásra).

 

3.: Az oldalunkon el kell helyeznünk egy inicializálási utasítást az OnInitben:

  1. using System;
  2.  
  3. namespace ServerVariables.Code
  4. {
  5.     public class BasePage : System.Web.UI.Page
  6.     {
  7.         protected override void OnInit(EventArgs e)
  8.         {
  9.             SessionHelper.InitializeSessionVariables(this, Session, this.Page.ToString());
  10.             
  11.          
  12.             base.OnInit(e);
  13.         }
  14.     }
  15. }

Jó szokáshoz híven erre készítek egy ősosztályt és majd ebből származtatom az oldalaimat. Így megúszom azt, hogy minden egyes oldalon bajlódnom kell a hívásokkal.

 

4.: Már csak egy oldalra van szükségünk ahova kipakolhatunk néhány változót:

  1. using System;
  2. using ServerVariables.Code;
  3.  
  4. namespace ServerVariables
  5. {
  6.     public partial class _Default : BasePage
  7.     {
  8.         public SessionVariable<string> SessionHello { get; set; }   // Mindenképpen public legyen
  9.         
  10.  
  11.         protected void Page_Load(object sender, EventArgs e)
  12.         {
  13.             SessionVariable<string> s = new SessionVariable<string>("s", this.Session); // itt már nem fontos a public láthatóság.
  14.             s.Value = "hmmm…";
  15.             
  16.  
  17.             SessionHello.Value = "Hello World";
  18.             
  19.             Response.Write(SessionHello.Value);
  20.         }
  21.     }
  22. }

Van változónk, a Sessionben van letárolva és sehol se látunk szöveges hivatkozást, csökkent az esély arra, hogy el fogjuk gépelni.

Ami hátrány, hogy ha a property nem public akkor bizony a változónk értéke null lesz és bármilyen Value tulajdonságra hivatkozva NullReferenceExceptiont kapunk.

Megjegyzendő hogy egy egyszerű code snippet segítségével gyakorlatilag elérhetjük hogy mindig ott legyen a public láthatósági módosító. Ezzel még tovább csökkenthetjük a félre gépelések valószínűségét.

 

II. ViewState változók

Felbuzdulva a Session változókon, úgy gondoltam hogy nekiállok ViewState változókat is kezelni. Nagy különbség nincsen, csak át kell nevezni pár dolgot.

1.: A ViewState használatához szükséges típus és annak a helper osztálya:

  1. public class ViewStateVariable<T>
  2. {
  3.     private string VariableName { get; set; }
  4.     private System.Web.UI.StateBag ViewState { get; set; }
  5.  
  6.     public T Value
  7.     {
  8.         get
  9.         {
  10.             object viewStateValue = this.ViewState[this.VariableName];
  11.             if (null == viewStateValue)
  12.             {
  13.                 viewStateValue = default(T);
  14.             }
  15.  
  16.             return (T)viewStateValue;
  17.         }
  18.         set
  19.         {
  20.             this.ViewState[this.VariableName] = value;
  21.         }
  22.     }
  23.  
  24.     public ViewStateVariable(string variableName, System.Web.UI.StateBag viewState)
  25.     {
  26.         this.VariableName = variableName;
  27.         this.ViewState = viewState;
  28.     }
  29. }
  30.  
  31. public class ViewStateHelper
  32. {
  33.     public static void InitializeViewStateVariables(object instance,
  34.         System.Web.UI.StateBag viewState, string prefix)
  35.     {
  36.         foreach (var property in instance.GetType().GetProperties(
  37.             BindingFlags.Public | BindingFlags.Instance))
  38.         {
  39.             if (property.PropertyType.IsGenericType &&
  40.                 property.PropertyType.GetGenericTypeDefinition() ==
  41.                 typeof(ViewStateVariable<>))
  42.             {
  43.                 property.SetValue(instance, Activator.CreateInstance(
  44.                     property.PropertyType, prefix + property.Name, viewState),
  45.                     new object[] { });
  46.             }
  47.         }
  48.     }
  49. }

 

2.: Ősosztály a Page-nek:

  1. using System;
  2.  
  3. namespace ServerVariables.Code
  4. {
  5.     public class BasePage : System.Web.UI.Page
  6.     {
  7.         protected override void OnInit(EventArgs e)
  8.         {
  9.             
  10.             ViewStateHelper.InitializeViewStateVariables(this, ViewState, this.Page.ToString());
  11.          
  12.             base.OnInit(e);
  13.         }
  14.     }
  15. }

 

5.: A változók használata megegyezik a Session változóinkkal. Az előnyök és hátrányok szintén ugyanazok.:

  1. using System;
  2. using ServerVariables.Code;
  3.  
  4. namespace ServerVariables
  5. {
  6.     public partial class _Default : BasePage
  7.     {
  8.         public SessionVariable<string> SessionHello { get; set; }   // Mindenképpen public legyen
  9.         public ViewStateVariable<int> ViewStateTheLifeUniverityAndEverything { get; set; }  // Mindenképpen public legyen
  10.  
  11.         protected void Page_Load(object sender, EventArgs e)
  12.         {
  13.             SessionVariable<string> s = new SessionVariable<string>("s", this.Session);
  14.             s.Value = "hmmm…";
  15.             ViewStateVariable<int> i = new ViewStateVariable<int>("i", this.ViewState);
  16.             i.Value = 42;
  17.  
  18.  
  19.             SessionHello.Value = "Hello World – ";
  20.             ViewStateTheLifeUniverityAndEverything.Value = 42;
  21.  
  22.  
  23.  
  24.             Response.Write(SessionHello.Value + ViewStateTheLifeUniverityAndEverything.Value.ToString());
  25.         }
  26.     }
  27. }

 

 

A teljes projekt természetesen letölthető a skydriveról.

 

Morzel

Written by Morzel

június 29, 2011 at 10:33 de.

Asp.Net, C# kategória

Mindig érdemes válaszolni a kérdésre?

3 hozzászólás

 

Éppen olvasom a 70-515-ös training kit anyagát és olvastam egy érdekes bekezdést Tony Northrup billentyűzetéből:

 

TonyNorthrup

 

Amikor olvastam, eszembe jutott hogy hányan tettek fel nekem már olyan kérdéseket amikből tisztán látszik hogy az adott technológia ‘bevezető hülyegyerekeknek 24 óra alatt’ irományait se voltak képesek a kezükbe venni (nemhogy komoly irodalmat) mielőtt nekiláttak a sok ezer soros projektjük kódolásának.

Persze ebben az esetben jönnek elő azok az emberek akik linq kifejezésekkel szenvednek de még azt se tudják hogy mi az az IEnumerable interface és persze e a példa csak a jéghegy csúcsa.

Most felmerült bennem a kérdés. Ilyen esetben vajon érdemes illetve szabad-e egyáltalán válaszolni a kérdezőnek? Tegyük fel hogy nem tud össze hozni egy linq selectet query expressionnel és a problémáján látszik hogy linq bevezető – 3. oldal – és már meg is van a megoldás. Ebben az esetben ha válaszolunk, valószínűleg a kérdező semmivel se fog többet tudni az eszközről amivel éppen dolgozik, csak elakadt egy soron és kell neki valami tűzoltás szerű segítség.

Kinek mik a tapasztalati, vajon mennyit lehet nyerni egy komolyabb projekten (mondjuk legyen minimum 100e sor) hogyha az ember először ráfordít egy kis időt és legalább a technológia alapjaival megismerkedik mintha beleugrunk a mély vízbe és a végén köpni-nyelni nem tudunk, annyi apró probléma merül fel?

Written by Morzel

június 20, 2011 at 9:57 de.

Learning kategória

Kódolási tanácsok

5 hozzászólás

 

Íme néhány, szerintem hasznos tanács amit talán érdemes megfogadni forráskódjaink gépelése során:

 

1.: Egyenlőség vizsgálat skalár értékkel:

  1. bool valami = true;
  2. if (valami = false)
  3.     return null;

 

Az, hogy elírás, nyilvánvaló. Ez sajnos bár warningot dob, lefordul. Ha az ember kicsit belegondol, egy-egy ilyen elírás hatalmas hibákhoz vezethet. Viszont ha megfordítjuk az egyenlőség vizsgálatot, akkor skalárnak nem adhatunk értéket, fordítási hiba. Így lett a futtatási hibából fordítási hiba:

  1. bool valami = true;
  2. if (false = valami)
  3.     return null;

 

2.: Blokk zárójelezés ciklusoknál, elágazásoknál:

Ciklusok, elágazások feje után akkor is tegyünk blokk zárójeleket ha csak egy utasításunk van. A legtöbb nyelv megengedi hogy ne tegyünk blokkot a fej után, de mindenképpen hasznos. Elég gyakran fordul elő hogy utólag oda kell biggyeszteni egy-két-három vagy sok utasítást és mivel emberek vagyunk, vagy eszünkbe jut ez, vagy nem:

  1. if (true == valami)
  2.     return null;

 

Ez így tökéletesen helyes. Eszünkbe jut hogy egy kiírást is tenni kellene ide:

  1. if (true == valami)
  2.     Console.WriteLine("valami");
  3.     return null;

 

Ez is helyes. Szintaktikailag. Az már más kérdés hogy most teljesen mást csinál a kódunk mint amit szeretnénk. Ha egyből bezárójeleztünk volna, most nem lenne probléma:

  1. if (true == valami)
  2. {
  3.     Console.WriteLine("valami");
  4.     return null;
  5. }

 

Számomra a tanulság az, hogy ha egyből kiteszem a blokk zárójeleket akkor utólag biztosan nem fogom elfelejteni őket.

 

3.: Pontosvessző a ciklusok, elágazások feje után:

Nem egyszer tanítottam már diákokat/hallgatókat a programozás alapjaira, és gyakori típushiba hogy valami úton-módon (pl. esti fáradság a sör mellett) sikerül egy pontosvesszőt tenni a ciklusok, elágazások feje után, közvetlenül az utasítások blokkja előtt:

  1. while (true == valami);
  2. {
  3.     Console.WriteLine("valami");
  4.     return null;
  5. }

 

Mint látható, a probléma egyértelmű. Cefet nehéz odafigyelni rá. Volt olyan kód, ahol már az egész algoritmust átnéztem a tanítvánnyal, mire megtaláltam. Ha azt vesszük észre hogy egy ciklus egyszer sem fut le akkor érdemes jobban odapislantani. Az ember szeme egyszerűen átsiklik felette. Programozók vagyunk, az üzleti logikára, az algoritmusra, a tartalomra figyelünk elsődlegesen. Nem az elgépelésekre.

Felderítése blokk zárójelek nélkül viszonylag egyszerű, minden IDE esetében van automatikus kód formázás, ilyenkor hamar kibukik:

Elírás, automatikus kódformázás előtt:

  1. while (true == valami);
  2.     Console.WriteLine("valami");

Elírás, automatikus kódformázás után:

  1. while (true == valami) ;
  2. Console.WriteLine("valami");

 

Mint látható, innentől kezdve már a kódra messziről ránézve látszik hogy hibás.

Persze blokk zárójelek használata esetében, a kód formázó meghagyja kódunkat a fenti, első formában. Ilyenkor ezzel sokat nem kezdhetünk, szemünket gubbasztjuk, debuggerezünk, keressük a hibát a szokásos módokon. Mindenesetre jó fejben tartani hogy ilyen is történhet.

 

4.: Automatikus formázás:

Időnként fórumokon megjelenik egy-egy okos emberke aki azt mondja hogy notepadben kell fejleszteni. Hát nekik egészségükre, aki nem látja be hogy egy jó IDE mennyi terhet vehet le az ember válláról, az szenvedjen csak egy sima szövegszerkesztővel.

A népszerűbb fejlesztői környezetek mindegyike képes automatikus kódformázásra. Ez mindössze annyit jelent hogy a programunk szerkezete alapján a tabokat szépen helyre teszi nekünk a fejlesztői környezet, így átláthatóbb lesz a kód. Visual Studio alatt az automatikus formázást a CTRL-K –> CTRL-F billenytűkombinációkkal használhatjuk. Itt megjegyezném hogy ha a formázás parancs kiadásának hatására nem történik semmi akkor vagy helyes a kódunk formázása, vagy olyan szintaktikai hiba van, ami ellehetetleníti (pl. kevesebb záró zárójel mint nyitó).

Forráskód automatikus formázás nélkül:

  1. while (true == valami)
  2. Console.WriteLine("valami");
  3. if (true == valami)
  4. Console.WriteLine("hello");
  5. {
  6. {
  7. }{
  8.  
  9. }}

Forráskód automatikus formázás után:

  1. while (true == valami)
  2.     Console.WriteLine("valami");
  3. if (true == valami)
  4.     Console.WriteLine("hello");
  5. {
  6.     {
  7.     }
  8.     {
  9.  
  10.     }
  11. }

 

 

5.: Típus megjelölése a kifejezésekben is.

Hasznos ha a kifejezések típusát nem fejből rakjuk össze amikor ránézünk hanem már eleve jelezzük a forráskódban azt. Persze, nyilván könnyen ki lehet számolni de sose felejtsük el a drága időt amikor hirtelen valamit meg kell keresnünk a fél éve írt kódunkba (én tipikusan arra sem emlékszem hogy tegnap pontosan mit kódoltam).

Nézzük ezt az egyszerű kódot:

  1. float a = 5;
  2. Console.WriteLine(a / 2);

 

Az eredmény 2.5, mint ahogy azt vártuk. Azonban ha csak a második sört nézzük akkor tippelnünk kell az eredmény típusára. Ezt lehet elősegíteni az alábbi módon:

  1. float a = 5;
  2. Console.WriteLine(a / 2.0);

 

Az eredmény megegyezik az előzővel. Egyetlen különbség hogy már a második sorra ránézve is meg tudjuk mondani az eredmény típusát (az tuti hogy lebegőpontos lesz).

Így persze még az előzőnél is szebb:

  1. float a = 5.0f;
  2. Console.WriteLine(a / 2.0f);

 

Hozzátenném ha a deklaráció mondjuk nem a művelet sorában lenne hanem mondjuk 10 sorral vagy 3 metódus hívással arrébb, akkor inkább így írnám:

  1. float a = 5.0f;
  2.  
  3.  
  4. Console.WriteLine(a / 2.0f);    //float

 

Megjegyzendő az ökölszabály: bármilyen kódot is írunk, minimálisra kell csökkenteni az időt amit majd szükség esetén a későbbi értelmezéssel töltünk el. Az iskolai példáknál még nem lehet különösebb gond, később amikor a főnök rákérdez valamire a két hónappal ezelőtt csináltakból, az információra nem egy óra múlva hanem tegnapra lesz szüksége. Szóval minél inkább olvasható a kódunk (és értelmezhető), annál hatékonyabbak leszünk a visszafejtésében amikor már mi is elfelejtettük hogy mit is akartunk csinálni.

 

6.: Kivétel biztos programozás:

Ez egy egyszerű szabály. Törekedjünk arra, hogy olyan kódot írjunk ami nem dobhat kivételt (vagy csak ellenőrzöttet). Arra gondolom nem kell kitérni hogy minden kivétel kezelve legyen, ezt mindenhol beleverik az emberbe. Viszont az is egy nézőpont lehet hogy minimalizáljuk a lehetséges kivételek számát.

Egy egyszerű példa, bekérünk egy egész számot és a user inputot int-é alakítjuk:

  1. try
  2. {
  3.     string input = Console.ReadLine();
  4.  
  5.     int i = int.Parse(input);
  6. }
  7. catch (Exception exc)
  8. {
  9.     Console.WriteLine("Hibás input!");
  10. }

 

Az iskolapélda után nézzük meg kivételek nélkül:

  1. string input = Console.ReadLine();
  2.  
  3. int i = -1;
  4.  
  5.  
  6. if (!int.TryParse(input, out i))
  7.     Console.WriteLine("Hibás input!");

Az eredmény ugyanaz, viszont nincs kivétel.

 

 

A fenti tanácsok betartása sokszor több gépelést jelent mint amennyit a lusta emberek megengednek maguknak. Cserébe viszont a forráskód könnyen átlátható, könnyen javítható és könnyen hiba kereshető lesz.

 

Morzel

Written by Morzel

június 6, 2011 at 9:41 de.

C#, Fejlesztéshez kategória