Skip to main content

Posts

Showing posts from November, 2010

OR logic si AND logic - never say never

Mi-am adus aminte de o experienta nefericita pe care am avuto la începutului anului cu operatorii logici.
Era nevoie să fac debug pe un OR logic intre un ulong si un int.
int sursa1;
ulong sursa2;
Init(sursa1,sursa2);
ulong stare=sursa2 | sursa1;
Din pacate nu puteam sa folosesc enum. Era o aplicație vechie, care a fost portata de cineva in C# si era plina de erori de compilare. Nimeni nu cunoștea exact care sunt stariile in care se poate ajunge variabila stare si ce înseamnă fiecare stare.
Prima problema pe care o aveam era ca linia de cod care facea OR logic, codul nu compila deloc din cauza ca cele doua date( sursa1 si sursa2) erau de tipuri diferite. Eroarea pe care o primeam era "Operator | cannot be applied to operands of type int and ulong.". Era normal sa avem aceasta eroare, deoarece sursa2 era strict pozitiva, in comparație cu sursa1 care era o variabila cu semn(+/-).
Nici o problema am zis:
ulong stare= sursa2 | (ulong) sursa1;
Codul a compilat, aveam un warning legat de mo…

Covarianta si contravarianta in .NET 4.0

Covarianta si contravarinata au existat de la .NET 1.0. Schimbarea pe care a adus-o .NET 4.0 a fost ca a introdus aceste funcționalități si in tipurile generice.
In teorie, un tip T este mai mare decat S, daca si numai daca S este un subtip( derivat) din T.
Din acest enunt putem sa ajungem la concluzia ca exista o oarecare unitate de masura prin care se pot descrie tipurile( in forma unui arbore). Putem sa consideram ca T este clasa de baza, iar S este clasa derivata.
Covarianta: daca Generic este mai mare sau egal decat Generic. Covarianta se folosește in special cand vrem ca de la ceva generic sa ajungem la ceva mai particular.
Covarianta ne permite sa tratam un obiect ca si cum ar fi mai sus in ierarhie. Din aceasta cauza se ajunge ca proprietățile sa fie read-only din tipul generic.
De exemplu daca avem un tip de baza Animal si doua clase care moștenesc aceasta clasa( Caine, Sarpe), in mod normal nu am putea sa avem:
public class Animal{}
public class Caine:Animal{}
public class Sarpe:Ani…

OutputCache in master page NEVER

Aveam nevoie ca la un controler din master page sa seteze output cache. Declar acest lucru fara probleme si la compilare descopar spre surprinderea mea ca nu pot sa am output cache in master page. Nici o problema zic, il declar in fis. de configurare sub forma:
<caching>
<outputCache enableOutputCache="true" />
<outputCacheSettings>
<outputCacheProfiles>
<add duration="20" enabled="true" varyByController="numeControl"
name="AssetCacheProfile" />
</outputCacheProfiles>
</outputCacheSettings>
</caching>
Toate bune si frumoase, doar ca nu pot sa refer un output cache profile din master page. Asa ca ajung sa scriu intr-un Page de baza, din care toate aspx mostenesc ceva de genul:
Response.Cache.SetExpires(DateTime.Now.AddSeconds(20));
Response.Cache.SetCacheability(HttpCacheability.ServerAndPrivate);
Response.Cache.SetValidUntilExpires(true);
Intrebarea: De nu putem avea in mas…

Ce nu trebuie sa facem cand vrem sa masuram viteza de executie a unei zone de cod

Cand testam viteza de executie a unui aplicatii sau a unei parti din cod nu trebuie sa uitam:
Sa masuram doar codul care trebuie masurat
Cand trebuie sa verificam viteza de execuție a unei porțiuni din cod, trebuie sa încercam sa eliminam cat mai mult cu putința liniile de cod care nu ne interesează si care nu trebuie masurate.
De exemplu in codul de mai jos se doreste cronometrarea doar in zona in care se procesează datele, fara timpul necesar citirii datelor si inițializarea altor obiecte.
public void DoTest()
{
//Start monitorizare.

var items=ReadData();
var container=new Container();
container.Init();

//Proceseaza datele.
...

Save(items);

//Stop monitorizare
}
Corect ar fi:
public void DoTest()
{
var items=ReadData();
var container=new Container();
container.Init();

//Start monitorizare.
//Proceseaza datele.
//Stop monitorizare

Save(items);
}
Dezactivati mesajele de debug
Toate mesajele de genul Debug.Writeline("..."), Trace("..."), Logger.WriteLine("...") trebuie dezactivate. …

