Minkälaisia loogisia virheitä aloittelevat ohjelmoijat yleensä tekevät? Minkälaisia virheitä olette itse aloitellessanne tehneet? Jos tulee mieleen jotain tyypillisiä haksahduksia tai asioita, jotka olivat mielestänne ohjelmointia aloitellessa vaikeita ymmärtää, niin heittäkää niitä tähän replyyn.
Koitan hahmoittaa minkälaisia ongelmia aloitteleva ohjelmoija yleensä kokee ja mitkä ovat yleisimpiä väärinkäsityksiä ja virheitä. Myös kaikenlaiset linkit asian tiimoilta kiinnostavat.
Koitan hahmoittaa minkälaisia ongelmia aloitteleva ohjelmoija yleensä kokee ja mitkä ovat yleisimpiä väärinkäsityksiä ja virheitä. Myös kaikenlaiset linkit asian tiimoilta kiinnostavat.
Vastaukset 12
Vanhimmat
C:stä pari esimerkkiä:
- oletetaan, että ohjelman koko olisi pienempi, kun käytetään pienempiä muuttujia (esim. char int)
- ihmetellään miksei teksti kopioidu / vertailu onnistu 'automaattisesti' (if(teksti == "vertailutekstiä"))
C:ssä on paljon muitakin (ehkä yleisin virheiden syy tulee osoittimien käytöllä).
http://keskustelu.suomi24.fi/show.fcgi?category=108&conference=4500000000000140&subcat=1066
Googlella löytyi pari parempaa linkkiä:
http://www.cprogramming.com/tutorial/common.html
http://www.drpaulcarter.com/cs/common-c-errors.php
Kielenä on itse asiassa C , mutta sain noista muutaman hyvän idean ja taas vähän näkemystä.
Myös "kieliriippumattomat" ongelmat kiinnostavat, eli esim. loogisen ajattelun kannalta usein tulevat hazardit yms.
Kieliriippumattomia voisivat olla edellisissä:
- ja / tai -lauseiden sekoitus
- taulukoiden indeksit
- tiedostoista luku/kirjoitus, kun rivin päätösmerkkiä ei aina tarvitse antaa
C :ssa tyypillinen, mutta aika lailla kieliriippumaton ongelma, on tiedon ja sen esitystavan sotkeminen.
Siihen ehkä auttaa, jos näyttää (vaikkapa debuggerilla ihan), miltä näyttävät muistissa esim.
merkkijono "3.1415"
luku tyyppiä double 3.1415
Monilla on se aloittelijan vaihe, jossa he eivät yksinkertaisesti tajua, miten tietokone esittää tietoa - tai jos tajuavat, eivät osaa soveltaa.
Yleensä tämä johtaa siihen, että ohjelma ei käänny, koska tietotyypit ovat sekaisin ja vääriä. Sitten kysellään, että miksi ei.
Pointtereita muka-osaavat taas saavat uskomatonta tuhoa aikaiseksi tämän takia :-)
Delphissä
if teksti = 'vertailutekstiä' then WriteLn('Muuttujan teksti arvo on vertailutekstiä');
on aivan kelvollinen tapa verailla merkkijonoja.
Delphissä myös: jos aloittelija kirjoittaa:
if (2 < a < 12) then ...
niin Delphi antaa käännösaikaisen virheen, ei tee jotain outoa "aina tosi" -testiä C:n tapaan.
Delphissä oikea tapa testata tuo olisi:
if (2 < a) and (a < 12) then ...
Tätä taustaa vasten voi vain ihmetellä, miksi niin monessa paikassa käytetään C:tä, tässä muutama esimerkki siitä, miten Delphissä asiat ovat selkeitä, ja kääntäjä huomaa monet virheet sen sijaan, että hyväksyisi virheellisiä rakenteita.
Lisäksi, luokissa Delphissä muuttuja on heti oikeaa tyyppiä:
esim:
unit Unit1;
interface
type
TBase = class(TObject)
private
protected
public
A : Integer;
constructor Create;
destructor Destroy; override;
procedure Kokeile; virtual;
published
end;
TDerived = class(TBase)
private
protected
public
B : Integer;
constructor Create;
destructor Destroy; override;
procedure Kokeile; override;
published
end;
procedure Testaa;
implementation
{ TBase }
constructor TBase.Create;
begin
inherited;
Writeln('metodi TBase.Create, tyyppi=' Classname);
end;
destructor TBase.Destroy;
begin
end;
procedure TBase.Kokeile;
begin
Writeln('metodi: TBase.Kokeile');
end;
{ TDerived }
constructor TDerived.Create;
begin
Writeln('metodi TDerived.Create, tyyppi=' Classname);
inherited;
end;
destructor TDerived.Destroy;
begin
end;
procedure Testaa;
begin
with TDerived.Create do
begin
try
Kokeile;
finally
Free;
end;
end;
end;
procedure TDerived.Kokeile;
begin
Writeln('metodi: TDerived.Kokeile');
inherited;
end;
end.
tuon kun laittaa unitiin Unit1 ja kutsuu Testaa;
Niin huomaa muutamia asioita, kuten se, että
TDerived.Create .konstruktoria kutsutaan ensin, ja on sen asia päättää, missä vaiheessa (jos ollenkaan) kutsutaan kantaluokan konstruktoria (inherited).
Niissä ei ole aloittelijallakaan suuria ongelmia, sillä virheiden tekeminen on erittäin vaikeaa. Tietysti ongelman voi ymmärtää väärin, jolloin ohjelmakin on vastaavasti pielessä.
Mitä ovat graafiset kielet? Miksi niillä on vaikea tehdä virheitä? Äkkiseltään tuntuisi, että ei kielellä ole merkitystä siinä mielessä..
niitä on (visual) basic täynnä.
Liukulukujen vertailu on tyypillinen aloittelijoiden virhe (ei ehkä looginen virhe, mutta kuitenkin).
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
Vaikeimpia asioita ovat kuulemma nämä:
sijoituslauseet, eli mitvit a = a 1 tarkoittaa
sekvenssi, eli miksi asiat pitää tehdä oikeassa järjestyksesä
rinnakkaisuus, eli miksi ohjelmani jää deadlockiin
Rinnakkaisuus ei kaikissa kielissä ole aloittelijan asia.
Sijoituslauseisiin liittyviä virheitä on monia. Ihan aloittelija ei joskus tajua, että ne pitää lukea niin, että ensin mietitään, mitä oikea puoli saa arvoksi ja sitten se sijoitetaan vasemmalle. Parempi on käyttää esim. a = 1 tai vastaavia ilmauksia heti alusta asti. Tai jos kielessä onkin merkintä kuten a := a 1, niin se on helpompi tajuta aivan eri asiaksi kuin yhtäsuuruus.
Opetus: Ohjelmointi ei ole algebraa. a = a 1 ei ole yhtälö.
Sekvenssointiin liittyy paljon ongelmia. Tehdään vain asiat missä järjestyksessä sattuu ja sitten odotetaan, että kone tajuaa asiat "kuten ihminen". Näitä virheitähän tekee kokenut ohjelmoijakin melko säännöllisesti. Omat ajatukset kun eivät ole tarpeeksi selviä, niin koodista tulee virheellinen.
Pitää siis oppia seuraamaan ohjelman suoritusta mielessään.
Näitä minä muista kuulleeni paljon. "Kyllä minä tuossa kohdassa sanon sille, että se tekee näin. Miksi se ei sitten tee niin täällä kohdassa?"
Rinnakkaisohjelmointi taas on niin vaikea ja laaja asia, että ei tässä kannata luetella mahdollisia virheitä.
Tyyliseikat ovat myös vaikeita. Moni, kun oppii if-lauseet eka kerran, luulee että niitä kannattaa laittaa sata ja tuhat aina peräkkäin. No ei. Pienikin modulaarisuus on aina eduksi :-)
Erityinen virhe vielä lopuksi. C-kielen tyylisissä kielissä on monesti hankala oppia oikea tapa esittää yhtäaikaisten testien logiikka.
if (3 < a < 12) { ...
Testi näyttää ihan oikealta ja jopa kääntyy. Mutta eihän se testaa mitään järkevää, vaan on aina tosi. C-ohjelmoija tietää miksi. Oikein on
if ( 3 < a && a < 12) { ...
Nämä jutut, mitkä kääntyvät jotenkin ja muka toimivat, ovat aina vaikeita. Ankarampi kieli on joskus parempi aloittelijalle, kuin huolettomasti käytetty C.
No, auttaa se -Wall jotain. Lisäksi aina on asioita, jotka pitää vain osata, oli kieli mikä vain.
Hyviä huomioita. Mainitsit asioita, jotka tuskin olisivat minulle tulleet mieleen.
Kiitos!