Kultainen koodi

.NET-osaajan ajatuksia paremmasta koodailusta

Archive for the tag “ohjelmointi”

Clojuren opiskeluun vaihtoehtoja

Clojuren ja ClojureScriptin opiskeluun löytyy useita työkaluja, jotka toimivat hyvin. Alkuun voi ottaa maistiaiset kokeilemalla jotain selaimessa pyörivää REPLiä. Sen avulla voi suorittaa suoraan clojurekoodia.

Koodaajan iloksi clojurelle löytyy useita eri kehitysympäristöjä:

Counterclockwise on ilmainen Eclipsen päälle tehty ympäristö.

JetBrains kehitti IntelliJ:n päälle kokonaan oman tuotteen clojurelle. Sen nimi on Cursive. Se näkyi ClojuTRE:n demoissa suosituimpana työkaluna.

Emacsiin saa clojuren pyörimään mainiosti. Käytän sitä itse töissä, koska kokeneemmat kehittäjät osaavat näyttää sillä miten hommat tehdään.

Visual Studioon löytyy vsClojure-lisäosa, jolla pääsee vauhtiin.

Jos haluat opiskella clojurea, voit joko lukea siitä kirjasta, suosittelen Clojure for the brave and true -opusta. Se on kirjoitettu kieli poskessa ja se sisältää hyviä linkkejä lisäopiskelua varten. Aloitin itse sitä kautta.2016-07-19-11-57-22

Ehkä matalin kynnys tulee kuitenkin pyöräyttämällä läpi yksinkertainen hands-on harjoite. Sellainen löytyy try clojuresta. Sen päristely kestää vain 5 minuuttia. Suosittelen lämpimästi. Siinä kerrotaan suoraan mitä pitää kirjoittaa, joten se onnistuu helposti. Toisaalta siinä ei sukelleta kovinkaan syvälle clojuren mahdollisuuksiin.

Omaa osaamista voi vahvistaa ratkomalla koodisokeriongelmia 4Clojuren sivuilla. Kannattaa luoda käyttäjätunnus, niin edistyminen tallentuu. Ratkaisujen löytäminen vaatii rajapintojen tuntemista, tuskastuttavaa ja lopulta palkitsevaa. Apuna voi tietenkin käyttää Cheatsheet-sivua tai vaikka lueskella aiemmin mainittua kirjaa. Hyviä esimerkkejä löytyy myös clojuredocsista, siellä on rajapinnan lisäksi näppäriä esimerkkejä. Stackoverflowsta ei vielä löydy vastauksia, joten kannattaa panetua muuhun materiaaliin.

Exercism.io & clojure on suosikkini itseopiskelua varten. Se tosin vaatii oman koneen ja ympäristön, jossa ratkaista tehtäviä. Exercism antaa kuitenkin vapaat kädet ongelmien ratkaisuun. Ongelman voi ratkaista kauniilla koodilla tai kirjoittamalla apufunktioita ja karmean pitkän hässäkän, kuten itse teen ensimmäisellä iteraatiolla. Löydettyäni ratkaisun yritän jalostaa mörkömöhkäleestäni kaunista koodia.

Valitse oma polkusi clojureen! Opiskele niin paljon kuin on tarpeen tai syöksy kielen syvyyksiin oivaltamaan. Nauti.

Mainokset

Clojureen ihastuminen

Astuin clojure-maailmaan, tehtyäni töitä yli kymmenen vuolla .NET-työkaluilla. Suurimman osan tuosta ajasta kirjoitin C#:lla ja hieman yli vuoden Visual Basicilla. Clojure on LISP-perheeseen kuuluva kieli. Ensin se nyrjäyttää aivot ja sitten sillä koodaaminen tuntuu mahtavalta.2016-07-13-09-53-17

Uusimmassa projektissa kieli- ja tekniikkavalintoina on ClojureScript frontissa muutamien lisäpalikoiden kera, serverillä Clojure ja tietokantana CouchDB. Olen harjoitellut ja koodannut clojurea vasta kuukauden, joten kielen vaihtoon liittyy paljon uutuuden viehätystä.

Miltä clojure näyttää?

(map inc [1 2 3])
;; => [2 3 4]

Oheessa koodi, jossa lisätään inc-funktiolla annetun vektorin alkioiden arvoja yhdellä. Map-funktio kutsuu inc funktiota jokaiselle alkiolle erikseen, jolloin funktion tulos on [2 3 4].

