A kiválasztott változat és az aktuális verzió közötti különbségek a következők.
Előző változat mindkét oldalon Előző változat Következő változat | Előző változat | ||
oktatas:programozas:tisztakod [2021/09/03 18:04] admin [Gyakorlat 01] |
— (aktuális) | ||
---|---|---|---|
Sor 1: | Sor 1: | ||
- | [[oktatas:programozás|< Programozás]] | ||
- | |||
- | ====== Tisztakód ====== | ||
- | |||
- | * **Szerző:** Sallai András | ||
- | * Copyright (c) Sallai András, 2020, 2021 | ||
- | * Licenc: [[https://creativecommons.org/licenses/by-sa/4.0/|CC Attribution-Share Alike 4.0 International]] | ||
- | * Web: https://szit.hu | ||
- | |||
- | ===== A tisztakód ===== | ||
- | |||
- | A programozók sokkal több kódot olvasnak mint írnak, ezért | ||
- | fontos, hogy kód ne legyen zavaros, mint a mocsár. A haladó programozók | ||
- | tudják, hogy a zavaros kódok, amiket vissza kell olvasni, | ||
- | nagyban lassítják a munkát. Mégis, sokszor úgy érzik, nekik is | ||
- | ilyet kell írniuk, csakhogy haladjon a munka. | ||
- | Az ilyen kód lehúz mint a mocsár, és nem fogjuk tudni | ||
- | tartani a határidőt. | ||
- | |||
- | |||
- | A kódot ezért úgy kell megírni, hogy mindig olvasmányos legyen, | ||
- | kevés ránézéssel tudjuk mit csinál, meglepetések nélkül. | ||
- | |||
- | A kód tisztán írása és tartása, művészet. | ||
- | |||
- | Ez a rövid leírás Robert Martin: Tiszta kód című könyve alapján | ||
- | készül. | ||
- | |||
- | ===== Elnevezések ===== | ||
- | |||
- | ==== Beszédes nevek ==== | ||
- | |||
- | A változók, állandók, osztályok és függvények létrehozása során | ||
- | a rossz névadás a kódmocsár irányába lökjük a kódunkat. | ||
- | |||
- | A jó elnevezéshez három dolgot vizsgáljunk meg az elnevezendő részről: | ||
- | * mi az oka létezésének | ||
- | * mit csinál, mi a szerepe | ||
- | * hogyan használjuk | ||
- | |||
- | |||
- | Ha úgy érezzük megjegyzést kell fűzni egy változóhoz vagy | ||
- | állandóhoz, biztosan rossz az elnevezése. | ||
- | |||
- | |||
- | int a; //A háromszög alapja | ||
- | |||
- | |||
- | |||
- | ==== Félrevezetés ==== | ||
- | |||
- | Kerüljük a félrevezető elnevezéseket. A közismert nevek | ||
- | például félrevezetők. | ||
- | |||
- | A bin, például Unix alapú rendszerekben a bináris szóra utal, | ||
- | illetve kettes számrendszerben megadott számokra is utalhat. | ||
- | Ha mi a belső indexet így szeretnénk rövidíteni, az félrevezető. | ||
- | |||
- | Példák az ismert azonosítókra, közismert és egyéni értelemmel: | ||
- | |||
- | * bin - binary | ||
- | * belső index | ||
- | * pc - personal computer | ||
- | * pozitív cél | ||
- | * tv | ||
- | * tiltott viselkedés | ||
- | * tevékenység | ||
- | |||
- | |||
- | A List szó félrevezető, ha olyan gyűjtemény nevében használjuk, | ||
- | ami nem List szerkezetben van tárolva. Például: | ||
- | |||
- | dolgozoList | ||
- | |||
- | Ilyenkor válasszuk például a következőket: | ||
- | dolgozoCsoport | ||
- | dolgozok | ||
- | |||
- | Az O használata is megtévesztő lehet: | ||
- | if( 0 == 35) | ||
- | |||
- | ==== A nevek kimondhatósága ==== | ||
- | Válasszunk olyan neveket, amit könnyű kimondani. | ||
- | Ha egy névben nincsenek magánhangzók, nem könnyű azokat kimondani. | ||
- | |||
- | A dkn, a dolgozó keresztnevének rövidítésre például nem ajánlott: | ||
- | dkn - dolgozó keresztnevek | ||
- | |||
- | Legyen helyette: | ||
- | dolgozoKeresztnev | ||
- | |||
- | ==== A nevek kereshetősége ==== | ||
- | |||
- | Az egybetűs azonosítók keresése rémálom. Kerüljük a használatát. | ||
- | |||
- | |||
- | ==== Típuskódolás ==== | ||
- | |||
- | A névben a típus kódolása kerülendő. Régebben indokoltak voltak | ||
- | ezek az eljárások, mint a "magyar jelölés", vagy az tagváltozó | ||
- | jelölése. A tagváltozót egy m_ karakter előtag párral jelölhetjük. | ||
- | |||
- | A felületek (interfész) nevébe sem ajánlott beletenni a i vagy I | ||
- | karaktereket. Helyette tegyük a hozzátartozó megvalósításba | ||
- | mondjuk Imp szót, vagy magyarul Megval, vagy hasonló szót. | ||
- | |||
- | DolgozoGyarMegvalositas | ||
- | DolgozoGyarMeg | ||
- | |||
- | |||
- | ==== Osztálynevek ==== | ||
- | |||
- | Az osztálynevek legyenek mindig főnevek vagy főnévi kifejezések. | ||
- | |||
- | Robert Martin szerint kerülendők még a következő | ||
- | szavak az osztályok neveiben: Manager, Processor, Data, Info | ||
- | és hasonlók. | ||
- | |||
- | ==== Tagfüggvények ==== | ||
- | |||
- | A tagfüggvények nevei mindig igék, vagy igei kifejezések. | ||
- | |||
- | Az elérő függvények előtagjai legyenek: | ||
- | * set | ||
- | * get | ||
- | * is | ||
- | |||
- | Ha magyar tagfüggvény neveket használunk, akkor | ||
- | nem valami szép az ilyen név: | ||
- | getNev() | ||
- | Ez hunglish nyelven van írva, azaz félig magyar, félig | ||
- | angol. Ha mégis mellette döntünk, akkor használjuk | ||
- | következetesen. Jobb ötlet megkeresni a szavak | ||
- | angol megfelelőjét: | ||
- | getName() | ||
- | |||
- | Esetleg a get, set és is helyett magyar változatok | ||
- | keresése: | ||
- | lekerNev() | ||
- | beallitNev() | ||
- | |||
- | Az is helyett nehéz a magyar nyelvben megfelelő szót találni. | ||
- | |||
- | |||
- | A konstruktorok túlterhelése helyett, használjunk gyártó metódust. | ||
- | |||
- | Dolgozo dolgozo = Dolgozo.nevvel("Nagy János"); | ||
- | |||
- | ==== Jófejkedés ==== | ||
- | |||
- | Kerüljük a jófejkedést, például szülőfüggvényecske. | ||
- | |||
- | ==== Egy fogalom, ugyanaz a szó ==== | ||
- | |||
- | Ha egy fogalomra használunk egy szót, akkor legyünk következetesek | ||
- | és mindig ezt használjuk. | ||
- | fetchName() | ||
- | fetchCity() | ||
- | fetchSalary() | ||
- | |||
- | Vagy: | ||
- | getName() | ||
- | getCity() | ||
- | getSalary() | ||
- | |||
- | ==== Szóviccek ==== | ||
- | |||
- | A szóvicceket is kerüljük, de mit értünk szóvicc alatt? | ||
- | Két eltérő fogalmat ugyanazzal a szóval jelölünk. | ||
- | |||
- | ==== Megoldás és feladat tartományok ==== | ||
- | |||
- | Ha van megoldástartományból a szakmában használatos név, | ||
- | használjuk azt. Ha nincs maradhat a feladattartomány. | ||
- | |||
- | |||
- | ==== Gyakorlat 01 ==== | ||
- | === Feladat 01 === | ||
- | |||
- | Vajon mit csinál a következő függvény? | ||
- | <code java> | ||
- | trinangleCalc(); | ||
- | </code> | ||
- | |||
- | |||
- | Többet mond, ha paraméterrel kell hívni? | ||
- | triangleCalc(30, 35, 45); | ||
- | |||
- | |||
- | === Feladat 02 === | ||
- | |||
- | Adott egy metódus, amely beállítja egy jármű sebességét, véletlenszerűen. | ||
- | Vagy gyorsít vagy lassít. | ||
- | <code java> | ||
- | public Car extends JComponent { | ||
- | int d; | ||
- | Integer e; | ||
- | Car() { | ||
- | | ||
- | } | ||
- | public void doit(){ | ||
- | Random a = new Random(); | ||
- | boolean b = a.nextBoolean(); | ||
- | int c = a.nextInt(3) + 1; | ||
- | | ||
- | if(b) { | ||
- | if(d>(this.e + c)) { | ||
- | this.e = this.e + c; | ||
- | } | ||
- | }else { | ||
- | if((this.e - c) >0){ | ||
- | this.e = this.e - c; | ||
- | } | ||
- | } | ||
- | } | ||
- | |||
- | } | ||
- | </code> | ||
- | |||
- | |||
- | ===== Függvények ===== | ||
- | |||
- | ==== Méret ==== | ||
- | |||
- | A függvények mérete legyen minél kisebb. Ha 3-4 sor, akkor | ||
- | az már jó. Ennek eredménye lehet, hogy egy if vagy while | ||
- | törzsében csak egy függvényhívás van. Ez jó. | ||
- | Ha ilyen rövid függvényeink vannak, akkor valószínűleg | ||
- | elkerültük az egymásba ágyazott kifejezéseket is. | ||
- | |||
- | |||
- | ==== Egyetlen feladat ==== | ||
- | |||
- | Egy függvény csak egyetlen feladatot csináljon, de azt | ||
- | jól csinálja. | ||
- | |||
- | ==== Sorrend ==== | ||
- | |||
- | A függvényeket fentről lefele írjuk egymás után. | ||
- | Ezt nevezik leszállószabálynak. | ||
- | |||
- | <code java Triangle.java> | ||
- | |||
- | package haromszog; | ||
- | |||
- | public class Haromszog { | ||
- | |||
- | public static void main(String[] args) { | ||
- | | ||
- | double perimeter = calcPerimeter(30, 35, 40); | ||
- | System.out.println("Perimeter: " + perimeter); | ||
- | } | ||
- | |||
- | public static double calcPerimeter(double sideA, double sideB, double sideC) { | ||
- | double perimeter = -1; | ||
- | if(isEditable(sideA, sideB, sideC)) { | ||
- | perimeter = sideA + sideB + sideC; | ||
- | } | ||
- | return perimeter; | ||
- | } | ||
- | | ||
- | public static boolean isEditable(double sideA, double sideB, double sideC) { | ||
- | boolean editable = true; | ||
- | if(sideA + sideB < sideC) { | ||
- | editable = false; | ||
- | } | ||
- | if(sideA + sideC < sideB) { | ||
- | editable = false; | ||
- | } | ||
- | if(sideB + sideC < sideA) { | ||
- | editable = false; | ||
- | } | ||
- | return editable; | ||
- | } | ||
- | } | ||
- | |||
- | </code> | ||
- | |||
- | |||
- | |||
- | |||
- | === Javított verzió === | ||
- | |||
- | |||
- | <code java Sides.java> | ||
- | class Sides { | ||
- | double a, b, c; | ||
- | public Sides(double a, double b, double c) { | ||
- | this.a = a; | ||
- | this.b = b; | ||
- | this.c = c; | ||
- | } | ||
- | } | ||
- | </code> | ||
- | |||
- | |||
- | <code java Triangle.java> | ||
- | public class Triangle { | ||
- | |||
- | public static void main(String[] args) { | ||
- | Sides sides = new Sides(30, 35, 40); | ||
- | double perimeter = calcPerimeter(sides); | ||
- | System.out.println("Perimeter: " + perimeter); | ||
- | } | ||
- | |||
- | public static double calcPerimeter(Sides sides) { | ||
- | double perimeter = -1; | ||
- | if(isEditable(sides)) { | ||
- | perimeter = sides.a + sides.b + sides.c; | ||
- | } | ||
- | return perimeter; | ||
- | } | ||
- | | ||
- | public static boolean isEditable(Sides sides) { | ||
- | boolean editable = true; | ||
- | if(sides.a + sides.b < sides.c) { | ||
- | editable = false; | ||
- | } | ||
- | if(sides.a + sides.c < sides.b) { | ||
- | editable = false; | ||
- | } | ||
- | if(sides.b + sides.c < sides.a) { | ||
- | editable = false; | ||
- | } | ||
- | return editable; | ||
- | } | ||
- | } | ||
- | </code> | ||
- | |||
- | ==== Beszédes nevek ==== | ||
- | |||
- | Keressük meg a legbeszédesebb neveket. Ha bizonytalanok vagyunk, | ||
- | próbáljunk meg több nevet is. Használjunk bátran hosszú neveket. | ||
- | A nevek megválasztásánál legyünk itt is következetesek. | ||
- | |||
- | ==== Paraméterek ==== | ||
- | |||
- | Az a legideálisabb ha egy függvénynek egyetlen paramétere sincs. | ||
- | |||
- | |||
- | Előfordul, hogy van egy paraméterünk, amivel kapcsolatban valamilyen | ||
- | kérdésre szeretnénk választ adni, vagy azon egy műveletet szeretnénk | ||
- | elvégezni. A függvény nevében következetesen szét kell választani | ||
- | ezt két tevékenységet. | ||
- | |||
- | Vannak a jelzőparaméterek, amelyek használatát kerülni kell. | ||
- | A jelző paraméter, amikor például átadok egy logikai | ||
- | paramétert, amely megmondja, hogy amin művelete kell | ||
- | végezni az milyen állapotban van. Az ilyen függvények | ||
- | helyett írjunk két függvényt, amely mindkét állapotra | ||
- | megoldást nyújt. | ||
- | |||
- | Tegyük fel, hogy van egy függvényünk, ami képes PostgreSQL | ||
- | és MariaDB adatbázishoz kapcsolódni. Hogy melyikhez kapcsolódik | ||
- | egy állandóval jelezzük. | ||
- | |||
- | <code java DatabaseCon.java> | ||
- | |||
- | class DatabaseConn { | ||
- | public Connection connect(DatabaseType.PostgreSQL) { | ||
- | ... | ||
- | } | ||
- | } | ||
- | </code> | ||
- | |||
- | Az ilyen szerkezetek kerülendők. Írjunk helyette két | ||
- | külön függvényt. Az egyik PostgreSQL adatbázis kapcsolatához, | ||
- | a másik a MariaDB-hez. | ||
- | |||
- | Ha egy függvénynek 2-3 paraméternél többre van szüksége, | ||
- | csomagoljuk egy osztályba. | ||
- | |||
- | |||
- | |||
- | ==== Mellékhatások ==== | ||
- | |||
- | Ha egy művelet hatással van olyan változókra, objektumokra | ||
- | amely kívül esik tervezett célon, akkor azt mellékhatásnak | ||
- | nevezzük. | ||
- | |||
- | |||
- | Adott egy függvény, ami MariaDB adatbázishoz kapcsolódik. | ||
- | |||
- | |||
- | <code java DatabaseCon.java> | ||
- | class Mariadb { | ||
- | boolean connected = false; | ||
- | public Connection connect() { | ||
- | ... | ||
- | connected = true; | ||
- | } | ||
- | } | ||
- | </code> | ||
- | |||
- | |||
- | Matematikai értelemben ((https://softwareengineering.stackexchange.com/questions/40297/what-is-a-side-effect)), ha egy függvénynek | ||
- | nincs visszatérési értéke, biztosan van valami | ||
- | mellékhatása. Például megváltoztatja az objektum | ||
- | állapotát. | ||
- | |||
- | Nekünk most, fontosabb mi a függvény | ||
- | létrehozásának célja. Ha megváltoztatja egy objektum | ||
- | állapotát, az lehet csak hatás, ha ez volt a függvény | ||
- | létrehozásának célja. Ha visszaad valamit | ||
- | a függvény, akkor általában nem az a célja, hogy | ||
- | megváltoztasson valahol egy objektumot. | ||
- | |||
- | |||
- | ==== Kimeneti paraméterek ==== | ||
- | |||
- | <code java> | ||
- | class Program01 { | ||
- | public static void main(String[] args) { | ||
- | StringBuffer msg = null; | ||
- | getMessage(msg); | ||
- | System.out.println(msg); | ||
- | } | ||
- | public static void getMessage(StringBuffer msg) { | ||
- | msg.append("Helló Világ"); | ||
- | } | ||
- | } | ||
- | </code> | ||
- | |||
- | |||
- | |||
- | ===== Irodalom ===== | ||
- | |||
- | * Robert C. Martin: Tiszta kód (2010, Budapest, KISKAPU) | ||
- | |||
- | |||