Kultainen koodi

.NET-osaajan ajatuksia paremmasta koodailusta

Archive for the tag “programming”

Code Wars, mahdollisuus oppia

Tutustuin codewarsiin työkaverini suosituksesta yhtenä syksyisenä päivänä. Hän löysi koodiharjoitussivuston, jossa editoria ja testejä voi ajaa selaimen kautta. Toisin kuin exersim.io tai vastaavissa palveluissa, codewarsilla harjoitteleminen onnistuu ilman kehitysympäristöä.

Harjoitusten tekeminen codewarsissa käy helposti. Harjoitusta kutsutaan nimellä kata.

codewars_kata

Kata eli harjoitus codewars.com:ssa.

 

Harjoituksen tehtävänanto selviää ruudun vasemmalta puolelta. Koodi kirjoitetaan oikeassa yläkulmassa näkyvään koodinäkymään. Kirjoitettu koodi ajetaan ”paikallisia” testejä vastaan Run Examples -painikkeella. Ne löytyvät Example Tests -otsikon alta. Näitä testejä voi myös muokata omien mieltymysten mukaan.

Lopullinen testi ratkaisulle tehdään ajamalla koodi Attempt-painikkeella. Ratkaisun toimivuus testataan yksikkötesteillä, joita ei näytetä käyttäjälle. Vain testien tulos näytetään. Toisinaan testien nimestä voi päätellä mikä testi epäonnistui. Järjestelmä sallii myös satunnaistettujen testien ajamisen, jolloin tehtävän luojan ei tarvitse kirjoittaa kaikkia testitapauksia käsin.

Ratkaistuasi tehtävän, saat vaikeusasteen mukaan tietyn määrän pisteitä. Helpoimmat testit saa ratkaistua muutamassa minuutissa, vaikeampien ratkaiseminen kestää tunteja.

Ratkaistuasi tehtävän, näet muiden vastaukset ja näistä oppii. Vastauksista voi merkata omasta mielestä parhaan ja nokkelan vastauksen. Vastauksista näkee kuinka paljon ohjelmoijien ongelmanratkaisukyky ja API-tuntemus vaihtelee.

codewars_stats

Stats-sivu kertoo mistä olet saanut pisteitä.

 

Olen kerännyt suurimman osan pisteistäni tekemällä harjoituksia. Pisteiden hankkimiseen käytetyt kielet näkyvät oikeasta laidasta ja prosenttiosuus kertoo kuinka paljon pisteitä on kerätty ennen seuraavaa tasoa.

Pisteet päivittyvät muutaman tunnin välein, kun palvelin ajaa ajastetusti pisteiden päivistyskriptit. Itsekin ihmettelin aluksi miksi pisteet päivittyvät viiveellä.

Jos teet vain harjoituksia, pisteillä ei ole merkitystä. Halutessasi voit kirjoittaa harjoituksia muiden ratkaistavaksi tai kääntää niitä kieleltä toiselle. Tällöin korkeampi pistemäärä sallii kevyemmän validointiprosessin ennen kuin kirjoittamasi harjoitus julkaistaan.

Yhteisöllisyyttä yritetään lisätä klaanien avulla. Käyttäjän tiedoissa voi antaa itselleen klaanin. Se on vain merkkijono. Kaikki jotka kirjoittavat saman merkkijonon, tulevat samaan klaaniin.

codewars_klaanit

Klaanit

 

Klaanijärjestelmä ei ehkä ole täydellinen, koska vaihdettuani klaanin, näen edelleen kaikki vanhan klaanini jäsenet.

Codewars on ehdottomasti paras palvelu ohjelmointiharjoitusten tekemiseen. Sen avulla voi ylläpitää kielen osaamista tai opetella uutta kieltä. Toki harjoitusten avulla oppii erityisesti kielen käyttöä, ei niihin liittyvien frameworkkien käyttöä.

Suosittelen kokeilemaan codewarsia, sen avulla voit löytää palon vanhaan rakkaaseen kieleen tai kehittää osaamistasi nykyisen kielen kanssa.

 

 

 

Mainokset

Emacs työvälineenä

Kirjoitin clojurea syksyn emacsilla ja se sujui hyvin. Suurin osa ajastani menee siis koodin rakenteen ja toiminnan pohtimiseen. Saan näppärästi avattua haluamani tiedostot suoraan editoriin ja se tukee kohtuullisesti kirjoittamista.

Emacsin lisäksi pidän melko usein avoinna clojuren cheat sheet -sivua tai clojurescriptin vastaavaa.

Käyttö

Tavallisesti jaan ruudun kahteen tai kolmeen osaan. Yhdellä puolella näkyy koodi ja toisella yksikkötestit. Mikäli teen rajapintaan koodia, niin yhdellä puolella on tietenkin esim. palvelimen rajapinnat näkyvissä ja toisella puolella asiakas/web-sovelluksen puoli, joka kutsuu rajapintoja. Usein testaan koodin toimintaa myös REPL-ikkunassa.

