Web Dev »

[1 vlj 2012 | 0 Comments]

sqlmigrationJedna od čestih tehnika rada sa bazom, obavezna u ozbiljnijim firmama sa programerskim timovima, ali i popularizirana u Ruby on Railsu, je izrada migracijskih skripti. Radi se o kontinuiranoj izradi skripti koje upravljaju sa shemom baze. Drugim riječima, ne smije direktno mijenjati baza, jer se time izgube informacije tko je, kada i što promijenio, nego se rade kratke skripte, i svaka se nazove ili notira datumom (timestamp-om). Da bi se baza kreirala, dovoljno je pokrenuti sve skripte.

Jedan način izrade migracijskih skripti je pisanje SQL-a unutar običnih textualnih (.sql) fajlova, koje je moguće izvršiti u SQL Management Studio, ili nekom drugom alatu. Da bi automatizirali to, pratili u kojoj je “verziji” naša baza (koja je zadnja skripta izvršena), trebati će nam neki alat. U .NET svijetu ih ima nekoliko. Svi oni rade na slični princip, stoga opisana procedura ovdje vrijedi i za ostale alate. Pokazati ću rad sa FluentMigratorom, kojega ja upotrebljavam u svojim web projektima.

Ovaj alat je C# apstrakcija nad generiranjem SQL skripti i baze podataka, što znači da se koristi fluent API za kreiranje skripti, i željeni database provider ovisno o bazi (MS SQL, MySQL, SQLite, Jet, Oracle, Postgres). Sastoji se od DLL biblioteke koja sadrži fluent API klase, i runnera, .EXE izvršne datoteke koja pokreće skripte. Runner se može pokrenuti po želji, i on će izvršiti samo skripte koje nedostaju, odnosno od zadnjeg pokretanja, jer u bazi postoji podatak o trenutnoj verziji. Također, runner je pogodan za pokretanje u sklopu build procesa.Više...

Web Dev, quick thoughts »

[6 srp 2011 | 1 Comments]

windows_open_source_Nedavno sam dobio upit da napravim jednostavnu aplikaciju za potrebe jedne udruge. Radi se o aplikaciji za praćenje zahtjeva, koja vodi evidenciju tko je predao zahtjev, tko ga provodi, evidentiraju se zabilješke, i na kraju se zahtjev zatvori. Uz to, bitno je da aplikacija prilikom otvaranja novog zahtjeva pokuša pronaći u bazi dali je slični zahtjev bio već riješen, te ponudi njegovo rješenje. Aplikacija mora imati i različite izvještaje.

Sve u svemu, radi se o spoju CRMa i Issue Trackera, a specifičnost bi bila jednostavnost korištenja i izrade, "pametni" sustav traženja postojećeg rješenja i izrada izvještaja.

Da stvar bude zanimljivija, odlučio sam aplikaciju raditi kao Open Source projekt, i putem opisivati kako sam neke stvari realizirao, zašto i slično. Tehnologije koje planiram koristiti isto nisu nešto što koristim u svakodnevnom radu, te je ovo prilika za proširenje znanja.

Za sada sam se odlučio za tehnologije:

- Silverligh 4
- ASP.NET i WCF web servisi
- RavenDb baza podataka (SQL Server sa EF Code First je backup rješenje, ako se RavenDb iz nekog razloga naljuti na mene i odbije poslušnost!)

Cilj je također koristiti tehnike i alate:

1. planiranje, projektiranje i izrada document baze. Imam iskustva samo sa relacijskim modelom podataka, i ovo će biti odlična prilika za uhvatiti se u koštac sa NoSQL problematikom! Koliko me ovo veseli, toliko me i plaši (Key/Value store, Map/Reduce funkcije, kreiranje indexa, ...)!
2. Caliburn.Micro za MVVM framework. Do sada sam koristio MVVMLight, koji odlično služi svrsi, ali opinioned pristup sa mnoštvo ugrađenih konvencija me jako privlači
3. CQS pattern: kao u predhodnom postu, htio bi:
- enkapsulirati upite, da ih mogu ponovno upotrebljavati
- slati one-way commande koje izvršavaju zapisivanje i/ili poslovnu logiku
  Do sada sam koristio CQS pattern isključivo u MVC web aplikacijama, te još nisam 100% siguran kako ovo izvesti u Silverligh klijent/server modelu, i to zbog:
