Category Archives: Uncategorized

Singleton unit tesztelése, avagy .NET-ben miért nem 12 hónapból áll az év?

Íme mai vizsgálódásunk tárgya:

public class Calendar
{
  private static Calendar _instance;

  public static Calendar Instance { ... }

  private Calendar() { }

  public string[] GetMonthNames()
  {
    string[] names = DateTimeFormatInfo.CurrentInfo.MonthNames;
    return Sorter.Alphabetically(names);
  }

  // És még sokan mások...
}

Két dolgot mindenképp érdemes ezen az osztályon megfigyelni: van egy GetMonthNames metódusa és követi a Singleton tervezési mintát. A kettő nyilván összefügg, a metódust Calendar.Instance.GetMonthNames() formában lehet meghívni.

Mivel ez egy nagyobb, korosabb kódbázis része, mielőtt nagyobb változtatásokba fogunk, írjunk unit teszteket a GetMonthNames függvényhez. És itt rögtön belefutunk abba a problémába, hogy nem tudjuk izolálni a metódust, bele van drótozva, hogy függ a DateTimeFormatInfo és a Sorter osztályoktól. Az előbbi a .NET Framework része, az utóbbit viszont én találtam ki, ugyanebben a projektben van:

public static class Sorter
{
  public static string[] Alphabetically(string[] values)
  {
    return values.OrderBy(v => v).ToArray();
  }
}

Alakítsuk át, de úgy, hogy a Calendar osztályban lévő 123 másik metódust, és az őket hívó kódot ne kelljen módosítani.

A függőséget írjuk le egy interfésszel, mert azt könnyű lesz mockolni:

public interface ISorter
{
  string[] Alphabetically(string[] values);
}

Implementáljuk úgy, hogy visszavezetjük a már meglévő, static megvalósításra:

public class SorterWrapper : ISorter
{
  public string[] Alphabetically(string[] values) => Sorter.Alphabetically(values);
}

Másként fogalmazva eddig annyit csináltunk, hogy a static implementációt becsomagoltuk egy példányosítható implementációba, amit egy interfésszel is le tudunk írni.

Mivel az eredeti Calendar osztály nyilvános interfészéhez nem akarunk hozzányúlni, vezessünk be újabb osztályt, amit én fantáziadúsan MonthManager-nek neveztem el:

public class MonthManager
{
  private ISorter _sorter;

  public MonthManager(ISorter sorter)
  {
    this._sorter = sorter;
  }

  public string[] GetMonthNames()
  {
    string[] names = DateTimeFormatInfo.CurrentInfo.MonthNames;
    return this._sorter.Alphabetically(names);
  }
}

Ez már egy kiválóan tesztelhető osztály, aminek a függőségét a konstruktoron keresztül meg lehet adni. (Az egyszerűség kedvéért a DateTimeFormatInfo függőséggel itt szándékosan nem foglalkozom.)

Módosítani kell természetesen az eredeti Calendar osztályt is, de szerencsére csak a belső implementációját, a publikus interfésze változatlan marad:

public class Calendar
{
  // Singleton...

  private MonthManager _monthManager;

  private Calendar()
  {
    ISorter sorter = new SorterWrapper();
    this._monthManager = new MonthManager(sorter);  
  }

  public string[] GetMonthNames()
  {
    return this._monthManager.GetMonthNames();
  }
}

Ehhez már könnyen írhatunk teszteket:

public class IdentitySorter : ISorter
{
  public string[] Alphabetically(string[] values) => values;
}

[TestClass]
public class CalendarTests
{
  [TestMethod]
  public void ShouldReturnTwelveMonths()
  {
    MonthManager mgr = new MonthManager(new IdentitySorter());
    string[] months = mgr.GetMonthNames();
    Assert.AreEqual(12, months.Length);
  }
}

Igazán kár, hogy ez a teszt hibát fog jelezni, méghozzá mindig! Látod a hibát?

Nem? Mert nincs is! Ez feature 🙂