Käytin tovin aikaa todetakseni, ettei tässä ilmaisessa wordpress.com:ssa voi asentaa plugineja, joilla voisi tyylikkäästi näyttää miten clojure toimii. Klipse:n voisi upottaa blogiin, jos saisi ajaa JavaScriptiä tai asentaa plugarin.

Käy klipsen sivuilla testaamassa clojurea, niin saat maistiaisen kielestä.

Attach To Anything

AttachToAnythingRajapintojen (Silverlight, SOAP ym) ja palvelujen (windows service) debuggaukseen löytyy kätevä lisäosa. Attach To Anything kiinnittää debuggerin parilla hiiren painalluksella haluttuun prosessiin. Toinen vaihtoehto on tietenkin heittää perinteinen näppäinsarja:
Alt + d, Alt + p ja sitten valita hiirellä listasta sopiva prosessi.

Attach To Anything myös odottaa prosessin nousemista. Voi pistää debuggerin odottamaan, että IIS nousee pystyyn ensimmäisen kutsun myötä. Debug-valikon kautta joutuu sen sijaan odottamaan, että palvelu tai muu moduli lähtee käyntiin.AttachToAnything2

Suosittelen kokeilemaan, jos pitää koodata verkkosivujen, rajapintojen, palvelujen ym. kanssa jotain. Mielestäni erinomainen lisä Visual Studioon.

Koodaajan erilaiset hatut, refaktorointi

Martin Fowler piti hienon puheen ohjelmoijan erilaisista hatuista. Se upposi ajatusmaailmaani saman tien.

Hänen mukaansa koodia tehtäessä ohjelmoija laittaa päähänsä tietynlaisen hatun käydessään työtehtävään. Tyypilliset hatut ovat

  • koodaus, uusien toimintojen lisäämiseen ja
  • refaktorointi, laadun parantamiseen.

Toki näiden lisäksi löytyy optimoijan hattu, protoilu tai POC-hattu.

iPhone 166Hyvä koodaaja siistii koodinsa aina ominaisuuden luomisen jälkeen, joten miksi refaktoroinnille pitää käyttää omaa hattua? Koska koodi haisee.

Haiseva koodi on (jonkun toisen tekemä) vanha tuotos. Se ei toimi niin tehokkaasti kuin voisi toimia ja se kaipaa pientä tuunausta. Tästä karmeudesta pääsee eroon vain refaktoroimalla. Ohjelmoimista oppiessa huomaa myös oman vanhan koodinsa kaipaavan päivitystä. Koodin hajun lisääntymisen yksi keskeinen syy on sovelluksen kasvaminen ja toimintojen lisääntyminen.

Alkuperäiseen tarkoitukseen käytetty yksinkertainen arkkitehtuuri ei enää toimi, vaan uusien ominaisuuksien lisääminen pakottaa purkkakoodin lisäämiseen, ellei refaktoroi rakennetta uudelleen. Yksinkertaisimmillaan metodikutsu sisältää liian monta parametria ja tarvitaan parametriolio.

Jos koodin hajuun ei kiinnitä huomiota, koodin laatu rapistuu ja koodin rakenne katoaa. Se hukkuu kaikkiin pieniin muutoksiin ja jippoihin. Kompleksisesta koodista seuraa koodaamisen tuska, koska sitä on vaikeampi ymmärtää ja uusien ominaisuuksien liittäminen käy hankalaksi. Aikaa menee hukkaan. Sen sijaan hyvin suunnitellussa ja siistinä pidetyssä koodissa työskentely on vaivatonta ja nopeaa.

Johtoportaalle refaktorointia on turha perustella laadulla, kauniilla koodilla, asinatuntijuudella tai oikealla tavalla tehdä. Perustele rahalla. Sotkuiseen koodiin koodaaminen vie enemmän aikaa kuin pitäisi.

Huomaa, että refaktoroinnin voi joskus jättää tekemättä. Jos haiseva koodi sijaitsee jossain harvoin käytetyssä syrjäisessä osassa, siihen ei tarvitse koskea. Jos haisevaan koodiin törmää päivittäin, se pitää siivota pois. Muutoin joudut tekemään ylimääräistä työtä ja laskutat ylimääräistä asiakkailta. Se on varastamista.

