Pinu planeet

May 17, 2012

DT blogiTask Parallel Library ja PLINQ aktsioonis

Paralleelarvutus on pühat eesmärki täitev asi – hoiame oma niigi voolu õgivad protsessorid ja arvutustuumad maksimaalselt midagi asjalikku tegemas. Teen selle kohta ühe näite, mis aitab paremini mõista, kuidas .NET raamistikus tänaste vahenditega paralleelarvutus käib. Ühtlasi mõõdame oma tulemusi ja katsed viime läbi reaalelulise koodi peal.

.NET raamistikus on kaks vahendit paralleelarvutuse jaoks:

TPL on võimas raamistik, mis muudab paralleelarvutuse meie jaoks palju lihtsamaks ja koodi paremini mõistetavaks. PLINQ toob LINQ peale võimaluse töödelda andmeid paralleelselt. Seega võime öelda, et TPL on ülesannete põhine ja PLINQ on andmepõhine paralleelarvutus.

RSS-agregaator ja selle mõõtmine

Meie näite südamikuks on RSS-agregaator, mis loeb andmebaasist sisse blogide loendi, tuvastab nende RSS-i aadressid ning loeb sisse viimased postitused. Positused, mida veel andmebaasis pole, lisatakse sinna ära.

internal class FeedClient
{
    private readonly INewsService _newsService;
    private const int FeedItemContentMaxLength = 255;

    public FeedClient()
    {
        ObjectFactory.Initialize(container =>
        {
            container.PullConfigurationFromAppConfig = true;
        });

        _newsService = ObjectFactory.GetInstance<INewsService>();
    }

    public void Execute()
    {
        var blogs = _newsService.ListPublishedBlogs();
       
        for (var index = 0; index <blogs.Count; index++)
        {
            ImportFeed(blogs[index]);
        }
    }

    private void ImportFeed(BlogDto blog)
    {
        if(blog == null)
            return;
        if (string.IsNullOrEmpty(blog.RssUrl))
            return;

        var uri = new Uri(blog.RssUrl);
        SyndicationContentFormat feedFormat;

        feedFormat = SyndicationDiscoveryUtility.SyndicationContentFormatGet(uri);

        if (feedFormat == SyndicationContentFormat.Rss)
            ImportRssFeed(blog);
        if (feedFormat == SyndicationContentFormat.Atom)
            ImportAtomFeed(blog);
           
    }

    private void ImportRssFeed(BlogDto blog)
    {
        var uri = new Uri(blog.RssUrl);
        var feed = RssFeed.Create(uri);

        foreach (var item in feed.Channel.Items)
        {
            SaveRssFeedItem(item, blog.Id, blog.CreatedById);
        }
    }
    private void ImportAtomFeed(BlogDto blog)
    {
        var uri = new Uri(blog.RssUrl);
        var feed = AtomFeed.Create(uri);

        foreach (var item in feed.Entries)
        {
            SaveAtomFeedEntry(item, blog.Id, blog.CreatedById);
        }
    }
}

Mõõtmiseks kasutame sellist vahendit nagu Stopwatch klass. Programmi alguses lööme kella käima ja kui programm lõpetab, paneme kella seisma.

Seriaalne agregeerimine

Esiteks mõõdame ära tulemused, mida annab eeltoodud kood. Seal tehakse kõik sammud järjest ja korraga midagi käima ei lasta. See tähendab seda, et kõik RSS-id laetakse alla üksteise järel ja nende sisu salvestatakse andmebaasi samuti üks postitus korraga.

Mõõtmisel saame tulemuseks 25.46 sekundit.

Task parallelism

Meie esimene analüüsiülesanne on leida üles punkt, kus me saaksime eraldada muust koodist sõltumatud osad. Need osad koodist võime me käima lasta paralleelselt (me võime ka sõltuvustega osi paralleelselt käivitada, kuid see on oluliselt keerukam ja riskantsem tegevus). Meie juhul on selleks kohaks, kus võiksime kaaluda paralleeltöötlust, näiteks RSS-ide lugemine ja andmebaasi sisestamine.

internal class FeedClient
{
    private readonly INewsService _newsService;
    private const int FeedItemContentMaxLength = 255;

    public FeedClient()
    {
        ObjectFactory.Initialize(container =>
        {
            container.PullConfigurationFromAppConfig = true;
        });

        _newsService = ObjectFactory.GetInstance<INewsService>();
    }

    public void Execute()
    {
        var blogs = _newsService.ListPublishedBlogs();       
        var tasks = new Task[blogs.Count];

        for (var index = 0; index <blogs.Count; index++)
       {
            tasks[index] = new Task(ImportFeed, blogs[index]);
            tasks[index].Start();
        }

        Task.WaitAll(tasks);
    }
    private void ImportFeed(object blogObject)
    {
        if(blog == null)
            return;
        var blog = (BlogDto)blogObject;
        if (string.IsNullOrEmpty(blog.RssUrl))
            return;

        var uri = new Uri(blog.RssUrl);
        SyndicationContentFormat feedFormat;

        feedFormat = SyndicationDiscoveryUtility.SyndicationContentFormatGet(uri);

        if (feedFormat == SyndicationContentFormat.Rss)
            ImportRssFeed(blog);
        if (feedFormat == SyndicationContentFormat.Atom)
            ImportAtomFeed(blog);           
    }

    private void ImportRssFeed(BlogDto blog)
    {
        var uri = new Uri(blog.RssUrl);
        var feed = RssFeed.Create(uri);

        foreach (var item in feed.Channel.Items)
        {
            SaveRssFeedItem(item, blog.Id, blog.CreatedById);
        }
    }
    private void ImportAtomFeed(BlogDto blog)
    {
        var uri = new Uri(blog.RssUrl);
        var feed = AtomFeed.Create(uri);

        foreach (var item in feed.Entries)
        {
            SaveAtomFeedEntry(item, blog.Id, blog.CreatedById);
        }
    }
}

Muudatused, mis me tegime, on lihtsad – me defineerisime RSS-ide importimiseks eraldi ülesanded ja lasime need paralleelselt käima. Seejärel jäime ootama, millal kõik ülesanded on tehtud.

Kui aega mõõdame, siis saame tulemuseks 17.57 sekundit.

Data parallelism

Järgmiseks vaatame, kas meil on veel kohti, kus võime korraga mitut asja teha. Nagu tellitult vaatab meile vastu RSS-ist loetud postituste loend. Kuna postituste sisestamine andmebaasi on tehtav isolatsioonis (me ei kasuta teiste postituste andmeid), siis proovime, mis juhtub, kui laseme postitused andmebaasi sisestada paralleelselt.

internal class FeedClient
{
    private readonly INewsService _newsService;
    private const int FeedItemContentMaxLength = 255;

    public FeedClient()
    {
        ObjectFactory.Initialize(container =>
        {
            container.PullConfigurationFromAppConfig = true;
        });

        _newsService = ObjectFactory.GetInstance<INewsService>();
    }

    public void Execute()
    {
        var blogs = _newsService.ListPublishedBlogs();       
        var tasks = new Task[blogs.Count];

        for (var index = 0; index <blogs.Count; index++)
       {
            tasks[index] = new Task(ImportFeed, blogs[index]);
            tasks[index].Start();
        }

        Task.WaitAll(tasks);
    }
    private void ImportFeed(object blogObject)
    {
        if(blog == null)
            return;
        var blog = (BlogDto)blogObject;
        if (string.IsNullOrEmpty(blog.RssUrl))
            return;

        var uri = new Uri(blog.RssUrl);
        SyndicationContentFormat feedFormat;

        feedFormat = SyndicationDiscoveryUtility.SyndicationContentFormatGet(uri);

        if (feedFormat == SyndicationContentFormat.Rss)
            ImportRssFeed(blog);
        if (feedFormat == SyndicationContentFormat.Atom)
            ImportAtomFeed(blog);           
    }

    private void ImportRssFeed(BlogDto blog)
    {
        var uri = new Uri(blog.RssUrl);
        var feed = RssFeed.Create(uri);

        feed.Channel.Items.AsParallel().ForAll(a =>
        {
            SaveRssFeedItem(a, blog.Id, blog.CreatedById);
        });
    }
    private void ImportAtomFeed(BlogDto blog)
    {
        var uri = new Uri(blog.RssUrl);
        var feed = AtomFeed.Create(uri);

        feed.Entries.AsParallel().ForAll(a =>
       {
            SaveAtomFeedEntry(a, blog.Id, blog.CreatedById);
       });
    }
}

Siin kasutasime TPL asemel PLINQ, sest selle abil on meil mugavam lasta andmete peal operatsioone tööle.