A .NET Frameworkben lévő System.Globalization.Calendar osztályt úgy tervezték, hogy mindenféle naptárt le tudjon írni, van is 11 származtatott osztálya, köztük például a GregorianCalendar. Természetesen az egyes naptárak máshogy értelmezhetik a hónap fogalmát és ennek megfelelően más lehet a számuk is. Ennek a támogatását pedig úgy sikerült megoldani, hogy a DateTimeFormatInfo osztály MonthNames tulajdonsága CurrentCulture-tól függetlenül mindig 13 (!) elemű tömböt ad vissza, ami a mi naptárunk esetén a 12 hónap nevét jelenti, a 13. elem pedig egy üres string. Mindezért persze nem a .NET a felelős, így van ez a Win32 API-ban is (lásd LOCALE_SMONTHNAME13 konstans) már jó rég óta.

Advertisements

Add a tudásodat és az idődet: Honlap egy alapítványnak

Így karácsony előtt gyakran érkezik a telefonomra rejtett számról hívás, majd a következőhöz hasonló beszélgetés zajlik le:

– Én: Patológia, Doktor Mészáros.

– Ismeretlen hang a vonal túlsó végén: Őöööö, én Balássy György Miklóst keresem.

Mindezt általában szépen tagolva mondja, amiből az ember pontosan érzi, hogy most sikerült ezzel a névvel először találkoznia. Ha még azt is hozzáteszi, hogy “vagy feleségét”, esetleg, hogy “vagy bárkit a családban 18-68 év között”, akkor biztosan nem folytatjuk a beszélgetést.

– Én: Tájékoztatom, hogy a beszélgetést rögzítem. Mit mondjak, ki keresi és milyen ügyben?

Sokszor itt szakad meg a beszélgetés, de ekkor nem én szoktam letenni.

– Ő: Én XY vagyok és a WZ alapítvány számára gyűjtünk támogatást. Az alapítványunk beteg [gyermekek|állatok|számítógépvírusok] családjainak támogatásával foglalkozik és szeretném megkérdezni, hogy tudna-e minket támogatni. A ZS Kórháznak szeretnénk átadni egy nagyon fontos életmentő berendezést, de sajnos ez nagyon sokba kerül, ezért minden forintra szükségünk lenne.

Tegyük fel, hogy tetszik a dolog:

– Én: Rendben van, hogyan tudom támogatni az alapítványt?

– Ő: Meg tudom adni a számlaszámunkat, vagy tudunk küldeni postán csekket.

– Én: Erre semmi szükség, biztosan van egy honlapjuk, ahol mindez le van írva az alapítvány bemutatkozásával és alapító okiratával együtt. Ha átküldi nekem a weboldal címét, akkor biztosan nem fogom elfelejteni, de épp fel is tudom írni.

– Ő: Őöööö, hát mi nagyon kis alapítvány vagyunk, olyan kicsi a költségvetésünk, hogy még honlapunk sincs.

Na, ez az a pont, ahol a hívó biztosan elvágja magát nálam. Nem azért, mert olyan béna, hogy még weboldala sincs, hanem mert ezzel olyan hiteltelenné válik, hogy már nem akarom támogatni. Bármennyire nemes célt is szolgáljon egy alapítvány, az “alapítvány” fogalmat a kevéssé nemes szervezetek már lejáratták, ezért a jó célt szolgálóknak mindent meg kell tenniük azért, hogy hitelesnek tűnjenek. A weboldal ennek egy eszköze lehet, ha szerepel rajta:

  • Az alapítvány célja, bemutatkozása
  • Az alapítvány tagjai, a kurátorok, a felügyelő bizottság, a munkatársak
  • Az alapítvány elérhetőségei, névvel, címmel
  • Az alapító okirat
  • A bejegyzésről szóló bírósági végzés szkennelt változata (pecséttel, aláírással)
  • Az éves beszámoló és közhasznúsági jelentés
  • Adományozási lehetőségek: számlaszám, adhat.hu, 1%-os rendelkező nyilatkozat
  • Támogatók listája
  • Hírek, cikkek az alapítvány életéből, Rólunk írták rovat
  • Dokumentáció az alapítvány eredményeiről: képek és videók átadásokról, eseményekről, köszönőlevelek a kórházak igazgatóitól, gyerekrajzok