Refaktorointitalkoot ja issuet projektin backlogilla kannattaa unohtaa. Ne putoavat priorisoinnissa aina alaspäin. Sen sijaan korjaa ihan vähän koodia tänään. Paranna laatua taas huomenna, kun törmään heikkolaatuiseen koodiin. Viikkojen ja kuukausien kuluessa koodin laatu paranee. Pian pääset koodaamaan mukavan koodipohjan päälle.

Windows Forms lokalisointi, Satellite Assemblies

Windows Forms -lokalisointi eli kieliversioiden tarjoaminen teksteille ei käy käden käänteessä. Teknisesti asia hoidetaan yksinkertaisesti. Luodaan yksi resurssitiedosto jokaiselle tarvittavalle kielelle ja merkkijonojen käännökset sijoitetaan näihin tiedostoihin. Uudemmilla tekniikoilla, kuten WPF, tämän voi automatisoida hyvin pitkälle esimerkiksi ReSharperilla.

Demoissa käytetty Microsoftin ”automaattinen” kieliversiointi luo jokaiselle lomakkeelle ja UserControllille omat resurssitiedostot. Esimerkiksi kymmenen formin ja viiden UserControllin projektissa tällöin kahdelle kieliversiolle tulisi kolmekymmentä resurssitiedostoa, joissa sama teksti toistuisi useaan kertaan. Ok- tai Peruuta-tekstit pitäisi kääntää jokaisen komponentin kohdalla erikseen ja muistaa tehdä muutokset jokaiseen resurssitiedostoon.

Windows forms -lokalisointi toimii näin:
1. Luodaan resurssitiedostot käytetyille kielille
2. Luodaan sovelluskohtainen ResourceManager
3. Asetetaan lomake tai UserControl lokalisoitavaksi
4. Tehdään lokalisointi koodin puolella
5. Luodaan lokalisoitavat tekstit resurssitiedostoihin
ja
6. Luodaan paikka, jossa voi vaihtaa kieliasetusta

Vaiheet 1 ja 2 tehtään kerran. Vaiheita 3-5 toistetaan jokaisen lokalisoitavan lomakkeen ja UserControllin kohdalla. Sovelluksesta riippuen, kieliversion vaihtaminen sijoitetaan sovelluksen mukaisesti joko aina nähtäville tai kertavalinnaksi.

Kieliversioitu testilomake

Yksinkertainen lomake Satellite Assembly -lokalisointia varten.

1. Luodaan resurssitiedostot käytetyille kielille

Luo projektiin Resources-kansio. Lisää sinne resurssitiedostot. Geneerinen en-valinta sopii hyvin Suomalaiseen makuun, koska meillä ei yleensä tehdä suurta eroa Amerikan- ja Britannianenglannin välille.

Luo resurssitiedostot

Luo resurssitiedostot

2. Luodaan sovelluskohtainen ResourceManager

Luo päälomakkeelle tai sovelluksen avaavaan program-kohtaan globaali ResourceManager.

private ResourceManager _resourceManager = null;

Initialinnin yhteydessä aseta nykyinen kulttuuri, tässä tapauksessa Suomi ja sen lisäksi viittaus resurssitiedostojen sijaintiin.

Thread.CurrentThread.CurrentCulture = new CultureInfo("fi-FI");
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
_resourceManager = new ResourceManager("WFSatelliteAssembly.Resources.WFSatelliteAssembly", 
                                       Assembly.GetExecutingAssembly());

Globaalin resurssienhallitsijan sijaan voit luoda myös aina uuden, jos siltä tuntuu. Tällöin pitää huolehtia resurssitiedostojen löytymisestä, varsinkin jos yritetään viitata niihin toisesta projektista käsin. Useampaa projektia käytettäessä globaali olio tuntui kätevämmältä.

3. Asetetaan lomake tai UserControl lokalisoitavaksi

Valitse haluttu luokka ja muuta se lokalisoitavaksi.

Laita lokalisointi päälle

Laita lokalisointi päälle

4. Tehdään lokalisointi koodin puolella

Konstruktoriin, heti komponenttien initialisoinnin jälkeen aseta kieliversioidut tekstit.

InitializeComponent(); // Visual Studion luoma metodi
UpdateUiControls();

Itse päivitysmetodi