Tulemuseks saame 11.22 sekundit.

Tulemused

Kui tulemused graafikule toome, samme sellise graafiku.

Serial, TPL, PLINQ

Näeme, et RSS-ide allalaadimine paralleelselt annab meile umbes poolteist korda võitu. Kui andmete uuendamise ka paralleelseks muudame saame võrreldes algsega 2.3 kordse võidu.

Kokkuvõte

Me alustasime tavalise lihtsa koodiga, mis tegi kõike samme järjest. Esimese muudatusena viisime me paralleelsele kujule andmete allalaadimise ja uuendamise. Andmete uuendamine jäi seejuures ikkagi järjestikuseks. Seejärel viisime ka andmete uuendamise paralleelsele kujule ja saime veel võitu. Meil läks seekord hästi, sest erinevate thread-ide peal jooksev kood ei vajanud midagi, mis sealt välja jääks.

Kui oma lähtekoodi hoolikalt analüüsida, siis võib tihti leida kohti, kus paralleeltöötlus võib rakenduse jõudlust tõsta. Oluline on need kohad tuvastada ja mõõta ära, kas paralleelsus annab midagi juurde või ei.


Loe lisaks


May 15, 2012

Andris Reinmantest2

DT blogiKuidas alustada node.js arendust

node.jsNode.js on Chrome nimelise brauseri JavaScripti mootoril põhinev õhuke platvorm, mille otstarbeks on skaleeritavate võrgurakenduste jooksutamine. Ümar definitsioon küll, kuid kui node.js olemusse süveneme, siis näeme, et selle abil lahendab ära päris palju probleeme.

Mis on node.js?

Oma sisemuses toimib node.js lihtsasti. Me kirjutame valmis skripti, mis töötleb HTTP-pöördumisi ning saadab neile välja vastuseid. Veebiserver, mis node.js koosseisu kuulub, on äärmiselt lakooniline ja väike. Iga pöördumine töödeldakse ära erineva thread-i peal ja see tähendab võimet vastata korraga suurele arvule pöördumistele. Pöördumised on õhukesed ja jätavad maksimaalselt ruumile tööle, mis nende raames peab juhtuma.

Kuidas node.js käima saada?

node.js saamiseks tuleb minna node.js kodukale ja see allalaadida. Installer on mõned megad suur ja mingiks suuremaks installiks ja konfimiseks pole seega vaja valmistuda. Failid paigaldatakse kataloogi

C:\Program Files\nodejs

Seal asub ka node.exe, mis on siis protsess, mille all skriptid jooksevad.

Laiendused ja arendus

Kuigi node.js jaoks tuleb juba installeriga terve hulk laiendusi, saab neid iseseisvalt juurde laadida node.js laienduste hoidlast. Laiendusi saab allalaadida ka käsurealt töötava klientrakenduse abil. Kellel huvi, siis vaadaku olemasolevate laienduste nimekirja.

Päris hea ülevaate node.js kasutamisest annab Patterns & Practices Symposium Online 2012 raames Yavor Georgievi poolt antud loeng “node.js on Azure”.

<iframe frameborder="0" scrolling="no" src="http://channel9.msdn.com/Events/Patterns-Practices-Symposium-Online/Patterns-Practices-Symposium-Online-2012/node-js-on-Azure/player?w=480&amp;h=272" style="width: 480px; height: 272px"></iframe>

Ma arvan, et otste lahti tegemiseks on nüüd piisav info koos ja selleks, et

Näiterakendus

Et Node.js pole ressurside osas nõudlik, sobib see ideaalselt näiteks lihtsate HTTP-põhiste rakenduste jaoks, mis jooksevad eraldi thread-ide peal. Kuigi node.js peal saab teha palju muud tarka ja kasulikku, toon ma näitena välja lihtsa skripti, mis kuvab pöördumiste vastuseks pilte veebiserveri juurkataloogist.

Viimistlemata kood, mida mu pisike server kasutab, näeb välja selline:

var sys = require("sys")
    http = require("http")
    url = require("url")
    path = require("path")
    fs = require("fs")

http.createServer(function (request, response) {
  var uri = url.parse(request.url).pathname
    var filename = path.join(process.cwd(), uri)
    path.exists(filename, function(exists) { 
        if(!exists) { 
            response.writeHead(404, {"Content-Type": "text/plain"})
            response.write("404 Not Found\n")
            response.end()
            return
        } 

    if(path.extname(filename) != '.jpg')
    {
                response.writeHead(500, {"Content-Type": "text/plain"})
                response.write("Forbidden extension!\n")
                response.end()
                return
    }

        fs.readFile(filename, "binary", function(err, file) { 
            if(err) { 
                response.writeHead(500, {"Content-Type": "text/plain"})
                response.write("error: " + err + "\n")
                response.end()
                return
            } 
 
        response.writeHead(200, {"Content-Type": "image/jpeg"})
            response.write(file, "binary")
            response.end()
        })
    })

}).listen(8124);

console.log('Server running at http://127.0.0.1:8124/');

Selle koodi käivitan käsurealt käsuga node.exe test.js. Järgmiseks ühendan ennast brauseriga aadressile http://localhost:8124/ ja küsin faili nimega something.txt. Tulemus, nagu oodata, on selline:

nodejs-something

Kui aga küsin rabbit.jpg, siis saan sellise tulemuse:

node.js: küsisime lubatud faili

Lõpetuseks

node.js peale saab ehitada erinevaid rakendusi ja saadaval on lausa veebiraamistikud, mille abil saab node.js peale kirjutada MVC-mustrit järgivaid veebirakendusi, kuid peamiselt on node.js eesmärk siiski pakkuda serveripoolset punkti, kus mingeid toiminguid kiiresti ja eriliste ressursikuludeta toime pannakse. Muide, node.js töötab ka Windows Azure peal ja ka Microsoft panustab sellesse, et node.js oleks tulevikus paremini toetatud nii Visual Studio kui ka Windows Azure peal.


Loe lisaks


May 12, 2012

DT blogiWiFi-kindel tapeet Prantsusmaalt

Ajal, mis küberkaitsekeskuseid rajatakse nii siin- kui sealpool suurt lompi, püüavad teemasse anda oma panuse ka Prantsusmaa teadlased, kes leiutavad WiFi-kindlat tapeeti. Eesmärk – kaitsta oma WiFi-võrku võõraste eest.

Võlutapeet on tehtud hõbeda kristallidest, mis peatavad raadiolained sagedustel, mida kasutavad WiFi-ruuterid. Grenoble tehnoloogiainstituudi uurija Pierre Lemaitre-Auger näeb tapeedis kaitseinglit WiFi-ruuteritele, mida muidu võidakse häkkida. Kummalisel kombel jääb arutluskäik seinte juurde, kuid laest ja põrandast juttu ei tehta.

Tapeet, millest saaks arvatavasti ka tinamütsikesi teha, tuleb müüki järgmise aasta alguses. Hinnad pidid tulema keskmised ning samas oluliselt odavamad kui varasematel katsetel.

Põhjalikumat lugemist pakub CIO artikkel Wi-Fi-Blocking Wallpaper Keeps Your Signal In, Intruders Out.


Loe lisaks


May 10, 2012

Kiibi lühiuudiste blogiARM’i Windowsil vaid IE

Mozilla ja Google on tõsiselt häiritud: Microsofti Windowsi ARM protsessoritele kohandatud versioon RT saab olema vaid IE veebisirvikuga. Probleem seisneb spetsiaalses tarkvarakihis, mis annab IE brauserile eelisseisundi ja kiirema ligipääsu opsüsteemile.

Põhjalikumalt analüüsib The Register.


DT blogiTechEd Europe 2012 sinu taskus

Midagi uut TechEd Europe 2012 külastajatele. Need, kellel Windows Phone 7, Android või iPhone taskus, saavad omale koostada seminaride kava telefoni peal. Selleks on eraldi rakendus, mis jagab seminari kohta ka muud infot, töötavad meeldetuletused ja kuskilt hakkas silma ka live tile tugi.

EventBoardMicrosoft on teinud diili sellise firmaga nagu Falafel Software, kelle üks teenustest on EventBoard. EventBoard on professionaalne organiseerijatele mõeldud teenus oma sündmuste toetamiseks. Osalejatele on kogu lõbu loomikult tasuta.

Nii palju kui EventBoardiga hommikul mängida jõudsin tundus see igati mugav ja asjalik rakendus olevat. Millestki sellisest olen puudust tundnud mitmetel suurematel sündmustel osaledes.

Vist parim on see, et oma seminarikava saab kokku laduda otse mobiili peal ja selleks saab kasutada igasuguseid hetki, kus midagi tarka niigi teha pole.

