…meie igapäevast IT’d anna meile igapäev…

2012-03-02

Tehnilised intervjuuküsimused C# programmeerijale

Filed under: Programmeerimine — Sander @ 10:00:38
Tags: ,

CSharpLogoOlen viimase poole aasta jooksul päris mitmel .NET programmeerija tööintervjuul osalenud – siis intervjueerijana, mitte intervjueeritavana.

Mulle ei meeldi küsida trikk-küsimusi – kui sult kunagi tööintervjuul küsitakse “mitu muna munevad 1.5 kana 1.5 päevaga, kui…” või muud sellesarnast, siis küsi vastu – et kas selliste probleemidega siis siin firmas tegeletaksegi? Ma tulin programmeerijaks, mitte talunikuks.

Veel vähem meeldivad mulle kohapeal programmeerimisülesannete lahendamised. Kui viimati ise intervjueeritava rollis olin, siis paluti mul tahvlil üks suhteliselt lihtne probleem lahendada. Keeldusin, põhjendades seda sellega, et ei usu et sellisest lahendamisest saaks reaalselt aru minu oskustest programmeerijana.

Miks nii? Nagunii on pinge sees – vaja ju paista välja hästi tark, lisaks eeldavad sellised kiirülesanded sageli mitte intelligentset probleemi lahendamist, vaid eelnevalt kindla lahenduse teadmist. See ei anna ka edasi tegelikke intervjueeritava oskuseid – ta võib ju olla superhea linked listi mudija või stringi tagurpidi keeraja, aga kui ta seejärel ei saa hakkama mitte millegi muuga…

Ah jaa, tolle tööintervjuu ma läbisin edukalt. “Tehniline intervjueerija” olevat käskinud osakonnajuhil mind kindlasti palgata.

Nüüdseks on mul kogunenud üks ports oma pisiküsimusi – enamik neist on C# süntaksi kohta. Ma ei eeldagi intervjueeritavalt, et ta neid kõiki silmpilkselt suudaks vastata. Pigem annab inimesest aimu see, kas ta suudab kümnestkonnast küsimusest vähemalt osale midagi vastuseks öelda – või suudab ta leida lahenduse loogikat kasutades. Või isegi, kuidas ta käitub vastust mitte teades.

Paljud neist küsimused on kasulikud teada igapäevaprogrammeerimisel – ning paljud küsimused seda ei ole. Mõned on hädavajalikud teada. Enamik ei ole.

Lisaks on vaja kindlasti lasta lahendada testülesanne – so, mitte just kõige lihtsam pisirakendus, mida saab kodus paari päeva jooksul programmeerida. See annab inimese oskustest kõige parema ülevaate. Kas asi on spaghetti, kas kood on korralikult kommenteeritud, kuidas on struktureerimisega, nõuete implementeerimisega ja nii edasi.

Lisaks loe ka mu eelmisi programmeerija mitte .NET-spetsiifilisi tööintervjuualaseid postitusi: 1, 2, 3.

TL,DR: mul on tekkinud kolmkümmend tehnilist küsimust, mida küsida tööintervjuudel. Siin on neist kümme. Kui saan kokku viiskümmend küsimust, siis postitan järgmised kümme. Vastused võid kommentaaridesse postitada.

  1. Mis on readonly ja const vahe? Millal saab esimest kasutada ja milline on saadav kiirusevõit?
  2. float, double, decimal. Mis on nende erinevused? Mille poolest erineb decimal kahest teisest? Milline on neist kolmest kiireim arvutustes? Aga täpseim?
  3. ArrayList vs geneeriline List<>. Kumb on kiirem, millised on ühe või teise eelised?
  4. Mis on ja kus sa kasutaksid singleton patternit? Mis juhul sa ei saa static’ut kasutada ja pead singletoni kasutama?
  5. Kas staatilisel klassil saab olla konstruktor? Kui jah, siis millal seda välja kutsutakse? Aga destruktor?
  6. Kuidas sa lahendaksid olukorra, kus sama interface’i implementeerivatel klassidel on vaja sama funktsionaalsust – näiteks on 3rd-party library’s interface IPerson, millel on property’d Firstname, Lastname, Initial. Seda implementeerivad sinu klassid Customer, Client, Employee ja Manager, mis vajavad kõik täisnime kuvamise funktsionaalsust. Kuidas seda teha, kui interface’i ei saa muuta? (NB! Siin on vähemalt kaks võimalust)
  7. Mille poolest erinevad funktsiooni parameetrites Foo(params string[] list) ja Bar(string[] list)?
  8. Kas interface’st päritud klass saab olla staatiline?
  9. Mida võimaldab @ stringi ees (@”foo. bar.”)? Aga muutuja nime ees (@variable)?
  10. Kas enum’i numbriline väärtus saab olla suurem, kui Int32.MaxValue?
About these ads