Ioc( Dependency Injection) - Teorie

Plecam de la principiul substitutiei a lui Liskovs:
Daca S este un subtip a lui T, atunci obiectul de tip T, in interiorul programului, poate sa fie înlocuit de obiectul de tip S fara sa se altereze funcționalitatea programului.
Sursa
Pe scurt, acesta se refera la faptul ca putem sa avem referinte la interfete si nu la tipuri concrete in interiorul aplicatiei, a.i. in orice moment putem sa înlocuim implementarea interfeței, fara a fi nevoiti sa schimbam codul.
Dependency injection se refera la faptul ca responsabilitatea initalizarii, construirii si a duratei de viata a unui obiect nu o are obiectul care contine referinta la obiectul nostru. Aceste elemente o sa fie controlate de catre un controler.
Exista trei tipuri prin care putem sa injectam dependentele prin:
constructor;proprietati;metode;Prima varianta este cea mai des folosita. Prin acest mecanism o sa putem fi siguri ca dependența a fost injectata in interiorul obiectului nostru. Daca vrem sa injectam prin proprietati atunci trebui…

Programare paralela in .NET 4.0

Plecam de la premiza ca avem o metoda care executa acelasi cod pentru fiecare element dintr-o colectie:
public bool CheckItem(Item item)
{
...
}
In mod natural am scrie:
foreach (Item item in items)
{
item.IsValid = CheckItem(item);
}

sau
items.ForEach(item=>CheckItem(item));
Am putea sa rulam paralel acest cod foarte usor, daca ne folosim de clasa ajutatoare Parallel:
Parallel.ForEach(items,new Action(item=>CheckItem(item)));
O varianta mai simpla in acest caz este sa scriem direct:
Parallel.ForEach(items,CheckItem);
Daca vrem sa parcurgem doar o parte din colectie putem sa scriem in felul urmator:
Parallel.For(0, 3, new Action(index => CheckItem(items[index])));
Atentie, daca lucrati cu stream-uri sau baze de date trebuie avut grija la close si dispose.
Problema este ceea ce se petrece in spate. N threaduri sunt folosite pentru linia de cod scrisa mai sus. Daca suntem pe client side, acest lucru nu este atat de important, dar daca suntem pe partea de server, putem avea mari probleme. De exemp…

Private Cloud - a devenit realitate

Microsoft a lansat private cloud. Incepand de acum nu mai trebuie sa punem datele in data center-ul Microsoft, toate discutiile despre securitatea datelor au fost inchise. Fizic toate datele le poti tine tu, pe serverele tale.
Ce ofera private cloud:
un mediu grafic unde sysadminii isi pot defini cum arata cloudul( serverele, baza de date, serverele web si de aplicatii, etc);se pot defini aplicațiile care o sa fie puse in cloud;Tot ce ne oferea Windows Azure ramane si la private cloud: autoservirea, scalabilitate pe orizontala, utlizarea unui sistem comun pentru toate operatiile necesare, balancer decuplat.
Blog sursa

Cat de puternic trebuie sa fie un framework sau o tehnologie ca sa schimbe ceva?

Problema se pune in felul următor: ce trebuie sa contina un framework sau o tehnologie ca sa schimbe ceva si sa fie folosit la scara mare?
Pornim de la cazuri reale:
MEF nu a avut un impact foarte mare - este greu sa convingi lumea sa folosesca recomandările tale, mai ales ca in fiecare firma exista deja un framework ajutator;EF nu a avut nici un impact major, NHibernate inca exista( NHibernate este deja un produs matur care a trecut de problema: ce a fost prima data. EF inca nu este un produs matur in totalitate, unele funcționalități inca lipsesc);ASP.NET MVC a batut tot, proiecte de gen MonoRail au fost rase;Prism - o aplicatie care a ajuns la o masa critica si incepe sa fie integrata de catre M$;
Exista proiecte care au nevoie de o masa critica pentru a reuși. De exemplu Oslo Project( cu limbaj M). Un proiect indraznet, in care M$ a investit foarte mult, dar din pacate a fost oprit. Acesta concureaza direct cu EF si nu a ajuns sa fie folosit atat de mult incat sa supraviețuiască.
Un l…

ASP.NET Sprites