Üks hea lisa, mis EventBoardil on, on Twitteri ja mõnede muude infokanalite tugi. Juba praegu saab TechEd Europe 2012 kohta vaadata jooksvat infot, mis uueneb päris tihedalt.

Allalaadimine: EventBoard


Loe lisaks


May 04, 2012

DT blogiArenduskeskkonna optimeerimine: Kuidas suurendada paralleelselt kompileeritavate projektide arvu

Keeruline juttEt reede kiiremini õhtusse saada, siis annan väikse vihje Visual Studio projektide kompileerimise kiirendamiseks. Sedapuhku pole tegu peenema putitamise ja ehitamisega – pääseme optsioonide dialoogiga.

Visual Studio lubab öelda, et mitu projekti ta korraga kompileerib. Seejuures loomulikult arvestab ta ka projektide sõltuvusi (üks viitab teisele ja seega üks kompileeritakse enne teist valmis). Paralleelselt kompileeritavate projektide arvu saab määrata Tool => Options menüü alt.

Build and Run seadistused
Visual Studio 2010: Build and Run jaotusest saab määrata korraga
kompileeritavate projektide maksimaalse arvu.

See väike optimeerimise trikk töötab hästi lahendustega, kus on mitu sõltumatut projekti. Kõik projektid, mis teineteisest ei sõltu või millel puuduvad omavahelised sõltuvused või on neil ühesugused sõltuvused teistest projektidest, saab samaaegselt kompileerima panna.

Kellele ikka tundub, et justkui asjad masinal ei edene piisavas tempos, siis peenemast optimeerimisest saab lugeda minu postitust Arenduskeskkonna optimeerimine: Visual Studio lahenduste kompileerimine.


Loe lisaks


May 03, 2012

DT blogiKuidas ehitada wizard ASP.NET MVC peal

Ja jõudsingi õhtuga ideelahendusest esimese tulemuseni. Läbi mitmete katsete kirjutasingi valmis ASP.NET MVC jaoks mõeldud wizard-ite baasklassid. Seejuures jäin kenasti püsima raamistiku mängureeglitesse ja mingeid jubedaid häkke ei teinud. Anna oma esimesed bitid-baidid teilegi vaadata ja torkida.

Esmane lahendus wizarditele

Minu lahendus on lihtne – meil on baasklass wizard-ite kontrollerite jaoks. Kõik need kontrollerid laiendavad samat baasklassi ning ütlevad sellele ette oma “suure” mudeli tüübi.

Kontrolleri aktsioonid kasutavad wizard-i sammude kuvamiseks eraldi alammudeleid. Need kõik pärivad ennast wizard-i mudelite jaoks mõeldud baasklassist. Kui pöördumine tuleb kontrollerisse sisse, siis püüab kontroller “suure” mudeli valmis luua kas operaatoriga new või siis serialiseeritud andmetest.

Kui pöördumisele hakatakse vastust saatma, siis otsib baasklass üles mudeli küljest välja, kuhu “suur” mudel maha salvestatakse ning nii elab “suur” mudel üle lehtede vahel liikumise.

Sammude mudelid

Wizard-i sammude jaoks mõeldud baasklass on selline:

public class WizardStepBase
{
    [NonSerialized]
    public string SerializedModel;
}

Seda kasutavad mu wizard-i kaks sammu:

[Serializable]
public class Step1AskName : WizardStepBase
{
    [Required]
    public string FirstName { get; set; }

    [Required]
    public string LastName { get; set; }
    public string SSN { get; set; }
}

[Serializable]
public class Step2AskPhone : WizardStepBase
{
    [Required]
    public string WorkPhone { get; set; }

    public string HomePhone { get; set; }
    public string MobilePhone { get; set; }
}

Siiani peaks kõik lihtne olema – mudelite baasklass sisaldab lihtsalt atribuuti mudeli serialiseeritud versiooni kohta.

Wizardi kontroller

Järgmiseks see kõikse keerukam osa – wizard-i baasklass.

public class WizardControllerBase<t> : Controller where T : new()
{
    protected T WizardModel { get; set; }

    protected override void Initialize(RequestContext requestContext)
    {
        base.Initialize(requestContext);

        var serializedModel = requestContext.HttpContext.Request["SerializedModel"];
        if (string.IsNullOrEmpty(serializedModel))
        {
            WizardModel = new T();
            return;
        }

        WizardModel = Deserialize(serializedModel);
    }

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var parameters = filterContext.ActionParameters;
        if (parameters.Count == 0)
            return;

        var publicPropertyMask = BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty;
        var wizardProperties = WizardModel.GetType().GetProperties(publicPropertyMask);
        if (wizardProperties.Length == 0)
            return;

        foreach (var key in parameters.Keys)
            foreach (var property in wizardProperties)
                if (property.PropertyType == parameters[key].GetType())
                {
                    var type = WizardModel.GetType();
                    type.InvokeMember(property.Name, publicPropertyMask, null, WizardModel, new object[] { parameters[key] });
                }

        base.OnActionExecuting(filterContext);
    }

    protected override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        var result = filterContext.Result as ViewResult;
        if (result != null)
            if (result.Model is WizardStepBase)
            {
                var stepModel = (WizardStepBase)result.Model;
                stepModel.SerializedModel = Serialize();
            }

        base.OnResultExecuting(filterContext);
    }

    [NonAction]
    private string Serialize()
    {
        var serializer = new XmlSerializer(typeof(T));
        var builder = new StringBuilder(10000);

        using (var writer = new StringWriter(builder))
        {
            serializer.Serialize(writer, WizardModel);
        }

        var serializedBytes = Encoding.UTF8.GetBytes(builder.ToString());

        return Convert.ToBase64String(serializedBytes);
    }

    [NonAction]
    public T Deserialize(string serializedModel)
    {
        var deserializedBytes = Convert.FromBase64String(serializedModel);
        var modelString = Encoding.UTF8.GetString(deserializedBytes);
        var serializer = new XmlSerializer(typeof(T));

        using (var reader = new StringReader(modelString))
        {
            return (T)serializer.Deserialize(reader);
        }
    }
}

Ja siin on minu lihtne kontroller, mis küsib esimese sammu vaates külastaja nime ja teises sammus tahab teada telefoninumbreid. Sealt liigub see edasi andmete kinnitamise vaatesse, kus saab kontrollida, kas kõik andmed tulid ootuspäraselt kaasa.

public class HomeController : WizardControllerBase<mywizardmodel>
{
    [HttpGet]
    public ActionResult Index()
    {
        return View("Step1AskName", WizardModel.AskNameStep);
    }

    [HttpPost]
    public ActionResult Index(Step1AskName nameStep)
    {
        if (!ModelState.IsValid)
            return View("Step1AskName", nameStep);

        return View("Step2AskPhone", WizardModel.AskPhoneStep);
    }

    [HttpPost]
    public ActionResult Step2(Step2AskPhone phoneStep)
    {
        if (!ModelState.IsValid)
            return View("Step2AskPhone", phoneStep);           

        return View("Confirm", WizardModel);
    }
}

Sellega on nüüd suurem tegemine möödas. Asi, millele rõhku tuleb pöörata, on see, et kasutage alati WizardModel omadust, kui alammudelitega töötate kontrolleris, sest muidu pole wizard-ite kontroller kursis sellega, et midagi muutus.

Vaated

Vaated võite lasta omale Visual Studio poolt genereerida, kuid arvestage sellega, et HTML-i vormidele tuleb ette öelda õige kontrolleri aktsioon, kuhu andmed postitada. Ma tegin viimaseks vaate, kus on näha kõik andmed, mis sai sisestatud:

ASP.NET MVC wizard: andmete ülevaade

Paistab, et saimegi toimima. Teha on veel paar riukalikumat sammu, kuid need jätan järgmisteks päevadeks.

Kokkuvõtteks

Kuigi ASP.NET MVC ei paku välja kõiki ASP.NET Forms tugevaid külgi, on raamistik piisavalt paindlik, et sellega kõik viisakalt lahendatud saaks. Tuleb enne vaid võtta pits ja aru pidada. Nagu ennist mainisin, siis inspiratsiooni sain ühest suht jubedast wizard-i lahendusest ja paari tunniga sain valmis oma lahenduse, mis oluliselt viisakam.

</mywizardmodel></t>


Loe lisaks


Kiibi lühiuudiste blogiMicrosoft viis Skype’i Linuxile