2 kommentaari »

  1. Hmmh, midagi sellist äkki ?

    1. Pakun, et põhiline vahe on, et readonly initialiseeritakse runtimes kas välja deklareerimisel või konstruktoris. Kuna const valued resolvitakse juba kompilleerimisel siis seal vast on mingi teoreetiline kiirusvõit aga ma arvan et see on nii marginaalselt väike, et sisuliselt erilist vahet ei ole. Ma eelistan suht alati readonlyt, et ei peaks kompilleerima uuesti.

    2. Decimal on ülitäpne aga sigaaeglane võrreldes riistvaraliselt manipuleeritavate andmetüüpidega. Tegin möödunud aasta Monte Carlo simulatsiooni kus pidin igalpool decimali kasutama, ANTS paljastas et natuke andis tunda küll võrreldes doubliga. Floati ma pole .NETis kunagi kasutanud, ei näe mingit pointi selles, suht kasutu tänapäeval minuarust (samuti nagu floati ja double performance vahe võrldus on tänapäeva protsessoritega täiesti jabur).

    3. Ei näe mingit eelist ArrayListis List ees, nendes haruldates olukordades võib ju alati List kasutada ja minuarust see on isegi informatiivsem. Peast nüüd ei mäleta aga kas VS isegi mingit warningut ei andnud et AL on deprecated vms (või oli see Resharper) ? Igatakses, ArrayList peab igakord boxima/unboxima sõltumata mida sa seal sees hoiad, nii et teoreetiliselt peaks AL vist alati aeglasem olema. Omaette küsimus on, et kas siis ka kui sul on AL ja List ja sa panedki ainult System.Object-e sinna. Siis võib vast enamvähem võrdne olla ?

    4. Hmm, ma üldiselt ei kasutakski singletoni, pole mitte kunagi sattunud sellise olukorra ette kus DI/IOC või static ei suudaks singletoni asendada. Pigem esimene mõte singletoni nähes on, et “miks kurat ta selle siia toppis ?”. Hüperteoreetiline eelis staticu ees on, et staticuga on state hoidmine paras jamamine ja mockimine kujutan ette et oleks omaette nali. Tood äkki mingi konkreetsema stsenaariumi kus on valida staticu ja singletoni vahel ?

    5. Jah, saab aga siis peab konstruktor ka staatiline olema. Initialiseeritakse esimese referenci resolvimisel sellele klassile. Staatilisel klassil destruktorit ei ole.

    6. Lihtne variant oleks teha nii:

    interface IPerson
    interface IPersonBase : IPerson
    class Customer : IPersonBase
    class Employee : IPersonBase

    IPersonBase asemel võib olla ka abstrakne klass või tavaline klass, oleneb kui väga tahad realisatsiooni kirjeldada. Siis saaks veel virtualidega sama asja teha jne.Muidugi on ka täiesti overkill lahendusi a la visitor methodi injectimine, funktsiooni referenci etteandmine jms jama.

    7. Esimesel juhul (params) sa kutsuks meetodit välja nii: Foo(“A”, “B”, “C”) ja teisel juhul nii: Bar(new string[]{“A”, “B”, “C”}). Sisulist vahet pole, mugav kompillaatori magic lihtsalt :)

    8. Nope. Mis point sel oleks ? Staatilised klassid suht hävitavad OO kontseptsiooni ja siis pole pärimisel ka väga pointi enam.

    9. Esimesel juhul märgib see stringi verbatim string literaliks (st backslashe ignoreeritakse kui erilistena), teisel korral võimaldab kasutada muutujatena reserveeritud sõnu, ala private string @class;

    10. Ei saa, enumi all istub vist alati 32bit integer (isegi 64bit kompilleerides), st public enum TestEnum { Midaiganes = 2147483648 } annaks alati vea.

    Aga igaljuhul toredad küsimused, mõtlema paneb ainult kas need peavad ikka nii platvormispetsiifilised olema. Selles suhtes, et mind huvitaks oluliselt rohkem, et arendaja oskab arhitektuurselt normaalset koodi kirjutada mitte mingit spagetti. Ma laseks tal näiteks paberi peal joonistada kuidas ta hüpoteetilise MVC projeti moodulid jaotaks. Näiteks:

    Projekt.Views
    Projekt.Dto
    Projekt.Controllers
    Projekt.ApplicationServices
    Projekt.Domain
    Project.DataProvider

    Ja kust siis mis info kuhu liigub, kes mida näeb jne. Kas ta dependancy injectionist saab aru. Kui aneemiline ta domeenimudel oleks ja kõik muud sellised konksud mis näitaks ta kogemust projektides mitte keele referentsi lugedes.

    Samas noh, teise poole pealt vaadates jälle mingi teoreetiline jura ka jälle ära ei veenaks. Ilmselt parim lahendus oleks mingi kesktee ?

    Andres.

    kommentaar kirjutas Andres R. — 2012-03-16 @ 16:14:29 | Vasta

    • Päris hästi. Nii kaheksa punkti kümnest.

      4. Singletonil on erinevalt staticust olemas ka destruktor – ning sa saad implementeerida interface’sid. Standardne koht singletoni kasutamiseks on näiteks logger, kuid ka igasugused teenused, kus on vaja öelda “sessiooni lõpp”. Ega tihti neid vaja ei ole.
      6. IPersonBase asemel ma kasutaks lihtsalt PersonBase baasklassi koos vastava meetodiga, kuid sul on lihtsaim lahendus puudu – public static string GetName(this IPerson person) {}. Tundub, et paljud programmeerijad ei tea, et extension method’isse saab saata ka interface.
      10. Vale, aga kui aus olla siis paar kuud tagasi oleks ma ise ka sama vastuse andnud. “An enum declaration may explicitly declare an underlying type of byte, sbyte, short, ushort, int, uint, long or ulong” (http://msdn.microsoft.com/en-us/library/aa664597%28v=vs.71%29.aspx).

      kommentaar kirjutas Sander — 2012-03-21 @ 13:03:58 | Vasta


Selle postituse kommentaaride RSS-voog. TrackBack URI

Lisa kommentaar

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Muuda )

Twitter picture

You are commenting using your Twitter account. Log Out / Muuda )

Facebook photo

You are commenting using your Facebook account. Log Out / Muuda )

Google+ photo

You are commenting using your Google+ account. Log Out / Muuda )

Connecting to %s

Theme: Rubric. Get a free blog at WordPress.com

Follow

Get every new post delivered to your Inbox.

Join 81 other followers