Cand trebuie sa cream designul unui site avem nevoie de o mulțime de imagini. Pentru a scadea numarul de apeluri la server, putem sa încărcam aceste imagini inline( conținutul binar a imaginii se poate pune direct in HTML sau CSS, ca si in exemplul de mai jos:
.logo-png
{
width:310px;
height:155px;
text-decoration:none;
display:block;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAATYAAACb…
}
Dezavantajul la aceasta solutie este faptul ca doar browserele mai noi suporta acest lucru( IE8+,FF 3.5+). Daca trebuie sa incarcam pagini de dimensiuni mari atunci aceasta solutie nu este tocmai buna, deoarece utilizatorul trebuie sa astepte pana cand se incarca tot continutul pentru a putea afisa partial pagina.
Pentru a rezolva aceasta problema aparuta, imaginile se pot pune intr-o singura imagine, iar prin intermediul CSS-ului sa afisam doar o portiune din imagine. Click pentru mai multe informații.
Dar ar fi frumos sa putem pune toate imaginile intr-un singur director din proie…

Switch vs Dictionary

Revin cu cateva informatii suplimentare pe tema switch vs dictionary ca o continuare a postuluiPutem-sa-inlocuim-switch-case
In cazul in care avem un switch simplu care nu are nevoie sa sara de la un case la altul, codul IL care se genereaza in spate o sa fie foarte simplu si rapid. Se genereaza ceva de genul:IL_0002: ldloc.0
IL_0003: switch (
IL_0016,
IL_001e,
IL_0026)
IL_0014: br.s IL_002eDar cand de la un case se sare la un alt case deja IL generat se complica si ar fi bine sa se faca un review la cod. Codul generat mai jos este pentru un switch care are cateva case-uri goale( au fost adaugate doar pentru ca sa avem un cod cat mai readeable) si un case ce nu are break. In cazul acesta, pierderea de performanta este de aproape 50%. Sursa: http://weblogs.asp.net/justin_rogers/archive/2004/03/25/95806.aspxIL_0002: ldloc.0
IL_0003: switch (
IL_002e,
IL_0036,
IL_003e,
IL_0056,
IL_0056,
IL_0056,
IL_0056,
IL_0046,
IL_004e)
IL_002c: br.s IL_0056Pentru cazul acesta putem folosii dictionarul cu success. Pe p…

Putem sa inlocuim switch ... case ?

Sunt locuri in aplicatii unde suntem obligati sa scriem ceva de genul:
switch (value)
{
case "start":
...
break;
case "end":
...
break;
case "continue":
...
break;
default:
...
break;
}

M-am intrebat de mai multe ori daca am putea oare sa eliminam switch. Nu mi-a placut niciodata de acest "statement". Este foarte util, este usor de inteles, dar parca ar putea sa fi inlocuit cu altceva.
O solutie pe care pot sa o propun este inlocuirea acestuia cu un dictionar unde cheile sa reprezinta valorile posibile pe care le poate avea variabila, iar valorea din dictionar poate sa fie reprezentata de o functie anonima(lambda expression) sau de un pointer spre o metoda ce contine codul ce trebuie executat.

Toate bune si frumoase, o solutie perfecta pentru a scrie un cod "trendy" folosind ceea ce a adus nou .NET 3.5. Dar uitam un lucru de baza, performanta. Switch ... case este optimizat pentru asa ceva si orice am face, oricum am scrie, nu o sa putem inlocui un swit…

Cum sa facem debug si sa monitorizam o aplicatie ASP.NET de pe IIS.

De nenumărate ori, atat eu cat si voi am fost nevoiti sa facem debug pe aplicatii web. O sa incerc sa trec in revista modurile prin care se poate face debug la o aplicație web. Nu are importanta daca aceasta este ASP.NET sau MVC.
Pentru a activa debugul trebuie sa setam atributul debug cu valorea true in web config.
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
</configuration>
Daca vrem sa activam doar pe anumite pagini debug-ul putem sa setam atributul Debug a directivei Page pe true.
<%@ Page Debug="true" ... />
Sunt momente cand vrem doar pe masina locala( pe server) sa putem vedea mesajul de eroare, iar in cazul in care eroarea apare la un client sa afisam un mesaj standard. In acest caz putem seta atributul mode a nodului customErrors cu valoarea RemoteOnly.
<configuration>
<system.web>
<customErrors defaultRedirect="Eroare.aspx" mode="RemoteOnly…

Cum sa obtinem numele unei proprietati folosind lambda expression

Nu odată ne-am lovit de acesta problema. Cum sa transmit numele unei proprietăți ca si string, fara sa fiu obligat in cazul unei redenumiri sa nu trebuiasca sa caut prin tot codul.
O solutie este crearea unei clase de mapare, dar aceasta trebuie sa fie tot timpul adusa la zi. O alta solutie este sa folosim reflection. Putem sa ne cream un helper care sa rezolve problema, dar lucrurile se complica cand vrem rezultatul sa fie sub forma: "proprietateParinte.proprietateCopil".
Cei care folosesc MVC stiu ca acesta vine in ajutorul programatorilor cu ExpressionHelper.GetExpressionText(exprisieLambda). Acesta metoda este des folosita cand se lucreaza cu ViewModel. Dar ce ne facem daca nu suntem intr-o aplicatie ASP.NET MVC?
O solutie este sa luam expresia lambda si sa o descompunem. Prin acest mecanism putem sa iteram prin fiecare parte din expresie. Prin intermediul propietatii Bodyputem sa obtinem body-ul expresiei, iar in functie de tipul expresiei putem sa stim pe ce pozitie ne af…

Autofac 2.3

De cateva zile s-a lansat o noua versiune de Autofac( v. 2.3). Am dat jos ultima versiune si am inceput sa ma joc cu acesta si iata ce am descoperit:
Ce ne ofera Autofac:
dependency injection;inversion of control( IoC);suportat de diferite platforme( ASP.NET MVC, Silverlight, etc);Nu este atat de complex precum Windsor de la Castle Project, dar ofera functiile de baza de care am avea nevoie pentru un proiect de dimensiuni mici.
Iata cum se foloseste:
Clasa de baza prin care putem sa inregistram sau sa obtinem instance este "ContainerBuilder"
var autofac=new ContainerBuilder();
Pentru a inregistra putem folosi de metoda "Register".
autofac.Register(component=> new NumeClasa());
Pentru a obtine o componenta din container trebuie apelata metoda "Resolve":
autofac.Resolve<NumeClasa>();
In cazul in care constructorul clasei noastre are nevoie de anumiți parametrii care au fost deja înregistrați putem sa apelam metoda "Resolve" in momentul in care înre…

ASP.NET - Accesare controale si propietati din master page

Nu odată am avut nevoie să accesez un controller sau o proprietate din master page. Pentru propietati am cautat tot felul de artificii si clase ajutatoare care sa stocheze aceste date. In cazul controalelor am folosit metoda FindControl. Nici una din aceste metode nu este naturala si optima.
ASP.NET ne ofera posibilitatea de a declara un master type in content pages.
<%@ MasterType VirtualPath="~/locatie_master_page" %>
Prin aceasta metoda putem sa ne declaram proprietati in master page, pe care mai tarziu le putem apoi accesa din content pages. De exemplu daca in master page avem un controller pe care vrem sa il accesam din content page putem sa facem următoarea metoda:
//MasterPage
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="WA.SiteMaster" %>
...
<asp:Label id="Name" runat="server">Ionel</asp:Label>

//MasterPage Code Behind
public Label NameLabel { get; set…

Tuplu in C#, am luat taurul de coarne

Ce este un tuplu? Este o metoda de a grupa elemente de tipuri diferite. Apare mai ales in cadrul limbajelor funcționale sau dinamice precum Python.
De exemplu daca trebuie sa stocam coordonatele unui punct in spatiu putem sa avem (12,"C",23.3m). Fiecare axa poate sa aiba o unitate de masura diferita.
In C# 4.0 avem o clasa statica ajutatoare denumita Tuple, care ne ofera posibilitatea sa cream un tuplu cu pana la 8 tipuri generice( Tuple.Create(T1,..,T8) ).
Pentru exemplul de mai sus ar trebui sa avem urmatorul obiect:
var point=Tuple.Create<int,string,decimal)(12,"C",23.3m)

Daca vrem sa cream un tuplu care sa contina 23.3m si 40m pe axa 0z atunci putem sa cream un nou tuplu pe pozitia a 3-a.
var point=Tuple.Create(12,"C",new Tuple<decimal,decimal>(23.3m,40m)

Prin aceasta modalitate putem sa stocam coordonatele unor forme geometrice.
In cazul in care ajungem sa avem nevoie de un Tuplu cu mai mult de opt elemente generice atunci putem pe ultima pozitie de…