- dali upite izvršavati u Silverlightu, preko RavenDb REST sučelja, ili ih slati na server i tamo izvršavati? Nikako ne želim imati standardne RPC SOAP web servise, nego više nešto nalik RESTu.
- dali komande izvršavati na serveru ili klijentu?
- kako serijalizirati querye i komande prilikom slanja preko WCFa, ako se uopće šalju?
Inspirirano prezentacijom “Dr. CQRS or: How I Learned to Stop CRUDing and Love the Domain Model” sa NDC 2011 konferencije.
4. reporting u Silverlight, još trebam odlučiti kako. Savjeti?
5. Aplikacija se mora pokretati na shared hosting okruženju, u Full Trust načinu rada

Sljedeće je plan izrade User Storya, i popisa funkcionalnosti koje aplikacija mora implementirati. Izvorni kod će biti objavljen na BitBucketu kroz tjedan-dva, čim postavim projekte i solution.

Kako je ovo jedan proces učenja novih tehnologija, očekujem puno primjedbi, komentara i sugestija! Zaželite mi puno sreće u mojem prvom Open Source projektu!

Web Dev »

[2 srp 2011 | 0 Comments]

Pokušati ću opisati još jedan u nizu patterna za arhitekturu aplikacije, bilo web, desktop ili Silverlight, koji upotrebljavam već neko vrijeme. Pattern se pokazao jako korisnim, i to sa stajališta organizacije veće količine koda, enkapsulacije logike u zasebne, odvojive cjeline, time omogućivši i lakši unit testing. Svrha ovog patterna je i pojednostavljenje koda i uklanjanje bespotrebne apstrakcije upotrebom puno slojeva (hint: dali baš u svakoj aplikaciji treba biti layer sa Repository klasama, Service klasama sa (praznom) poslovnom logikom, i sl?).

U osnovi, radi se o starom i poznatom CQS patternu (Command Query Segragation), koji nalaže da se odvoji logika za upite (npr: dohvati sve proizvode iz kategorije), koja vraća podatke, od logike koja sadrži određeno procesiranje, i ne vraća podatke (npr: dodaj proizvod u košaricu za kupnju). Dodatnu popularnost ovaj pattern je dobio kroz upotrebu u CQRS arhitekturi, koji query/command priču diže na jedan viši, enterprise nivo, da bi se dotakli problemi (horizontalnog) skaliranja i race conditiona (više procesa se natječu za prvenstvo pristupa određenom resursu), dodajući odvojene izvore podataka za pisanje i čitanje, te asinkroni sistem zapisivanja i sinkronizacije. Dodatne informacije o CQRSu se mogu pronaći na blogu od Udi Dahana.

Primjer upotrebe ovog patterna možemo prikazati na jednostavnom primjeru web shopa, kroz upotrebu u dva scenarija:

1 Dohvat prozvoda zadane kategorije
2 Dodavanje odabranog proizvoda u košaricu za kupnju

Naravno, ovdje se radi o web aplikaciji, koja može i ne mora biti MVC.

Više...

RIA, Web Dev »

[18 lis 2010 | 0 Comments]

image Silverlight po defaultu dolazi sa loader splash ekranom, koji je sve samo ne lijep. Neznam za čitatelje ovog teksta, ali ja čim vidim gradijente, odnosno prijelaze, još u kružnom obliku, dobijem iznenadnu želju za skakanjem sa vrha zgrade. Srećom, da ne bi slučajno došlo do realizacije tih želja gledajući brojna učitavanja Silverlight aplikacija, zamjena ekrana učitavanja je vrlo jednostavna.

Iz sljedećeg prikaza može se vidjeti slijed učitavanja aplikacije:

image