private void UpdateUiControls()
{
    try
    {
        if (_resourceManager != null)
        {
            Text = _resourceManager.GetString("Lomakkeen otsikko");
            uiLabelFirst.Text = _resourceManager.GetString("Eka teksti");
            uiLabel1.Text = _resourceManager.GetString("Toka teksti");
            uiLabel3.Text = _resourceManager.GetString("Kolmas teksti");
            uiLabel4.Text = _resourceManager.GetString("Valitse kieli");
            uiButton1.Text = _resourceManager.GetString("Peruuta");
            uiButtonTemput.Text = _resourceManager.GetString("Tee temput");
        }
    }
    catch (System.Exception e)
    {
        MessageBox.Show(e.Message);
    }
}

5. Luodaan lokalisoitavat tekstit resurssitiedostoihin

UpdateUiControls-metodissa annetaan avain, jonka perusteella haetaan lokalisoitu teksti. Esimerkiksi lomakkeen otsikko haetaan avaimella ”Lomakkeen otsikko” ja sen arvo suomeksi on ”Monikielisyys”. Jos kielen vaihtaa englanniksi, otsikon teksti muuttuu arvoon ”Satellite assembly test”.

Suomenkielinen lokalisointi

Suomenkieliset tekstit

Englanninkielinen lokalisointi

Englanninkieliset tekstit

6. Luodaan paikka, jossa voi vaihtaa kieliasetusta

Kielen valinta voidaan tehdä RadioButtonilla seuraavasti:

private void uiRadioButton_Click(object sender, Resco.UIElements.UIMouseEventArgs e)
{
    UIRadioButton radioButton = sender as UIRadioButton;
    string culture = string.Empty;
    if (radioButton == null) return;

    switch (radioButton.Text)
    {
        case "Suomi":
            culture = "fi-FI";
            break;
        case "English":
            culture = "en-GB";
            break;
    }

    // This is used for the language of the user interface
    Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(culture);
    // This is used with formatting and sort options (e.g. number and date formats)
    // e.g. a float value 2.352 will be 2,3.52 if CurrentCulture is set to de-DE
    Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(culture);
}

Näillä ohjeilla voi luoda kieliversioinnin Windows Forms -sovellukselle.

Katso myös

Bittivektorin tallentaminen integerinä

Bittivektori tallentaa kätevästi useamman muuttujan arvot yhteen muuttujaan. Aivan fantastinen keksintö. Se perustuu bitteihin. Luvut voidaan ilmaista nollina ja ykkösinä. Saman tiedon voi tallentaa merkkijonona ”00100101” tai lukuna. Luku mahtuu pienempään tilaan, jos data siirretään jonkinlaisen xml-wrapperin kautta. Tällöin yksi muuttuja vie huomattavasti vähemmän tilaa kuin usea boolean arvo.

Bittioperaatiot C#-kielellä

.NET-kielen bittioperaatiot ovat:

operaatio operattori
JA &
TAI |
XOR ^
EI ~

Pari käytännön esimerkkiä

Klassinen esimerkki löytyy yhteyden muodostuksesta. Päätelaitetta kätellessä voidaan kertoa muutama yhteyteen liittyvä tieto. Aikanaan myös datan koodaustyyli.

Bit Bit Value Meaning (1) Meaning (0)
7 128 Ready Off-Line
6 64 Connected Not Connected
5 32 Carrier Present Carrier Absent
4 16 Log Data Do Not Log Data
3 8 Auto Answer Mode Manual Answer Mode
2 4 Echo Commands Do Not Echo Commands
1 2 Use 8 Data Bits Use 7 Data Bits
0 1 Use Odd Parity Use Even Parity

Toinen tapaus voi olla käyttäjätiedot ja asetukset. Esimerkiksi sukupuoli, onko admin, jne. Mikäli asetuksissa käyttöliittymälle on valittavana erilaisia tyylejä, niin tyylivalinnat voi tallentaa bittivektoriin.

Bittivektoria voi käyttää valittujen viikonpäivien tallentamiseen. Mitkä tahansa päivät voidaan valita ja tallentaa tieto yhteen int-muuttujaan. Viikonpäiviä voi käyttää esimerkiksi herätyskello-toiminnossa. Sen voi laittaa soimaan tiettyinä viikonpäivinä. Sähköpostimuistutuksen tekemättömistä töistä voi lähettää tiettyinä viikonpäivinä (ma, ke, pe). Toistuvalle kalenteritapahtumalle voi määrätä halutut viikonpäivät.

päivä arvo
Maanantai 1
Tiistai 2
Keskiviikko 4
Torstai 8
Perjantai 16
Lauantai 32
Sunnuntai 64