Ikkunoiden ja tiedostojen välillä liikkuminen tapahtuu todella sujuvasti. Näppäinoikopolut purevat erittäin hyvin. Koodia saa siistittyä, leikattua ja liimattua vaivattomasti. Siihen emacs on tehty, kirjoittamiseen. Sen lisäksi yksikkötestit saa pyörimään jatkuvasti tai niitä voi pyöritellä komennoilla. Sekin toimii fantastisesti. Yksikkötestien ajaminen on paljon nopeampaa ja kätevämpää kuin Visual Studiolla, jota olen käyttänyt noin 10 vuotta.

Clojurea kirjoittaessani testaan usein koodia REPL-ikkunassa. Koodin namespacen saa ladattua näppärästi käyttöön ja voin ajaa haluamiani funktioita ”livenä”. Se helpottaa debuggausta, yksikkötestien suunnittelua ja funktion toiminnan testaamista.

Nähdäkseni emacsin valtteja ovat nopeus, koko ruudun tehokas käyttäminen ja laajennettavuus.

IDEn edut

IDE voittaa emacsin helposti koodin laadun tarkkailussa. Sekä Visual Studiosta, Eclipsestä ja InteeliJ:stä löytyy paljon lisäominaisuuksia, jotka helpottavat koodaamista.

Käyttömätön koodi nostetaan esiin paljon helpommin. IDEt yleensä ehdottavat (tai ainakin niihin lisätyt plugarit) kuinka koodia voisi parantaa. Koodausta helpottavat täydennystoiminnot ovat älykkäitä, toisin kuin emacsissa. Emacs tunnistaa aiemmin käytetyt funktiot, muttei osaa ehdottaa kirjastosta löytyviä vaihtoehtoja.

Sekä emacs että IDEt osaavat yhtä hyvin etsiä ja korvata tekstiä. Funktioiden tai metodien uudelleen nimeäminen sen sijaan onnistuu kunnolla vain IDEn kautta. Nimien tai nimiavaruuksien refaktorointi on ehdottomasti IDE-juttu.

Ohjelmakoodin rakenteen näkee IDEn olio tai sovellusrakenteesta, jos rakenne on yksinkertainen. Esimerkiksi MVVM tai simppeli Reactin dispatcher, subscriber -rakenne näkyy paremmin IDEstä kuin emacsista. Tosin kumpikaan ei pelasta jos kyseeseen tulee kompleksinen rakenne, kuten Prism tai laajalle levinnyt legacy-järjestelmä.

Kipeimmin emacsissa minua pistivät puuttuvat uudelleennimeämisominaisuudet, hyvän bookmark-järjestelmän puute ja heikko tuki koodin laadun tarkkailuun. Olisin kaivannut vihjeitä miten asiat koodataan. Projektissani asia korjaantui mob-koodauksessa ja pull request -arvioinneissa.

IDEssä käytettävien useiden näppäinten oikopolkujen sijaan emacsissa kirjoitetaan usea näppäinoikopolku peräkkäin. Esimerkiksi yksikkötestit voi ajaa komennolla (ctrl+c, ctrl+t, ctrl+n) IDEssä suositaan usean näppäimen samanaikaista painamista. IDEssä komennon voi siis käynnistää ”heti”.

Huomasin myös joidenkin emacsin lisäosien käytön vaativan järjettömiä näppäinoikopolkuja eli komennot menivät neljän tai useamman komennon syvyyteen. Se ei tuntunut käytettävältä. Niin pitkiä komentosarjoja ei edes pysty helposti muistamaan.

Lopuksi

Tuntui mukavalta kokeilla emacsia, mutta projektin laajentuessa jäin kaipaamaan useamman tiedoston refaktorointiin liittyviä ominaisuuksia. Halusin myös käyttää lyhyempiä näppäinoikopolkuja, mutta olenko valmis uhraamaan nopeuden käyttömukavuuden alttarille?

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.

BuildVision lisäosa

Helppous, selkeys ja käytettävyys. Näiden takia pidän BuildVisionista. Lyhyt esimerkki alkuun.

12>Build succeeded.
12>
12>Time Elapsed 00:00:01.41
========== Build: 12 succeeded, 0 failed, 122 up-to-date, 0 skipped ==========

Verratessani BuildVisionin näkymää vilisevään output-ikkunaan, näen helpommin missä mennään ja pystyn peruuttamaan käännöksen napin painalluksella. No joo (Ctrl + Pause/Break) pysäyttää normaalin buildin, mutta output-ikkunasta ei näe yhtä selvästi milloin yhden solutionin projektin kääntäminen epäonnistuu. BuildVision näyttää myös solutionin käännösajan ja statusbarissa juoksevan ajan, kun build on käynnissä.

BuildVision_build_time

BuildVision selkeyttää solutionin kääntämistä, kun solution sisältää useita projekteja. Sen kautta näkee selvästi mitä projekteja ei tarvitse kääntää, ”UpToDate”, mitkä projektit käännetään ”Building / BuildDone” ja mitkä projektit eivät käänny. Viimeisimmät merkataan punaisella ruksilla.

Selkeä käännösaika sai sukat pyörimään jaloissani. Sen näkee ensimmäisen onnistuneen käännöksen jälkeen, isolla. Kun build kestää pitkään ehdin hakea vaikka kupillisen kuumaa. Pienen solutionin kanssa askarrellessa ymmärtää pitää puolen minuutin tauon.

Suosittelen kokeilemaan, ei maksa mitään.

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