Splash screen i događaji koji ispisuju postotak učitavanja su u biti jedna XAML datoteka i Javascript metoda koja se poziva na promjenu postotka učitavanja i vrši interakciju sa elementima prikazanom XAML ekranu.

Postupak izrade izgleda ovako:

1. U jednoj XAML datoteci je potrebno pripremiti izgled ekrana. Ovdje se nalazi primjer takve datoteke,

2. Javascript metoda služi za prikaz i animiranje tog ekrana (potrebno dodati u posebnu JS datoteku i referencirati ju iz Head elementa od web stranice):

function SourceDownloadProgressChanged(s, e) {
    var bartext = s.findname("bartext");
    var bar = s.findname("bar");
    if (bartext != null || bar != null) {
        var value = Math.round(e.progress * 100)
        bartext.Text = value + "%";
        var newWidth = 3.3 * value;
        bar.Width = Math.round(newWidth)
    }
}

3. Dodatni parametri unutar poziva Silverlight aplkacije (u html/aspx, <object> element):

<param value="preloader.xaml" name="splashscreensource" />
<param value="SourceDownloadProgressChanged" name="onSourceDownloadProgressChanged" />

Tech, Web Dev »

[8 ruj 2010 | 0 Comments]

Ovo je prvi u nizu, nadam se, brojnih kratkih pregleda open source .NET alata, frameworka, toolkitova, i svega što može poslužiti, korisno ili beskorisno!

Prvi prezentirani alat je Automapper. Radi se jako korisnom frameworku za kopiranje vrijednosti iz jednog objekta u drugi. Osim osnovnog kopiranja propertya po propertya, postoje brojni načini konfiguracije koji omogućuju složene manipulacije nad podacima, a fluent interface DSL način konfiguriranja je intuitivan i relativno jednostavan za podesiti.

Najčešći scenarij u kojemu ja upotrebljavam AutoMapper je kopiranje vrijednosti iz domenskih entiteta (sa učitanim podacima iz baze) u DTO objekte koji reprezentiraju prikaz podataka na web stranici ili windows/Silverlight formi.

Najjednostavniji primjer je kopiranje prema konvenciji, što znači da će Automapper tražiti propertye sa istim imenima:

Public class Article
{
	public int ID { get; set; }
	public string Name { get; set; }
}

Public class ArticleDTO
{
	public int ID { get; set; }
	public string Name { get; set; }
}

AutoMapper.Mapper.CreateMap<Article , ArticleDTO>();

var article = new Article() {ID = 1, Name = "some name"};

var dto = new ArticleDTO();

AutoMapper.Mapper.Map(article, dto);

Malo složenija i češća upotreba je flattening, ili pretvaranje grafa objekata u jedan objekt, uz primjenu ValueResolvera za konverziju tipa podataka:

public class Person
{
	public string Name { get; set;}
	public Address Address { get; set; }
	public bool IsMale { get; set; }
}

public class Address
{
	public string StreetName { get; set;}
	public int Number { get; set;}
}

public class PersonDTO
{
	public string Name { get; set;}
	public string LivingAddress { get; set;}
	public string Gender { get; set; }
}

public class GenderConverter : ValueResolver<bool,string>
{
	protected override string ResolveCore(bool source)
	{
		return source ? "Male" : "Female";
	}
}

var person = new Person() 
	{ Name = "Hudo", Address = new Address() {StreetName = "Sezam", Number = 1, IsMale=true}  };

AutoMapper.Mapper.CreateMap<Person , PersonDTO>()
	// kopiranje ulice i broja iz objekta Address u jedan property
	.ForMember(
	d => d.LivingAddress, 
	s => s.MapFrom(x => x.Address.StreetName + " " + x.Address.Number))
	// konverzija iz bool u string
	.ForMember(
	d=>d.Gender,
	s=>s.ResolveUsing<GenderConverter>().FromMember(x=>x.IsMale));

var dto = new PersonDTO();

AutoMapper.Mapper.Map(person, dto);

Ostali primjeri se mogu pronaći na Codeplexu (http://automapper.codeplex.com/) i naravno, Googlu.