Tyypillisesti käyttäjä valitsee käyttöliittymästä muutaman valinnan (CheckBox).

Valitut päivät

Valitut päivät

Valitut viikonpäivät saadaan tallennettua yhteen muuttujaan tai-operaattorin avulla.

int valitutPäivät = 0;

if (Maanantai.IsChecked != null && Maanantai.IsChecked.Value) 
    valitutPäivät = (int)Viikonpäivä.Maanantai;
if (Tiistai.IsChecked != null && Tiistai.IsChecked.Value) 
    valitutPäivät = (int)Viikonpäivä.Tiistai | valitutPäivät;
if (Keskiviikko.IsChecked != null && Keskiviikko.IsChecked.Value)
    valitutPäivät = (int)Viikonpäivä.Keskiviikko | valitutPäivät;
if (Torstai.IsChecked != null && Torstai.IsChecked.Value)
    valitutPäivät = (int)Viikonpäivä.Torstai | valitutPäivät;
if (Perjantai.IsChecked != null && Perjantai.IsChecked.Value)
    valitutPäivät = (int)Viikonpäivä.Perjantai | valitutPäivät;
if (Lauantai.IsChecked != null && Lauantai.IsChecked.Value)
    valitutPäivät = (int)Viikonpäivä.Lauantai | valitutPäivät;
if (Sunnuntai.IsChecked != null && Sunnuntai.IsChecked.Value)
    valitutPäivät = (int)Viikonpäivä.Sunnuntai | valitutPäivät;

Tässä esimerkissä käytetään viikonpäiville seuraavaa enumia

public enum Viikonpäivä
{
    Maanantai = 1,
    Tiistai = 2,
    Keskiviikko = 4,
    Torstai = 8,
    Perjantai = 16,
    Lauantai = 32,
    Sunnuntai = 64
}

Päivämäärän valinta tarkistetaan haetaan muuttujasta ja-operaattorin avulla ja asetetaan CheckBoxeihin

int valitutPäivät = 45; // ma, ke, to ja la

if ((valitutPäivät & (int)Viikonpäivä.Maanantai) != 0)
    Maanantai.IsChecked = true;
if ((valitutPäivät & (int)Viikonpäivä.Tiistai) != 0)
    Tiistai.IsChecked = true;
if ((valitutPäivät & (int)Viikonpäivä.Keskiviikko) != 0)
    Keskiviikko.IsChecked = true;
if ((valitutPäivät & (int)Viikonpäivä.Torstai) != 0)
    Torstai.IsChecked = true;
if ((valitutPäivät & (int)Viikonpäivä.Perjantai) != 0)
    Perjantai.IsChecked = true;
if ((valitutPäivät & (int)Viikonpäivä.Lauantai) != 0)
    Lauantai.IsChecked = true;
if ((valitutPäivät & (int)Viikonpäivä.Sunnuntai) != 0)
    Sunnuntai.IsChecked = true;

Mielestäni yhden muuttujan käyttäminen usean boolean muuttujan sijaan säästää tilaa, nopeuttaa tiedonsiirtoa ja joissain tapauksissa selkiyttää koodia. Tosin kielen toimintaa ja rakennetta pitää tuntea hieman enemmän. Toinen vaihtoehto tässä tapauksessa olisi käyttää seitsemään boolean muuttujaa ja sijoittaa tieto niiden kautta.

Mikäli kaikki tämä tapahtuu sovelluksen sisäisesti, niin toteutustavalla ei ole suurta merkitystä. Jos kuitenkin joudutaan siirtämään tietoa netin ylitse, niin asialla on merkitystä. Sovelluksen toiminnan kannalta hitain operaatio on tiedon siirtäminen netin ylitse. Seuraavaksi tulee levyoperaatiot ja nopeimpia toimintoja ovat sovelluksen sisäiset tapahtumat.

Bittioperaatioden käyttäminen tiedon tiivistämiseen vähentää siirretyn datan määrää ja toimii siinä hyvin.

Katso myös

Oheessa muutamia linkkejä, joiden takaa löytyy eri tavoin selitettynä miten bittioperaatiot toimivat. Toisissa käydään hyvin perusteellisesti asioita läpi ja toisissa painotetaan enemmän koodin toimintaa. Avaa muutama ja omaksu tiedot niistä, joista opit asian helpoimmin.

Post Navigation