Täpsemalt muutis Skype hiljuti oma võrgu ülesehitust. Seni kasutati vargsi ära tavalisi kasutajaid, kel hea ja kiire internetiühendus ning nobe arvuti – nende seadmetes toimis Skype “super-sõlme” (supernode) režiimis, mis tähendas infoliiklust kontaktide sisselogimiste, asukohtade, aga ka otsest helipakettide jms liigutamist. Mõne aasta eest Skype’i võrgus esinenud häired, kus süsteem üldse töötamast lakkas, olid tõenäoliselt tingitud just vähesest kontrollist infovahetusserverite üle. Nüüd on Skype ise käima pannud umbes 10 000 Linuxil põhinevat ja spetsiaalsete turvatugevdustega kaitstud “super-sõlme”, mille üle on firmal täielik kontroll. Skype pole seega enam puhas P2P (“peer-2-peer”) ehk hajusvõrk, milles kunded ise otse andmeid vahetavad. Kõnede ja sõnumite vahetamine ise toimib aga jätkuvalt otse kliendilt-kliendile. “Super-sõlmi” on vaja kasutajate audentimiseks, kasutajate kohta info hoidmiseks ja nende “kokku viimiseks”.

Põhjalikumalt pajatab Ars Technica.


DT blogiIdeelahendus: Wizardi loomine ASP.NET MVC peal

Tänase läbukoodi ülesande lahendusele mõeldes tuli üks päris hea mõte pähe. Kuulasin juttu ühest olemasolevast lahendusest ja mõtlesin vaikselt, et kuidas seal iga samm järgmist keerukamaks muudab. Ja pärast koduteel tuligi vist õige mõte pähe. Proovime nüüd ideelisel tasemel lahendada ära ASP.NET MVC raamistikus wizard-ite loomise.

Probleemid

ASP.NET Formsi all on wizard-ite tegemine lihtne. Meil on olemas kuvakontroller selle jaoks ning selle sees paneme paika, millist pilti ühe või teise sammu juures kuvatakse ning milliseid toiminguid tehakse. Natukese CSS-iga mängimist ja ongi täitsa nagu päris.

MVC peal meil midagi sellist ettevalmistatud kujul olemas ei ole. On olemas erinevaid lahendusi, mida kaaluda, kuid lõppeks peame ikkagi ise ehitama üles millegi, mis on mõistlik ja inimesi peast halliks ei aja.

Probleemkohad arendaja jaoks on siin järgmised:

  • milline mudel või millised mudelid tuleks koostada wizard-i jaoks?
  • kuidas mudeli andmeid hoida pöördumiste vahel?
  • kuidas kirjutada wizard-i jaoks midagi lakoonilist ja lihtsat?
  • kuidas see miski võiks olla korduvkasutatav?
  • kuidas teha nii, et selle miski silumine ja parandamine oleks lihtne?

Ma leidsin sellele esmase ideelise lahenduse. Panen selle kirja ja siis mõtlen edasi, kuidas asi selliselt vormistada, et nii võikski jääda.

Minu lahenduse idee

Ühe pealtnäha lihtsa lahenduse wizard-i ehitamiseks pakub välja Nadeem Afana oma postituses Create a Wizard in ASP.NET MVC 3. Siin kasutatakse AJAX-it, et korjata vormile kogu mudeli jaoks vajalikud andmed kokku. Seejärel alles saadetakse andmed serverisse. Tundub hea lahendus, kuid mida teha suvalise mobiili korral, millel mõni keskmiselt juust mobiilidele mõeldud brauser peal jookseb?

Minu lahenduse skeem on selline.

ASP.NET MVC wizard-i loomise idee

Me jaotame wizard-i taga oleva mudeli mitmeks pisemaks mudeliks, millele vastavad vaated. Iga vaade tegeleb selle mudeliga, mida temal vaja on. Selleks, et erinevate sammude jooksul sisestatud andmed oleksid meile koguaeg saadaval serveri pooles, siis loome wizard-i mudeli, mille omadusteks on sammude mudelid.

Selleks, et seni kasutaja poolt sisestatu säiliks, võtame ASP.NET Forms maailmast appi ViewState-i idee. Iga sammu mudeli koosseisu kuulub ka meie suur mudel serialiseeritud kujul. Seda hoiame mõnel peidetud väljal krüpteerituna peidus. Sessiooni me midagi ei kirjuta, sest kasutajal võib wizard olla samal ajal avatud rohkem kui ühes brauseri aknas.

Selleks, et saaksime “suure” mudeli tagasi, kasutame model binder-it, mis taastab deserialiseerimise teel suure mudeli ja uuendab seda vormilt tulnud andmetega. Seega me võime kõikide sammude vaadetes tegeleda suure mudeliga ja sealt lihtsalt sammudele vastavaid omadusi vaadetes renderdada. Samuti võime esikohale tuua just alammudelid ja hoida nendel viidet suurele mudelile, kust saame vajadusel andmeid juurde küsida mõne sammu jaoks.

Mis edasi?

Edasi ma tuulutan korraks aju ja mõtlen natukene järgi, kuidas see asi valmis kirjutada. Sealt edasi saab mu Visual Studio 11 jälle loovas protsessis osaleda kui koodi kallale asun. Kui midagi üldist siit ei sünni, siis vähemasti saame siit kokku lahenduse, mida kasvõi lahenduse mustri osas annab oma ASP.NET MVC projektides kasutada.

Kui kellelegi mõni kasvõi uitmõte pähe turgatas praegu, siis andke kommentaariumi vahendusel märku. Äkki saame kamba peale midagi veel vingemat kokku. :)


Loe lisaks


DT blogiDevReach 2012 registreerumine on avatud!

devreach2012Eelmisel aastal külastasin elus esimest korda sellist vahvad .NET seminari nagu DevReach 2011, mis toimub meile sobivalt ja soodsalt Bulgaaria pealinnas Sofias. Teleriku eestvedamisel toimuvale seminarile tuuakse kohale mitmed maailma suurnimed. Käesoleva aasta DevReach-ile registreerumine on alanud ja oodatud on kõik huvilised ka Eestist.

Miks minna?

Toon välja mõned põhjused:

  • esitajate nimekiri on tavaliselt olnud väga tugev (need nimed peaks tuttavad olema kõikidele tõsistele .NET arendajatele: Todd Anglin, Maarten Balliauw, Richard Campbell, Stephen Forte, Scott Hanselman, Tim Huckaby, Jesse Liberty, lisaks kohaliku regiooni staarid),
  • hinnad on soodsas – VIP-pass, mille koosseisu kuulub osalemine ürituse sulgemispeol, maksab  alla 200EUR (arenenud Lääne-Euroopas tähendab analoogse seminari tavapilet umbes 600-800 EUR suurust väljaminekut),
  • bulgaarlased on sõbralikud inimesed ja uusi kontakte luua on seal küllaltki lihtne, samuti on head võimalused leida omale uusi sõpru arendajate hulgast,
  • hinnad on Bulgaarias suhteliselt madalad ja kui hoida turistilõksudest eemale, siis pole ka õhtused õlleringid oluline kulu.

Sofia ja Tallinna vahel on lennuühendus päris hea ja hätta ei jää ka kohapealse majutusega. Hotelle on nii vanemast ajastust – rajud raudbetoon monstrumid – kui ka uuemad ja moodsamad (Radisson jt).

Millal toimub?

Toimumisajaks on 04.10-05.10.2012. See tähendab seda, et Tallinnast on mõttekas startida 03.10 ja tagasi Tallinnasse võiks ennast sättida 06.10 pealelõunal – jääb natuke aega Sofias ringi kolamiseks ka. Kes muidugi soovib linnaga tutvust teha pikemalt, siis võib ka 07.10.2012 peale tagasituleku plaanida. Mina saaksin omalt poolt rääkida kohalikega, kes meile äkki linna oleks nõus tutvustama.

Kohalik olustik on mulle selge ja kellel on plaani tulla, siis võite julgesti minuga ühenduda. Oskan eelmise aasta põhjalt küsimused ära vastata, mis esimest korda minejatel tekkida võivad.

On Eestist veel minejaid?

Peale sinu läheb sinna veel inimesi, kuigi arvatavasti mitte just palju. Loodame, et sellel aastal tuleb minuga kaasa paar kolleegi, kes .NET ja SharePoint arendusega tegelevad. Kui oled ka huviline, siis võtame teisi tulijaid ka hea meelega kampa. :)

Registreerumine

DevReach registreerumise lehel saate valida omale sobiva paketi ning selle eest tasuda. Kohapeal tuleb ennast esimesel päeval kirja panna ning tavaliselt saab registreerumisel ka kotikese nänni. Särk, pastakas, kaustik ja mingid kohalikus keeles värvilised paberid, pluss loomulikult seminari kava. Praegu on hinnad ülisoodsad ja kes kiirustab, see saab ka hea kokkuhoiu!