Természetesen, még ha mindez szerepel is egy weboldalon, akkor sem lehet teljesen kizárni, hogy kamu az egész, de legalább csökkentettük a kockázatot.

Segítsetek, mi legyen még rajta, amitől hitelesebbnek tűnik számotokra egy szervezet? (És itt most a jó fiúknak akarok segíteni, nem a zsiványoknak 🙂

És persze simán előfordulhat az is, hogy egy alapítványnak valóban kicsi a költségvetése, és nem engedhet meg magának egy olyan szakembert, aki össze tud rakni neki egy weboldalt. A karácsony remek alkalom, hogy ezen segítsünk:

Add a tudásodat és az idődet!

Válassz egy alapítványt, iskolát, jótékonysági szervezetet vagy bármilyen más non-profit intézményt, és segíts, hogy ők is hitelesen megjelenhessenek az interneten.

Ha értesz a weboldal-készítéshez, programozz! Ha weboldalak tervezéséhez értesz, dizájnolj! Ha szívesen videózol, készítsd el a bemutatkozó filmjüket! Ha van szkennered, digitalizáld az alapító irataikat! Ha szeretsz fotózni, kattintgass a következő eseményükön, átadásukon! Ha úgy érzed, hogy a dolog műszaki oldala nem neked való, de szívesen segítenél, akkor állítsd össze az oldal tartalmát!

Én szívesen elkészítem egy olyan jótékonysági alapítvány weboldalát, amely eddig még nem rendelkezett honlappal és a domain regisztráció első éves költségét is állom. Nem kell hozzá más, csak a tartalom! A honlapot létező nyilvános szolgáltatásokra fogom építeni (pl. YouTube) és az elkészült forráskódot nyilvánossá teszem, hogy mások is felhasználhassák.

Ha szeretnél egy ilyen honlapot az alapítványodnak, vagy szeretnél a munka oldalon betársulni, írj az alapitvany@balassy.info címre!

Ha tetszik az ötlet, oszd meg, ha pedig te is vállalsz hasonló feladatot, írd meg ide kommentbe!

 

Technorati Tags:

Git Extensions: Syntax error near unexpected token

Frissen telepített Git Extensionsben az első klónozáskor belefuthatunk az alábbi hibaüzenetbe:

git-credential

Ebből a hibaüzenet pontosan ez:

\"C:/Program Files (x86)/GitExtensions/GitCredentialWinStore/
git-credential-winstore.exe\" get: -c: line 0: 
syntax error near unexpected token `('

A problémát a C:\Users\<Felhasználónév>\.gitconfig fájlban kell keresnünk, azon belül is ez a sor az oka mindennek:

[credential]
helper = !\\\"C:/Program Files (x86)/GitExtensions/GitCredentialWinStore/git-credential-winstore.exe\\\"

A megoldás, hogy vegyünk ki a sor elejéről és a végéről is 2-2 backslasht, hogy csak 1-1 maradjon:

helper = !\"C:/Program Files (x86)/GitExtensions/GitCredentialWinStore/git-credential-winstore.exe\"

Így már működni fog.

 

Technorati-címkék: ,

.NET állásinterjú témák

Korábban írtam már C# állásinterjú kérdésekről és általános .NET architect kérdésekről is, de az az igazság, hogy egy állásinterjún ennél sokkal szélesebb témakörök jöhetnek elő. Persze lehet C#-ból is olyat kérdezni, ami talán nem mindennapos (például Shallow copy vs. deep copy), de az az igazság, hogy SQL-es vagy webes kérdések éppúgy előfordulhatnak.

Chandan Kumar Sinha, aki Indiában dolgozik szoftver fejlesztőként, ezért úgy gondolta, hogy nem egy véges listát ír az állásinterjú kérdésekről, hanem egy blogon folyamatosan teszi közzé a szerinte fontos témákat.

A .NET Interview Cracker blogon heti két-három bejegyzés születik, amelyekben eddig C#, .NET, SQL és web szolgáltatásokat érintett. A cikkek nem hosszúak, és nem is kérdéseket tartalmaznak, hanem inkább összefoglalják az adott témához tartozó legfontosabb tudnivalókat. Ez a formátum haladóbbaknak is hasznos lehet, segít feleleveníteni és rendszerezni a régen tanultakat.

 

Technorati-címkék: ,,,

Helyes névsorrend a Facebookon

Azt mondja a Facebook, hogy:

facebook-rudi-turo

Tévedés. Én Rudi Túrót nem ismerek, csakis kizárólag Túró Rudit. Hungaricum az istenadta.

Szerencsére a Facebookon át lehet állítani a vezetéknév és a keresztnév sorrendjét. Irány az Account Settings oldal:

facebook-account1

Majd a név melletti Edit link:

facebook-account2

Miután kinyílt a Name rovat, a Display as sorban tudjuk beállítani, hogy milyen sorrendben szeretnénk látni nevünk darabjait:

facebook-account3

Végül kattintás a Save changes gombra és már készen is vagyunk.

 

Technorati-címkék:

Gyakori PowerShell kérdések

Nem írok sűrűn PowerShell szkripteket, ezért van néhány olyan probléma, amibe gyakran belefutok. Íme a megoldásuk, hátha más is hasznát veszi:

Kommentezés

# Egysoros komment kettőskereszt után
<#
  Ez egy
  több soron 
  átnyúló megjegyzés
#>

Leírás

A Get-Help cmdlet által kiírandó leírás tartalmát a szkript elejére tett komment blokkban adhatjuk meg az alábbi formában:

<#
.SYNOPSIS
    Rövid leírás...    
.DESCRIPTION
    Hosszú leírás... 
.PARAMETER MyParam1
    A MyParam1 paraméter leírása...
.PARAMETER MyParam2
    A MyParam2 paraméter leírása...
.EXAMPLE
    C:\PS> .\MyScript.ps1 –MyParam1 "egy"  
Az első példa leírása... .EXAMPLE C:\PS> .\MyScript.ps1 –MyParam2 2012 A második példa leírása... .NOTES Egyéb megjegyzés, például szerző, dátum...
Author: György Balássy Date: 2012.07.11. #>

Bemeneti paraméterek

Egy szkript vagy függvény bemeneti paramétereit a Param kulcsszóval definiálhatjuk. A paramétereknek adhatunk alapértéket is:

Param(
    $MyParam1,
    $MyParam2 = 10
)

Paraméter validálás

A paramétereknél a .NET-es attribútumokhoz hasonló szintakszissal megadhatunk típust, illetve néhány kényszert is:

Param(
    [parameter(Mandatory=$true)]  
[string]
[ValidateScript({Test-Path $_ -PathType 'Container'})] $MyParam1, [parameter(Mandatory=$false)]
[int]
[ValidateRange(-1, 31)] $MyParam2 = 10 )

Ezeken az attribútumokon kívül van még ValidateLength, ValidateCount, ValidatePattern, ValidateNotNull, ValidateNotNullOrEmpty is.

Mappa létezésének ellenőrzése

A Test-Path cmdlet segítségével ellenőrizhetjük, hogy egy vagy több mappa vagy fájl (általánosabban: útvonal) létezik-e, vagy akár csak azt, hogy a megadott útvonal érvényes-e (ld. –IsValid kapcsoló). A cmdlet $true értékkel tér vissza, ha az adott útvonal létezik:

if( $myPath -ne $null -and ( Test-Path $myPath ) -eq $true )
{
    Remove-Item $myPath -Recurse
}

Szkript leállítása

Egy futó szkript leállítására használhatjuk az exit kulcsszót, ami után tetszőleges hibakódot megadhatunk. Ha hibajelzéssel akarjuk leállítani a szkriptet, akkor jobb a throw kulcsszót használni, ami után megadhatunk egy szöveges hibaüzenetet és ami 1 hibakóddal állítja le a szkript futását. Normál esetben a szkript 0 hibakóddal fejeződik be.

if( ( Test-Path $cmd ) -eq $false ) 
{
throw "A $cmd értéke nem megfelelő!"
}

Színes betűk a konzolra

Ha jobban el akarjuk különíteni a szkriptünk által kiírt üzeneteket a felhasznált cmdletek vagy külső programok üzeneteitől, akkor írhatunk színesen a konzolra:

Write-Host "Valami történik..." -ForegroundColor Green

Dátum formázása

Néha szükségünk van a mai dátumra, méghozzá valamilyen formátumban, amit előállíthatunk például így:

$now = Get-Date -format yyyyMMdd_HHmmss;

Kimenet elhallgattatása

A kimenet “némítására” parancssorban általában a >null átirányítást szoktuk használni, de tapasztalataim szerint ez egy PowerShell szkriptben nem mindig azt csinálja, amit szeretnénk. Ez esetben bátran használhatjuk az Out-Null cmdletet:

mkdir $targetDir | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("MyAssembly") | Out-Null

Module vagy snap-in betöltése

Találkoztam olyan PowerShell bővítménnyel, amit PowerShell 1.0 alatt snapinként, 2.0 alatt pedig modulként kellett betölteni. Szerencsére le tudjuk kérdezni a PowerShell verziószámát és megifelhetjük a betöltést:

if( $PSVersionTable.PSVersion.Major -ge 2 )
{
  Import-Module MyModule
}
else
{
   Add-PSSnapin MyModule
}

Lásd Using Modules and Snap-Ins.

SQL adatbázis mentése

SMO segítségével így menthetünk SQL adatbázist:

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoEnum")

$s = New-Object ("Microsoft.SqlServer.Management.Smo.Server") "(local)" 
$b = New-Object ("Microsoft.SqlServer.Management.Smo.Backup") $b.Action = "Database" $b.BackupSetDescription = "Full Northwind backup" $b.BackupSetName = "Northwind backup" $b.Database = "Northwind"
$b.MediaDescription = "Disk" $b.Devices.AddDevice("C:\Backup\MyBackup.bak", "File") $b.SqlBackup($s)

IIS konfiguráció mentése

Az IIS konfiguráció mentéséhez használhatjuk az IIS  PowerShell Snap-Int:

Import-Module WebAdministration   # vagy  Add-PSSnapin
Backup-WebConfiguration "MyBackupName"

Szövegfájl sorainak feldolgozása

Get-Content $filePath | Foreach-Object
{ 
  # Sor feldolgozása a $_ változóval
}

 

A PowerShell megismeréséhez nagyon hasznos forrás Soós Tibor Windows PowerShell 2.0 rendszergazdáknak c. könyve.

 

Technorati-címkék: ,,,

Állásinterjú: fejlesztői kompetenciák

Minden állásinterjú alapvető célja, hogy az interjúztató gyorsan képet kapjon a jelentkező képességeiről és tapasztalatairól. A szoftverfejlesztés nagyon sokrétű terület, aki most jelentkezik egy állásra vagy épp azt kapja feladatul, hogy egy pozícióra megfelelő embert találjon, bizony nehéz feladat előtt áll, amikor a szempontokat kell végiggondolnia. A Programmer Competency Matrix táblázat ebben nyújt segítséget, ugyanis öt csokorba szedi a témákat:

  • Computer science
  • Software engineering
  • Programming
  • Experience
  • Knowledge

Nekem azért tetszik ez a táblázat, mert minden témánál mutat egy fejlődési irányít, így mindenki ötleteket kaphat, hogy minek érdemes utánanéznie a hiányosságok pótlására.

A táblázat persze vitatható, én például egy “soft skills” témakört erősen hiányolok. Ti mit tennétek még bele?

 

Technorati-címkék: ,