Arv Series – S01E02

Ok, det är dags att diskutera följande:

Lägg till en “default-konstruktor”

Detta är värt att diskutera!

Kolla (eller kanske lyssna?) på vår podcast om detta: https://juneday.podbean.com/e/arv-series-s01e02/

Låt oss utgå ifrån följande klass och arvshierarki (nej, vi gillar inte detta arv i sig). Här är ett “UML-liknande diagram” över vår struktur:

       
       +----------------+
       |   Person       |
       +----------------+
       |  name: String  |
       +----------------+
       | Person(String) |
       +----------------+
           ^
          /
         /
    +--------------------------+
    |   Employee               |
    +--------------------------+
    |  email: String           |
    +--------------------------+
    | Employee(String, String) |
    +--------------------------+

 

net/Person.java

package net;

public class Person {

 String name;

 public Person (String name) {
   this.name = name;
 }
}

net/Employee.java

package net;
package net;

public class Employee extends Person {

  String email;

  public Employee (String name, String email) {
    this.name = name;
    this.email = email;
  }

  public String toString() {
      return super.toString().toUpperCase() + "<" + email + ">";
  }
}

Detta ser la ok ut, eller?
Hmmm: om du tycker att det är konstigt att vi inte har private som åtkomstmodifierare (access modifier) så håller vi med, vi håller oss till vad böcker brukar lära ut!

Problem #1: Vad an default-konstruktor?

En default-konstruktor är något vi “får gratis” (på köpet) av Javs kompilator . Om vi inte har skrivit någon enda konstruktor så skapar javac en åt oss, en så kallad default-konstruktor, typ enligt följande

  public Person () { ; }

Om vi skriver en egen konstruktor, t ex med tom parameterlista:

  public Employee () { ; }

så får vi ingen konstruktor “på köpet”. Men den konstruktor vi skrivit är ej heller en default-konstruktor.

Alltså, om vi skriver

  public Employee () { ; }

… så kan vi inte kalla den “default-konstruktor” då vi inte får den “på köpet av Javac”.

Problem #2: Kompilerar inte