Loe lisaks


May 02, 2012

DT blogiASP.NET MVC: Laiendusmeetod kuupäevade vahemiku kuvamiseks

Mul oli vaja ühel ASP.NET MVC lehel kuvada sündmuste algus- ja lõpuaegu. Vaja oli pisut peenemat kuupäevade formaati, mis ei kuvaks kuupäeva kaks korda kui sündmus algab ja lõppeb samal päeval. Kirjutasin selle jaoks lihtsa laiendusmeetodi. Kellel vaja, siis võite siit julgelt haarata.

Väljund on samal päeval algava ja lõppeva sündmuse korral midagi sellist (stiilide abil saate endale sobiva välimuse külge ajada):

Sündmus algab ja lõppeb samal päeval

Kui algus ja lõpp on erinevatel kuupäevadel, siis on väljund selline:

Sündmuse algus ja lõpp on erinevatel kuupäevadel

Vaate sees on sellist asja niisama lihtsasti ilma loetavust kaotamata ära ei tee. Teine asi, mis räägib vaate sees formaatimise vastu antud juhul, on see, et taolist kuupäevade kuvamise loogikat võib meil kasutada mitu vaadet.

Laiendusmeetod ise on selline:

public static MvcHtmlString DisplayDateRange(this HtmlHelper helper, DateTime from, DateTime to)
{
    var buffer = new StringBuilder(100);
 
    buffer.Append(@"<div class=""dateRange"">");
 
    buffer.Append(from.ToShortDateString());
    buffer.Append(" ");
    buffer.Append(from.ToShortTimeString());
    buffer.Append(" - ");
 
    if (from.Date == to.Date)
    {
        buffer.Append(to.ToShortTimeString());
    }
    else
    {
        buffer.Append(to.ToShortDateString());
        buffer.Append(" ");
        buffer.Append(to.ToShortTimeString());
    }
 
    buffer.Append("</div>");
 
    return new MvcHtmlString(buffer.ToString());
}

Lisa see mõnda staatilisse klassi, et saaksid seda vaadetes kasutada.


Loe lisaks


DT blogiObjektipuu laadimine ja salvestamine kettale

Kui ehitame mõnda demorakendust, siis pole meil tihti mõtet kulutada aega andmebaasi ehitamisele. Ma näitan ette ühe lihtsa nõksu kuidas oma objektid faili salvestada ja kuidas neid failist laadida. Ühtlasi seletan paari sõnaga ära mõned serialiseerimise nüansid .NET raamistikus.

Alustuseks veidike serialiseerimisest. Serialiseerimise formaate on .NET-is mitmeid: kahendformaat, XML ja JSON. Kindlasti leidub serialiseerijaid veelgi. Viimased kaks kapriissemad, sest ringviiteid objektide graafis esineda ei tohi. See tähendab seda, et invoiceRow.Invoice ja invoice.Rows pole toetatud, sest mööda sama graafi liikudes saame tagasi jõuda algpunkti. Binary format on sellest probleemist vaba ja selle võtame kasutusele ka käesolevas näites.

Enne kui salvestamise kallale asume, on meil vaja klassi, mis hoiaks objekte, mis ei pruugi teineteisega seotud olla. Näiteks arved ja kasutajad võivad täiesti sõltumatut elu elada samas objektmudelis. Meie andmehoidja võiks välja näha midagi sellist:

[Serializable]
internal class SampleDataHolder
{
    public IList<Contact> Contacts { get; set; }
    public IList<Invoice> Invoices { get; set; }

    public SampleDataHolder()
    {
        Contacts = new List<Contact>();
        Invoices = new List<Invoice>();
    }
}

Järgmiseks kirjutame klassi, mis andmeid laeb ja maha salvestab. Selle klassi käest saame alati küsida andmeid hoidva objekti:

public class SampleDataProvider
{
    private static SampleDataHolder _dataHolder;
    private static string _dataFilePath;

    static SampleDataProvider()
    {
        var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase);
        _dataFilePath = Path.Combine(path, "data.dat").Replace("file:\\", "");
    }
       
    public static SampleDataHolder DataHolder
    {
        get
        {
            if (_dataHolder != null)
                return _dataHolder;

            if (!File.Exists(_dataFilePath))
            {
                _dataHolder = new SampleDataHolder();
                return _dataHolder;
            }

            using (var file = File.OpenRead(_dataFilePath))
            {
                var formatter = new BinaryFormatter();
                _dataHolder = (SampleDataHolder)formatter.Deserialize(file);
            }

            return _dataHolder;
        }
    }

    public static void Save()
    {
        if (File.Exists(_dataFilePath))
            File.Delete(_dataFilePath);

        using (var file = File.OpenWrite(_dataFilePath))
        {
            var formatter = new BinaryFormatter();
            formatter.Serialize(file, DataHolder);
        }
    }
}

Igal korral kui oleme teinud muudatusi objektipuusse kutsume Save() meetodi, et andmed maha salvestada. Kui on piisavalt kindlust rakenduse tulevase ülesehituse osas, siis võib siin ehitatud klassid peita ka andmekihi klassidesse ajutise lahendusena ära. Hiljem, kui rakenduse osas selgus majas on, saab luua päris andmebaasi toe ning rakendus ise ei pruugi sellest muutusest midagi teada.


Loe lisaks


April 30, 2012

DT blogiKuidas valmistuda ettekandeks?

Tehniliste ettekannete tegemist kasvõi meie Eneta kommuuni raames on ehk kaalunud nii mõnigi inimene, kes siiski on peatselt ümber mõelnud. Andres andis hea idee kirjutada üks lugu sellest, kuidas üks hea ettekanne valmib ja mida silmas pidada ja nii otsustasingi, et panen kirja oma ettekannete valmistamise protsessi ja mõned nõksud, mis inimeste ees olles abiks on.

Kuidas minust ettekandja sai?

Esiteks räägin ära selle, kuidas minu rada ettekannetega algas. Algas sellest, et mul polnud mingit kogemust. Küll aga jätkus piisavalt jõudu, et igasugu laheda tehnikaga tegeleda. ASP.NET, SharePoint, Joomla! CMS, SEO ja palju muud. Tulemas oli uus .NET-i versioon ja seda oleks hea idee laiemalt tutvustada.

Kui plaan ettekannet pidada, siis parim plaan – anna Andresele teada. Kuivõrd minu jaoks oli tegemist esimeste ettekannetega, siis korraldas Andres mulle paar prooviettekannet. See ei ole midagi hirmsat – valmistud ette ja teed nagu päris ettekande. Peale seda saad tagasisidet, et mida ja kuidas muuta. Näpunäited, muide on vajalikud, sest need on aegumatud.

Sealt edasi sain oma esimese ettekandega maha ja siis teisega ja siis kolmandaga. Enesekindlus kasvab iga korraga ja iga kord annab järgmiseks väga hea sisendi, millega arvestada.

Kust tuleb idee millestki rääkida?

Tavaliselt see lihtsalt tuleb kuskilt. Kui oma käsilolevate tööde või eraprojektide teostuse vastu piisav huvi olemas on, siis tekib materjal automaatselt. Või kui midagi põnevar näppu hakkab, mida torkida. Minul on suureks abiks ka minu blogid. Kui mõnest huvitavast asjast hakkab valmima kannete seeria, siis on aeg kindlasti ettekandele mõelda.

Mõnikord tekib ideid hoopis töisest keskkonnast eemal. Õdusas õllesaalis, mõnes kaunimas söögipaigas, kuhu tüdruku viin või õhtal diivanil raamatut lugedes. Telekast tulevat Hollywoodi valikut püüan ma maksimaalselt vältida, sest see ei anna ideid – see on ühesuunaline madal lõbu, mis vajutab aju kortsu ja loovalt lainelt välja. Muide, ka täielikus vaikuses tuleb häid ideid, sest see aitab mõtteid paremini koondada.

Oluline on see, et ideed ise tuleks. Pingutada pole mõtet – see ainult väsitab aju ja muudab olemise uniseks. Parim on lastata mõtetel rahulikult lennata ja varsti hakkavad ka ideed tasakesi välja kooruma. Algul ähmaselt ja siis järjest kindlamalt.

Ettekande ettevalmistamine

Ettevalmistamine on üks olulisemaid osi tööst. Ka kõikse igavam lektor võib täitsa asjalik tunduda kui ettekanne on hästi ettevalmistatud. Mul on tavaliselt ettevalmistumise hetkeks olema juba eelnevalt kokku kogunenud materjal. Kuid mitte alati. Ettevalmistus näeb välja umbes selline:

  1. Valitud teema osas mängin lähtekoodiga ning uurin, mis toimub vastava tehnoloogia sisemuses. See annab tunnetuse kätte.
  2. Järgmiseks korrastan ära katsete käigus suht sogaseks muutunud koodi ja püüan selle organiseerida selliseks, et see järgiks kõiki mulle teadaolevaid häid tavasid. See on oluline selleks, et kujuneks parem arusaam teemaks olevast tehnoloogiast. Lisaks sellele – lakoonilist ja hästi loetavat koodi on ka audientsil kergem jälgida, mis omakorda tähendab seda, et sa ei kaota aega koodi lahti seletamisele.
  3. Kui mul on selgus olemas, et kuidas asjad töötavad ja mida ma saan teha, siis proovin luua midagi kasulikku. Ei ole vaja midagi suurt ega uhket, mõni lihtne näide, mis oleks võimalikult lähedal sellele, mis päris elus juhtuda võib. Pane need näited tööle – need saavad olema asjad, mis audientsile meeldivad.
  4. Nüüd on aeg asuda slaidide kallale. Tee slaidid lihtsad ja jälgi, et iga punkt ja iga joonis annaks edasi selle mõtte, mida soovid. Viimase peensuseni ei pea minema – oluline on peamised ideed edasi anda. Arvesta sellega, et niigi selgitad sa slaidide juurde seda, mis seal kokku on võetud. Hetkel tee valmis kondikava – umbes sellised slaidid nagu olla võiks, kuid ära liialt põhjalikuks mine.
  5. Ära karda kasutada jooniseid ja skeeme slaididel. Kui joonis või skeem annab paremini edasi su jutu iva, siis lisa joonis või slaid. Nende kallal nokitsemine võtab aega, kuid see vaev tasub ennast ära.
  6. Nüüd võid asuda jutu kallale. Harjuta rahulikult iga slaidi juurde rääkima ja tee slaididesse jooksvalt parandusi ja täiendusi. Sa tead kui palju ettekande jaoks aega on ja teisel prooviringil suudad sa ajalistesse raamidesse kenasti ära mahtuda. Või kolmandal – ära seepärast muretse, algul ei peagi kõik 100% välja tulema.
  7. Järgmiseks proovi läbi demod. Tee täpselt samad sammud, mis sa plaanid ettekandes teha ja vaata, et kõik asjad töötaksid nagu vaja. Isegi kui see on su tuhandes ettekanne – tee ikka demod mitu korda läbi.

Nüüd oled piisavalt valmis, et oma esimene ettekanne ära teha. Tõenäoliselt pabistad algul, kuid soovitan ennast tunda kindlalt. Oluline on see, et su jutt on sorav, ise oled rõõmus ja hoiad tempot parajalt üleval. Esimestel kordadel aitab prooviettekanne sul õige rütmi kätte saada.

Vead, mida vältida

On asju, mida inimene ise ei näe, kuid mis audientsi segab või suisa häirib. Loomulikult ära lase ennast heidutada sellest kui mõni ettekanne ei õnnestu – nad kõik ei saagi õnnestuda. Parimad soovitused, mis ma oskan anda, on sellised:

  1. Alguses harjuta hoolega rääkimist, sest tempo, mis sinu jaoks tundub kiire, on audientsi jaoks oluliselt aeglasem. Liiga aeglane ja liiga monotoonne jutt uinutab inimesi ja tähelepanu kaob. Samuti segavad audientsi pausid su jutus ja igasugused ööö-äää mökutamised. Viimane segab kohe väga.
  2. Ära vaata oma slaide suurel ekraanil üle õla – see jätab sinust ebakindla mulje. Veel halvem on see, et see takerdab su jutu. Mitte sinu jaoks, kuid kuulajate jaoks on see märgatav tõrge ettekandes. Sa kaotad sellega aega, sest pead uuesti tempo üles saama.
  3. Ära kaldu teemast kõrvale. See on kuulajate jaoks väga häiriv kui äkki läheb jutt kuhugi mujale. Kuulajad tulid kuulama seda, mis ettekande reklaamis välja sai lubatud. Nad ei ole kuigi kergesti nõus kõrvalepõigetega.
  4. Kui näitad programme, siis näita alati koos demomiseks mõeldud andmetega. Ma kuulasin ühte ettekannet programmist, mida ma natuke tean, kuid mitte palju. Kummaline oli näha uue versiooni tutvustust, kus igasugused loendid ja asjad on tühjad ning juurde käib jutt, et umbes mis siin näha hakkab olema. Minust jäi see uus versioon sama kaugeks kui see oli ettekande alguses.
  5. Ära kuluta aega koodi kirjutamisele. Visual Studiol on olemas suurepärane asi nimega toolbar snippets. Kopeeri-pasteeri meetodil saad sa tööriistakasti lisada kõik ettekandes vajalikud koodilõigud, mida sa muutma või lisama pead. Su ajaline kokkuhoid on meeletu.
  6. Kui näitad midagi, mis võib lootusetult katki minna, siis tee selleks juhuks ettekandesse peidetud slaidid. Sa saad õnnetuse korral need nähtavaks teha ja ikkagi ettekandega lõpule minna. Kuulajad on äärmiselt pettunud kui sa pole sellisteks juhtudeks valmistunud ja muide – nad oskavad endalt küsida, et kas see tont kasutab PowerPointi elus esimest korda.
  7. Kui näide ei tööta, siis ta lihtsalt ei tööta ja mine edasi. Räägi, mis juhtuma oleks pidanud, kuid ära hakka parandamisele aega kulutama. Ka sellisel juhul võivad sind hädast välja aidata peidetud slaidid.

Need on peamised punktid, millest vähemasti seniks lähtuda kuni need harjumuseks saavad.

Üllata kuulajaid

Alati on võimalik kuulajatele pakkuda midagi, mida nad oodata ei tea ega oska. Võid selle saladuses hoida kuni ettekande lõpuni. Mõned ideed, mida proovida:

  • lahenda tutvustatavate vahendite abil lihtsasti mõni pealtnäha keerukas või mahukas probleem,
  • tutvusta ägedaid asju, mida antud vahend või tehnoloogia võimaldab (see võiks olla midagi sellist, mis kas loob uusi võimalusi või muudab midagi seni tüütut mugavamaks),

Aja jooksul areneb sinus ka üllatuste tegemise külg.

Mis edasi?

Edasi… mine vaata maailma ja räägi ka seal. See on väärtuslik kogemus ja sõpruskond, kes sul kujuneb seminaride külastades on midagi sellist, mida ükski riik sulle kohalikul tasemel pakkuda ei suuda. Mul on hulk selliseid sõpru ja maailma muudavad nad ikka oluliselt värvikamaks mul küll. See pole mu eralõbu, sinugi maailm saab senisest kirjum kui visalt suuri asju püüad korda saata.


Loe lisaks


April 28, 2012

Kuido tehnokajamRäsitabeli kollisioonirünnaku kõrvalmõjud, MS11-100 värskendus

Räsitabeli kollisioonirünnaku turbepaketi MS11-100 kõrvalmõjuna ei pruugi ASP.NET rakendused enam töötada nii nagu varem, ilmsiks võib see tulla "pikkade nimekirjadega" veebilehtede puhul kus peale turbevärskenduse paigaldamist enam asjad endist viisi ei tööta Põhjuseks see, et POST parameetrite võtmepaaride arvule on pandud piirang peale. http://support.microsoft.com/kb/2661403 Käima saab

April 26, 2012

Kiibi lühiuudiste blogiMicrosoft üritas Bingi Facebookile ärida

Redmonti hiid üritas oma Google’iga konkureerimisest sündinud õnnetut sülelast Bingi Facebookile mahaärida. Mõned tippjuhid – ilma ametliku Steve Ballmeri heakskiiduta – üritasid Facebookiga luua sellealast dialoogi, sest Zukerberg püüab Facebooki otsinguvõimalusi tunduvalt parandada. Edu siiski pakkumine ei toonud – Facebooki otsingu arenduse 25 töötajaga projekti juhib Lars Rasmussen, kes koos venna Jens’iga omal ajal Google Mapsi lõi, hiljem Google’i ebaõnnestunud Wave’iga tegeles ja šhokolaadivabrikust 2010. oktoobris Facebooki üle kolis.

Põhjalikumalt vihjab Register.


April 25, 2012

DT blogiHead ja halvad logid