Om vi inte lägger till en konstruktor med tom parameterlista,  så kompilerar det inte. Kompilator klagar enligt följande (eller liknande):

 
 net/Employee.java:7: error: constructor Person in class Person cannot be applied to given types;
 public Employee (String name, String email) {
 ^
 required: String
 found: no arguments
 reason: actual and formal argument lists differ in length
 net/Employee.java:16: error: constructor Person in class Person cannot be applied to given types;
 public Employee () { ; }
 ^
 required: String
 found: no arguments
 reason: actual and formal argument lists differ in length

Vad är då lösningen?

Dålig lösning

Enkelt!!!! Enligt de flesta böcker vi läst ach lärare vi hört gör du följande i Person.java:

public Person () { ; }

But no….. Det här leder till problem. Tänk dig följande:

    Employee empoli = new Employee();
    System.out.println("empoli: " + empoli);

Vad händer nu då?

javac net/Person.java  net/Employee.java net/EmployeeTest.java  && java net.EmployeeTest 
Exception in thread "main" java.lang.NullPointerException
	at net.Employee.toString(Employee.java:13)
	at java.lang.String.valueOf(String.java:2994)
	at java.lang.StringBuilder.append(StringBuilder.java:131)
	at net.EmployeeTest.main(EmployeeTest.java:12)

Varför hände detta då? Jo, för att vi i vår design tillåter icke-initierade objekt att skapas genom vår konstruktor:

  public Employee () { ; }

Varför har då så himla många böcker och vaför säger lärare att vi skall göra så här?????

Varför rekommenderar författare och lärare (som vi som skriver denna blog/pod) studenter att skriva konstruktorer med tom parameteerlista? Vi vet ärligt talat inte varför detta görs.

Ibland görs det implicit när man visar kod. Ibland görs det explicit:

// Filen Person.java

class Person {
  protected String namn, adress;   // Obs! protected
  protected int född;              // Obs! protected

  protected Person() {} // måste finnas för subklassernas skull

  .......
}

http://www.cse.chalmers.se/~skanshol/Java_dir/losn8/kap04/ex4-3.txt

Kommentar: det kan absolut finnas skäl till en konstruktor med tom parameterlista, t ex vid reflection, men att säga att det behövs för “subklassernas skull” är direkt fel. Vi skulle nog gå så långt att vi säger att det kan medföra skada för studenternas förståelse för arv och Javas regler.

Om du som lärare läst eller kansker använder boken ovan finns det en risk att detta förs vidare till studenter/elever då du litade på författaren (av olika skäl).

Problem #3: Åtkomstsmodifierare

I vårt fall hade vi inga åtkomstsmodifierare så vi fick alltså default (package private). Detta gör att ärvande klasser, t ex Manager.

package net.ext;

import net.Employee;

public class Manager extends Employee {

  public Manager (String name, String email) {
    this.name = name;
    this.email = email;
  }

}

Om vi kompilerar får vi följande fel:

net/ext/Manager.java:8: error: name is not public in Person; cannot be accessed from outside package
 this.name = name;
 ^
net/ext/Manager.java:9: error: email is not public in Employee; cannot be accessed from outside package
 this.email = email;
 ^
2 errors

Ok…. vad är felet? …. felet är att javac lägger till ett anrop till basklassens konstruktor med tom parameterlista. Om vi själva anropar en kontruktor i basklassen gör javac inget implicit anrop. I kort kan man säga att koden ovan ser ut så här:

package net.ext;

import net.Employee;

public class Manager extends Employee {

  public Manager (String name, String email) {
    super();
    this.name = name;
    this.email = email;
  }

}

Anropet till super (markerat med fetstil) läggs till i byte-koden[1] av kompilatorn.

Vi använder en konstruktor (sker implicit) med tom parameterlista och sedan manuellet sätter värden på variablerna i bas-klassen.

Men hur skall man göra då?

Bättre att istället använda existerande konstruktor.

Skriv om enligt följande:

  • inga klasser har konstruktorer med tom parameter-lista
  • anropa alltid explicit en existernade konstruktorer i basklassen, m h a super

Disclaimer:

Eftersom vi i övrigt anser:

  • arv mellan Person, Employee och Manager inte kan motiveras i ett riktigt system
  • i och med att det inte finns publika åtkomstsmetoder kommer man inte åt värdena
  • det enda som skiljer Employee och Person är att Employee har ytterligare data kan man inte programmera mot superklassen (Person) utan att casta ned till underklassen (Employee) för att komma åt det som skiljer dem

 

[1]

javap -c net.ext.Manager
Compiled from "Manager.java"
public class net.ext.Manager extends net.Employee {
 public net.ext.Manager(java.lang.String, java.lang.String);
 Code:
 0: aload_0
 1: invokespecial #1 // Method net/Employee."<init>":()V
 4: aload_0
 5: aload_1
 6: putfield #2 // Field name:Ljava/lang/String;
 9: aload_0
 10: aload_2
 11: putfield #3 // Field email:Ljava/lang/String;
 14: return
}

Posted in Uncategorized | Leave a comment

Arv Series – S01E01

Ok, dags för en av våra favorit-hat-grejer. Arv, enligt gängse uppfattning.

Här hittar du motsvarande pod(d)cast: https://juneday.podbean.com/e/arv-series-s01e01/

Vi har sett i bok efter bok, kurs efter kurs och hört av lärare efter lärare att arv är bra på grund av att ….. Men vi har aldrig förstått vurmen för arv, i alla fall inte så som det används i  alltför många exempel. Vi har nu tagit på oss den ganska stora kostymen och drar igång en serie om just arv. Blygsamt, som vanligt!

Vi startar med att diskutera och motivera denna serie om arv. Skall vi kalla serien för Arvssynden?

Saker vi tar upp under seriens gång är:

  • När är arv mindre bra – exempel från en så kallad verklighet
  • Alternativ till Arv
  • Man sparar så mycket kod med arv
  • När arv motverkar polymorfism (kräver typecast)
  • När är arv bra

I dag fokuserar vi på att snacka om våra invändningar mot arv. Detta utan att ens prata kod. Vi gör detta genom att diskutera arvshierarkier som:

                  +-------------+                 +---------+                 
                  |             | *            1  |         |                 
                  |    Fruit    |---------------<>|  List   |                 
                  |             |                 |         |                 
                  +-------------+                 +---------+                 
                   /\   /\   /\
                  /__\ /__\ /__\
                   /    |     \
                 /      |       \
               /        |         \
             /          |           \
           /            |             \
    +---------+     +---------+       +---------+       
    |         |     |         |       |         |       
    |  Apple  |     |  Orange |       |  Grape  |       
    |         |     |         |       |         |       
    +---------+     +---------+       +---------+       

Saxat från: http://courses.washington.edu/css343/zander/Code/fruituml

Eller följande:

                  +-------------+                  
                  |             |                 
                  |  Employee   |                 
                  |             |                               
                  +-------------+               
                   /\   /\   /\
                  /__\ /__\ /__\
                   /    |     \
                 /      |       \
               /        |         \
             /          |           \
           /            |             \
    +---------+     +----------+       +---------+       
    |         |     |          |       |         |       
    | Project |     |Developer |       | System  |       
    | Manager |     |          |       | Admin   |     
    +---------+     +----------+       +---------+      

Eller varför inte den här:

animal

som kommer från: http://cse.csusb.edu/dick/cs202/abstraction.html. Hittar ingen licens men eftersom det är ett universitet utgår vi ifrån att vi får använda i utbildningssyfte. OBS: bilden ovan visar förmodligen Abstrakt basklass eller inteface vilket gör bilden mer begriplig.

Posted in Uncategorized | Leave a comment

En bild säger mer än tusen ord

Ny podcast En bild säger mer än tusen ord. Detta är första delen i en, vad vi hoppas på, serie om ordspråk vi finner i bästa fall konstiga och i de flesta fall rent ut sagt dumma. Vi börjar med en gemensam favorit: “En bild säger mer än tusen ord”.

Borde vi gjort en bild istället för en pod och en blog?

Här är en bild från vår planering av podden (eller poden?):

 

20170306_141806

Planering av pod(d)en

Och här en bild när vi spelar in:

20170306_150156

Inspelning, på pedagogen på Göteborgs Universitet

Som ni redan förstått så säger ju bilderna mer än våd pod(d) så varför lyssna?

Om någon betvivlar våra akademiska meriter så säger den här bilden mer än tusen ord, d v s mer än sisådär 3-4 “papers”:

20170306_144506

 

Posted in Uncategorized | Tagged , , , , | Leave a comment

Podcast: Undvik för svåra övningar

Podcast: https://juneday.podbean.com/e/undvik-for-svara-ovningar/

Baserat på följande sida[1] på vår wiki[2] pladdrar vi i dag om att

Undvika för svåra övningar

Vad innebär det? I kort, som vi ser det bör man ställa frågan om det är av intresse att ha med sig stundenterna och deras motivation. Om svaret är:

  • ja – läs vidare
  • nej – fortsätt jobba som du alltid gjort

I sidan vi refererar till ovan pratar vi om att det är viktigt att stärka studenternas självförtroende. Gör vi detta genom att ge dem för svåra uppgifter? Gör vi detta genom att inte ge dem övningsuppgifter och sedan en svår inlämningsuppgift?

Vad kan vara för svårt då? Programmering är säkert svårt nog att lära sig med tanke på alla regler för syntax och semantik. Varför då lägga på ytterligare ett problem i

  1. formuleringen av uppgiften
  2. uppgiftens natur (t ex Fibonacci)

Vad vi menar är att när man lär ut ett nytt koncept eller en ny teknik behöver inte uppgifterna för att öva just detta vara sofistikerade eller komplicerade. Det räcker kanske att lösa enkla problem för att nöta in det nya konceptet.

Exempel:

  • För att lära ut metoder behöver du inte ge en uppgift där man skall skriva en metod som med hjälpa av rekursion räknar det n:e Fibonacci-talet.
  • För att öva på for-loopen behöver man inte ge studenterna en uppgift där man behöver öppna och läsa i från en fil, dessutom med ett konstigt format (t ex kommaseparerad lista) och hantera Exception på köpet.
  • För att förstå konceptet Lista behöver man inte söka (med hjälp av t ex binarySearch) eller sortera listan. I just detta fall verkar det finnas någon form av konsensus bland lärare att briljera i att ta upp “algoritmer” som rör just listor.
  • Introducera inte ett koncept i stil med “det finns något som heter JTable” (Java) och sedan ge en svår övning där det förutsätts att man kan JTable.

Inlämningsuppgifter då? Vad har dessa för syfte?

  1. examinera kunskaper som lärs ut i kursen
  2. knyta ihop kursen (med avseende på vad som lärs ut)
  3. förbereda inför kommande kurs(er). Kräver dock at man har dialog med lärare samt en plan för hur kurserna relaterar till varandra samt hur man genomför denna förberedelse.

Ibland examinerar vi saker som inte kommer på tentan genom att ge ut en inlämningsuppgift istället. Hur kommer detta sig? Detta lämpar sig bra för så kallad problembaserad inlärning – vilket till mångas stora förvåning INTE innebär att man låter studenterna jobba helt själva.

Knyta ihop kursen. Visst är vissa studenter intresserade av de invididuella koncepten, men de flesta behöver nog en sammanfattande uppgift där alla koncept används och är användbara för att se värdet av de ingående delarna. Bjud då studenterna på detta. Kan du inte skriva en sådan uppgift? … hmm, då är det nog för svårt även för studenterna. Åtminstone lär du nog inte kunna handleda studenterna om du inte kan formulera/skriva/lösa uppgiften själv.

Förberedelse då? Det är ju, av flera skäl, bra att ha kurser som relaterar till eller bygger på varandra. Ibland är det bra och ibland är det dåligt om det är ett krav att ha gått kurs A för att gå kurs B. Men det är alltid bra om studenterna känner att ett program hänger ihop. T ex kan man ge en uppgift som löses på ett enkelt, men kanske inte optimalt, sätt i kurs A för att sedan diskutera denna lösning och lösa den på ett mer sofistikerat sätt i kurs B med hjälp av de nya kunskaperna som tillskansats i kurs B.

 Om uppgiften upplevs för svår i kurs A förloras alla pedagogiska mål enligt ovan.

/r+h

[1] http://virt08.itu.chalmers.se/mediawiki/index.php/Didaktiska_principer#.C2.A7_9._Undvik_f.C3.B6r_sv.C3.A5ra_.C3.B6vningar

[2] http://virt08.itu.chalmers.se/mediawiki/

Referenser i poden:

Posted in Uncategorized | Leave a comment

Ny podcast: Ge lagom många lagom löjliga rekommendationer

Så… nu har vi spelat in en ny podcast: Ge lagom många lagom löjliga rekommendationer

Nu får vi %¤# sluta upp med dumheterna. Kolla på rubriken igen.

Ge lagom många lagom löjliga rekommendationer

Vad betyder det? Inte ett skit. Hmmm, detta är väl bra om lagom är noll, det vill säga ungefär så här:

Ge inga löjliga rekommendationer

Vad har detta med programmeringsundervisning att göra? Jo, det ser ju ut ungefär så i presentationer och i böcker.

Vad är en löjlig rekommendation då?

Här är ett par exempel på rekommendationer vi sett – där ingen närmare förklaring givits:

  • “Skriv inte för långa eller korta metoder”
  • “Kommentera lagom mycket”
  • “Krångla inte till saker i onödan”
  • “Strukturera koden”

Ovanstående tips är helt oanvändbara, faktiskt löjliga, om man inte:

  1. går igenom problemen om man gör så
  2. visar med kodexempel på ett bättre sätt
  3. kvantifierar om det går

 

Exempel

“Skriv inte för långa eller korta metoder”

Vad är problemet med en lång och kort metod?

Hur lång är en lång metod? 2m? 1 Aln?

“Kommentera lagom mycket”

Vad är problemet om man inte kommenterar lagom mycket? Händer det något? Exploderar skärmen?

Vad är lagom mycket? Vad skall kommenteras?

Visa exempel-kod. Varför inte visa bra och dåliga exempel från riktiga projekt?

“Krångla inte till saker i onödan”

Här utgår vi (lärare) ifrån att studenterna faktiskt gjort ett val att krångla till det. Studenterna har med största sannolikhet gjort sitt bästa. Kan man krångla till saker om det är nödvändigt (det vill säga inte “i onödan”).

Visa exempel-kod. Varför inte visa bra och dåliga exempel från riktiga projekt?

Och om du nu dristar dig att säga vad som är enkelt, t ex påstår att:

boolean ageOk = age > 45;

if (ageOk == true) { // [1] se kommentar i slutet av posten!!

  return true;

} else {

  return false;

}

är mindre krångligt än

boolean ageOk = age > 45;

return ageOk;

eller än hellre

return age > 45;

så bör du kunna motivera detta.

BTW, det sista är det minst krångliga enligt oss!

“strukturera koden”

Hur gör man detta då? Visa, återigen, exempel!

Man kan ju till exempel visa dåligt strukturerad kod och påvisa effekterna efter en förbättrad struktur. Det är ganska lätt att skriva övningar där studenterna uppmuntras strukturera om kod enligt vissa anvisningar.

Närliggande problem: meningslösa uppräkningar

“Det finns olika protokoll för nätverkskommunikation: tcp, ip, smtp, icmp, ipx”

Detta är ett exempel på en meningslös kommentar följt av en likaledes meningslös uppräkning, eftersom ingen vidare förklaring eller kontrastering ges. Dessutom blandar man högt och lågt mellan protokoll i olika lager utan att diskutera detta.

Vad skall studenten med denna lista till? Skall detta examineras? Skall studenten lära sig detta utantill?

Allra märkligast blir det om “vi” djupdyker ned i en substandard och presenterar allsköns siffror kring denna och på samma gång visar en lista av andra substandarder. T ex

“Det finns olika programmeringsspråk: Java, C, Cobol, MasparFortran, m4, perl, .NET…. Bland C finner vi C89 (eller C90), C11 och C++17.”

Återigen blandas högt och lågt. Vi tar en dialekt av Fortran och de övriga listas som de är. .NET är förvisso inget programmeringsspråk, men det är ju populärt 😉 Plötsligt dyker man ned på en lista av olika C-standarder[2]. Och vips, så ser man en standard som inte alls är C utan C++. Oavsett vet kanske inte studenterna vad C är för något så vad skall de med listan till.

Nu kanske ni tänker att vi är löjliga och överdrivna. Löjliga och barnsliga är vi absolut. Men tyvärr är det inte taget ur luften – det är dess värre ett fullt realistiskt exempel på hur man introducerar till exempel programmering i kurser och böcker.

Ja, då var det färdiggnällt denna vecka. OBS, det heter inte “denna veckan”.

/r+h

[1] Några ord om

if (ageOk == true) {

Varför i hela friden jämför så många lärare och författare en “boolesk” variabel med true. Variabeln innehåller ju true eller false och inget annat, vilket ju är precis vad “if-satsen kräver”.

[2] huruvida det heter “standarder” eller “standards” tar vi en annan dag. Tänk t ex på hur du skriver ordet musiker i pluralform 😉

 

 

 

 

 

Posted in pedagogik, Principerna | Leave a comment

Nytt podcast-avsnitt om cirkulära definitioner

Vi har spelat in ett nytt avsnitt i vår pod-serie. Denna gång behandlar vi cirkeldefinitioner vilket vi gör utgående från en “gammal” bloggpost “Undvik cirkeldefinitioner“.

“Detta kan naturligtvis låta som en självklarhet men faktum är att vi funnit många exempel på cirkeldefinitioner i såväl kurslitteratur som föreläsningbilder (egna och andras!).

En utmaning här är att inom programmering florerar en stor mängd programmeringstekniska termer och begrepp, varav många endast låter sig förklaras i termer av ytterligare programmeringsbegrepp.”

Pod-avsnittet hittar du här: Undvik cirkeldefinitioner

Posted in Uncategorized | Leave a comment

Ny podcast om hur man (eventuellt) tar fram kurser

Utifrån en gammal blogpost (Arbeta bakifrån från lärmålet) och en wiki-sida (Arbeta bakifrån från lärmålet) diskuterar vi en av våra principer som vi strävar mot när vi tar fram kurser.

Som vanligt har vi en pod om detta: Arbeta bakifrån från lärmålet.

Diskutera gärna med oss här på bloggen. Kommentera detta inlägg direkt här under.

 

Posted in Uncategorized | Leave a comment