Logifailide idee seisneb selles, et saaksime rakenduses esinevatest vigadest ja ohtudest hea ülevaate. See tundub kuidagi väga elementaarne, kuid kui käed külge lüüa, siis ei pruugi tulemus olla just see, mida rakendusi toetavad tehnikud ootavad. Kuidas saada head ja asjalikud logid?

Alustuseks üks reaaleluline näide ka, et oleks selgem, millist probleemi ma selle postitusega aitan teil vältida.

Kord ühe veebirakenduse logisid uurides olin hämmingus selle üle kui vähe need logid andsid probleemidega tegelemiseks sisendit mulle. Logid ise olid päris mahukad ning pilgeni täis tühja-tähja, mis edasi ei aita. Koostöös jube halva koodiga, kus meetodite pikkust võiks miilides mõõta, muutus kasutuskõlbmatuks ka see murdosa logi sisust, mis väärt infot sisaldas.

Mõni lugeja närib ehk hirmunult nüüd küüsi, kuid kindlasti on kõvasti neidki, kellel tekib deja-vu tunne.

Mis iseloomustab halba logi?

Pole ühtset valemit, mis aitaks logile niisama peale vaadates öelda, kas tegemist on hea või halva logiga. Alati on tegemist mitmete asjaolude ühele hetkele langemisega ning alati on kuskil tehtud pealtnäha häid, kuid lõppeks siiski mitte nii häid otsuseid.

  • logidesse jõudvad kanded ei ole kategoriseeritud (näiteks: hoiatus, viga, silumisteade),
  • kategoriseeritud kannetega logides pole teated korrektselt kategooriatesse jagatud,
  • logifaili sisu ei anna probleemi korral täit ülevaadet probleemist ja selle tekkepõhjustest,
  • leidub palju kandeid, mis on informatiivset laadi, kuid mis ei viita probleemidele,
  • kanded logis on ebaselged, sisaldavad lühendeid, mis ei kommunikeeri edasi oma tähendust,
  • logidesse kirjutatakse vigade ja tõrgete kohta liiga palju infot.

See on lihtsalt üks tagasihoidlik valik. Kindlasti annab seda rivi täiendada. Ahjaa, üks asi veel – millised logid kuuluvad millisele veebirakendusele tehtud pöördumisele? Jälle asi, mida oleks tihti hädasti vaja teada, kuid mida logid ei paku.

Kui arendaja peab logide kallale minema, siis on ilmselgelt midagi juhtunud, mida juhtuda ei tohiks. Süsteem tõrgub, inimesed ei saa tööd teha, aeg jookseb. Süsteem peab kiiresti jalgele tagasi saama, kuid aeg jookseb ja probleemi kohta infot koguv arendaja ei saa logidest teada midagi kasulikku. Tuleb tuttav ette?

Hea logi

Head logid annavad logi lugevale tehnikule olulist infot kõiksuguste tõrgete ja probleemide kohta. Hea info on näiteks see, et mis olid olulisemate muutujate väärtused vea hetkel või milliste andmetega süsteem parajasti tegeles.

Suurt rolli mängib ka lähtekood. Toon näite päris elust.

System.ArgumentNullException tekkis meetodis, mille ülesehitus on mida sellist:

public ActionResult SomeAction()
{
    Logger.LogError(“Some action started”);

    // tee midagi natukene

    try
    {
        // 70  rida koodi
    }
    catch(Exception ex)
    {
        Logger.LogInfo(“Viga tekkis!”);
        // nullime mõned muutujad
    }

    // veel paar mahukat try-catchi

    try
    {
        // 50 rida koodi
    }
    catch(Exception ex)
    {
        Logger.LogError(“Viga tekkis!”);
        // nullime jälle mõned muutujad
     }

     // teeme natuke veel midagi
     // tagastame tulemuse
}

Jube kood ja väga ootamatu ning algajatele väga raske siluda jah, kuid küsimus on hoopis teine: leides logist, et SomeAction käivitus ning leides järgmiseks teate “Viga tekkis!”, öelge täpne koodirida, mis vea põhjustas.

Ülaltoodud hall lugu on asi, mille ma tunnike peale leidmist kirjutasin oma õudusteraamatusse. Võtke selliseid leide kui asju, mis tuleb esimesel võimalusel korda teha, muidu ootavad teid ees põrgulikud üllatused.

Hoides ülaltoodud jubedust silme ees, võime kirjutada kokku loetelu nõuetest, millele üks logimise strateegia peab vastama:

  1. Logiteated tuleb kategoriseerida ning iga teade peab rangelt kuuluma oma kategooriasse. See tähendab, kui on tegemist veale omase kategooriaga, siis sinna lähevad ainult vead. Infoteadate kategooriasse lähevad ainult informatiivsed teated jne. Idee on lihtne – vähegi asjalikud logimise raamistikud lasevad seadetes lihtsasti muuta seda, milline on madalaim teadete kategooria, mis logisse jõuab.
  2. Ülaltoodud näites ei saa me logisid vaadates kuidagi otsustada selle üle, millal sai otsa SomeAction() meetodi täitmine. Kui järgmisena käivitunud meetodi alguses pole öeldud, et nüüd käivitus midagi uut, siis näeb arendaja seda, et arvatavasti on ta ikka veel SomeAction() meetodi sees.
  3. See, et tekkis viga, on hea tähelepanek ülaltoodud koodi autori poolt ja sellele keegi vastu ei vaidle. Küsimusi tekitab viga ise, mida me kuskilt ei leia. Mis viga siis ikkagi tekkis? Kus on selle vea stack trace? Millist rada pidi koodi täitmine selle veani viis? Alati kirjuta vea korral logisse ka Exception, mis tekkis – see annab oluliselt rohkem infot arendajale kui algul arvata oskad.
  4. Hoidu pikkade meetodite kirjutamisest. Mida pikemad on su meetodid, seda pikem on ka koodilõik, millest viga pead otsima. Lühikesed ja lakoonilised meetodid tõstavad logide väärtust kordades.
  5. Veebirakendustes püüa eristada erinevad pöördumised. Logisid lugeval arendajal on oluliselt lihtsam vigu leida kui ta saab tuvastada erinevate kasutajate tehtud pöördumised.

Alustuseks on need näpunäited piisavad. Loomulikult enne kui ütled, et nüüd on logimine viimase peal, pane oma rakendus logima, tekita vigu ja probleeme (veel parem, kasutage rakendust mitmekesi korraga) ning püüa ainuüksi logile toetudes leida üles, kus viga tekkis ja mis selle võis põhjustada.

Jabur nõks logide asjalikkuses veendumiseks

Eeltoodud jubedat koodi ja selle tekitatud logi vaadates tekkis mul üks täiesti jabur idee, kuidas veenduda selles, kui palju logi sisaldab asjalikku infot. Lihtne visuaalne kontroll, mis eeldab pisut nokitsemist.

  1. Tee algsest koodis varukoopia ja katseta selle peal. Kui sa selle katse peaksid hoidlasse saatma, siis usu mind – sa võid ka suured mehed nutma ajada.
  2. Otsi netist mõni vahva war-time story. Selline piisavalt pikk, kus lauseid ikka külluses oleks.
  3. Sammu läbi koodi failide ja märgates mõnda logiteadet, mis logi lugejale midagi juurde ei anna, asenda see jutust järgmise lausega.
  4. Kui oled koodi läbi käinud, siis lase rakendus käima ja kasuta seda. Mitte klõps-klõps-valmis, vaid niimoodi asjalikult nagu päris kasutaja oleks tegutsemas.
  5. Ava logifail ja hinda üldist olukorda. Kui saad ilma pingutamata lugeda war-time storyt, siis järelikult on logidega asjad valesti – liigset infot, mida sa vajalikuks ei pea, on logis liiga palju.

Edasi võid proovida ka seda, et kommenteerid need read välja, kuhu war-time storyt enne pasteerisid ja proovid uuesti. Nüüd oled, muide, selles kohas, kus logisse ilmub ainult see infot, mida sa vajalikuks pead. Selle infoga saad juba ladusalt edasi liikuda ning logimist vastavalt vajadusele täiendada.

Lõpetuseks

Logimine on midagi ääretult lihtsat kui sellest räägitakse ja midagi küllaltki keerulist kui seda tahta hästi teha. Libastuda on kerge ja peamine viga, mis logide juures tehakse, on see, et logisid hakatakse lugema alles siis kui päriselt midagi juhtus. Enne rakenduse valmimist tihti logidele rõhku ei panda, sest mis seal keerulist. Hästi läbimõeldud logid, milleni on küll keerukam jõuda, aitavad arendajaid palju – nad leiavad vead kiiremini üles ja lühendavad tõrgetega tegelemise aega olulisel määral.


Loe lisaks


April 24, 2012

DT blogiSkyDrive sai olulised uuendused

Uus SkyDrive on kohal ja muutunud on mängureeglites nii mõndagi. Ja ka toimimises. Praeguseks olen jõudnud uue SkyDrivega mõned tunnid mängida ja uurida selle käitumist. DropBox-ile tundub uus SkyDrive pakkuvad väga tõsist konkurentsi.

Uus SkyDrive

SkyDrive valik lemmikute allPeale SkyDrive kliendi installimist on meil näha kaks uut asja: lemmikute alla ilmub Windows Exploreris SkyDrive valik ja task bar-i peal on uus ikoon. Pilt paremal näitab uut valikut.

SkyDrive jaoks luuakse paigalduse käigus uus kataloog dokumentide kausta alla ning seda kataloogi jälgib SkyDrive klient. Kui sinna kausta midagi lisate või kui midagi muudate, siis sünkroniseeritakse muutused pilves asuva kettaga automaatselt.

SkyDrive kataloog on sünkroonis
SkyDrive: Minu SkyDrive kataloog on pilvega sünkroonis.

Failide suurusele pole enam nii rangeid limiite kui varem. Mul õnnestus ilma igasuguste probleemideta pilve peale ajada kuni 200MB suuruseid faile. Proovisin erinevaid laiendeid ja mingeid tõrkeid ei esinenud. Vaikimisi on pilves failide sünkimise ruumi 7GB, kuid seda saab laiendada piiratud aja jooksul.

Hea pakkumine piiratud ajaks

Alustuseks ava task bar-ist SkyDrive-i menüü ja vali sealt Manage Storage.

SkyDrive kliendi menüü

Peale pisukest mõttepausi avaneb järgnev leht:

SkyDrive ruumi laiendamine
SkyDrive: Piiratud aja jooksul saab oma pilve ruumi laiendada 25GB peale.
Pildi vaatamiseks originaalsuuruses kliki sellel hiirega.

Kui näed samasugust lehte, siis vajuta Free upgrade nuppu ja ruum laieneb 25GB peale. Kui sul on lingitud kontosid, siis nendega saad sama triki ära teha.

SkyDrive Windows Phone 7 klient

SkyDrive sai eile ka uuendatud Windows Phone 7 kliendi. Kellel soovi oma failidele juurde pääseda ka üle mobiili, siis soovitan uue rakenduse alla laadida. Teadmiseks, et selle kasutamiseks on vajalik Windows Phone 7.5. Ehk siis – laske uuendus peale, kellel see veel tehtud pole.


Loe lisaks


April 23, 2012

Melborp.NETVisual Studio 11 Beta – toote uuendused

Visual Studio 11 toob endaga kaasa paranenud (vähemalt minu arvates) toote uuenduste teatamise ning saamise. Enam ei pea otsima Visual Studio uuendust MS Downloadi lehelt ja google-st, vaid toote uuendustest annab teada Visual Studio ise ja Extension Manageris nupule “Update” vajutades tõmbate alla endale faili nimega VS_Update.exe ning see installeerib uuenduse.

image

Seega lisandub juurde uus kanal, mida kaudu arendajad saavad teada Visual Studio IDE uuendustest ning saavad hõlpsasti omale uuenduse alla tõmmata. Teadaande põhjal ütleks, et tegu testimises oleva teenusega ja Microsoft ootab tagasisidet kommuunilt, et otsustada parim kasutus kanalile.

Peale VS_Update.exe alla tõmbamist, tuleb aktsepteerida litsentsi ja seejärel installeerida uuendus. Ei miskit keerulist.

image

Kogu protsess (allatõmbamisest installeerimise lõpuni) kestis minu arvutis umbkaudu 10 minutit ja mul ei ole siin masinas SSD ketast ;)

Update KB2677574 kohta leiate rohkem informatsiooni Microsoft Supporti lehelt.

Veel lahedam edasiminek oleks see, kui Nupule “Update” vajutades installeeritakse uuendus automaatselt ning Visual Studio restarditakse. Päris nii sujuv see veel ei ole.

April 20, 2012

DT blogiSügisel tehnoatakk Ukrainale!

Tekkis möödunud nädalal üks mõte ja see mõte hakkas kooruma. Et läheks külla kuhugi ja ütleks inimestele midagi tehnoloogilist. Ja varsti saigi üks käik kokku pandud – tehnoatakk Ukrainale, kus kohalikud MVP-d ja kommuunijuhid aitavad kokku panna ühe tehnilise seminari, kus eestlased ka sõna saavad. Kellel huvi kampa lüüa, siis siin on mu lähem plaan.

Idee tekkest

Tsiteerides Juhan Viidingut – eluaeg olen tahtnud õue – võin öelda, et mingi seletamatu jõud on mind kogu mu elu liikvel ja tegevuses hoidnud ning maailmaga tutvumine on mu elu lahutamatu osa. Samamoodi tehnoloogia ning põnevad lahendused, bitid ja baidid. Igale poole ise ei saa, põhjuseid mitmeid – hinnad, ajalised võimalused, jmt. Ja on kohti, kuhu saab, aga kuhu ei kipu.

Nii ma siis mõtlesin, et kuhu võiks täiesti omal jõul ja sanktsioneerimatult minna ja Ukraina tundus selleks huvitav variant. Ma pole seal kunagi käinud, kuid olen suhelnud mõnede sealsete .NET arendajatega ning nende oskused osutusid tasemelt karmiks. Ehk siis – veel üks punkt Ukrainale juurde.

Idee ise

Idee on mul selline, et teha omal jõul käik ära, pidada  maha üks või mitu vägevat ASP.NET ettekannet ja tulla siis koju tagasi. Loomulikult varuks natukene aega, et tutvuda kohalike linnadega. Ja kui Eestist on veel huvilisi, kes tahaksid mõne ettekande teha, siis võtaks ka need huvilised kampa. Ära võiks sisustada pool päeva kuni päeva.

Kava praeguse seisuga on mulle omaselt lihtne ja rahulik. Päevade kaupa näeks see välja selline:

  1. Lendame Tallinnast Kievisse, vaba aeg, ööbime Kievis.
  2. Sõidame varahommikuse rongiga Harkovisse, ettekanded lõunast, sinna järgi vaba aeg, ööbime Harkovis.
  3. Varahommikuse rongiga sõidame Harkovist Kievisse, lõunaks kohal, vaba aeg õhtuni, ööbime Kievis.
  4. Sõidame esimese lennuga koju tagasi.

Kui juhtub, et Harkovist jõuab rongiga lennukile aegsasti, siis võib kaaluda ka kolmandamal päeval tagasitulekut.

Lennukiga saab Tallinnast Harkovisse ka sõita, kuid pilet võrreldes Kieviga on 2.5x kallim. Kui leian mõne soodsama variandi lennuks, siis annan huvilistele teada.

Ajaliselt plaanin spetmebri lõppu või oktoobri algust ja käik võiks enda alla võtta minimaalse arvu tööpäevi. Mitte, et mul vabade päevade vastu midagi oleks, aga mida teha nädala sees õhtuti, kui kogu linn magab mitte ei pidutse? :)

Miks minna?

Põhjuseid minekuks on mitu:

  1. See nurk maailmast on lisaks minule ka mitmetel teistel inimestel nägemata. Kindlasti leidub neidki, kes on kunagi varem käinud ja kes tahaks näha, mis toimub täna.
  2. Kohalik tehniline kommuun on suur ja tasemelt tugev. Ehk on seegi üks olulisi põhjuseid, miks ma just Ukraina valisin. Leiame uusi huvitavaid sõpru ja loome kontakte.
  3. Ukrainlased olid minu ettepanekuga ühisürituse osas igati nõus ja tundsid heameelt, et neile soovin külla minna. Oodata on sooja vastuvõttu ukrainlaste poolt.
  4. Distants pole pikk ja kohapeal ei ole hinnad liigkallid. Peaks meie inimese jaoks suht soodne olema. Nooremad inimesed kindlasti tunnevad huvi sellegi vastu, et milline vanasti meie ots ilmast välja nägi.

Pidulikku ülikonnaüritust ei plaani. Kõik saab olema selline mõnus ja vabas vormis. Vaevalt, et puhkus, aga midagi lahedat kindlasti.

Tekkis huvi?

Kellel huvi olemas, siis aega mõelda ja juurelda peaks jaguma. Konkreetseid samme mineku osas hakkan astuma augusti teises pooles. Kui varem, siis annan sellest blogi vahendusel teada. Kellel kindel soov juba täna, et minna, siis antagu teada aadressil gpeipman@hotmail.com.


Loe lisaks