Gyakorlati alapok
Gyorsan tanuljuk meg: a refaktorálás
A refaktorálás (angol szakszóval refactoring) egyszerűen fogalmazva a kód optimalizálását vagy valamilyen szintű manipulációját jelenti.
Például alacsony szintű a refaktorálás, ha a kódban egy metódust szeretnénk átnevezni (rename). Ez azonban nem csupán a MS Word szövegszerkesztő program Csere parancsa, hiszen a metódusra való hivatkozás sok osztály rengeteg helyén fordulhat elő és a fejlesztői környezetnek (a jelen esetben az általunk használt Eclipse platformnak) az összes hivatkozást érzékelnie és az átnevezés során javítania kell.
A magas szintű refaktorálás során a fejlesztői környezetnek bizonyos mértékig már a kód szemantikai, tartalmi elemeit is tudnia kell kielemeznie. Ennek természetesen vannak korlátai, hiszen azért mégsem veheti át a programozó analitikus feladatát, de bizonyos esetekben azt jelentős mértékben megkönnyítheti. Az intelligens fejlesztői környezetnek többek között képesnek kell lennie:
-
a kódban többször szereplő, de ugyanazon funkciójú kód felfedezésére,
-
túl bonyolult (ezek legtöbbször egymásba ágyazott /nested/) ciklusok optimalizálására,
-
stb.
Az alábbi rövid példában az alacsony szintű refaktorálás Átnevezés (rename) parancsát gyakoroljuk ki. A példakódok írása során ugyanis a magam részéről gyakran futottam bele abba a hibába, hogy kezdetben rossz vagy valamilyen szempontból helytelen változó-, vagy metódusnevet adtam meg; szerintem ezzel mások is ugyanígy lesznek. Ha a nevet többször felhasználtam már, akkor érdemes volt inkább a refactor - rename műveletet kiadnom, mint kézzel keresgélni meg az összes, névre való hivatkozást.
Ezen művelet kigyakorlására vegyünk egy olyan példakódot, amelyben egy változónév sokszor fordul elő. A lehetséges kódok közül én a Keresések rendezett tömbben című fejezetben ismertetett egyik tömbrendezéses algoritmust vettem elő:
import java.util.*;
public class Main {
public static void main(String[] args) {
int [] tomb = new int[10];
int keresettSzam = 0;
int keresettSzamIndex = 0;
Random rnd = new Random();
Scanner in = new Scanner(System.in);
boolean talalat = false;
System.out.println("Tömb rendezés előtt:");
for(int i = 0; i < tomb.length; i++){
tomb[i] = rnd.nextInt(100) + 1;
System.out.print(tomb[i] + " ");
}
System.out.println();
do{
System.out.print("Kérem, hogy adjon meg egy számot (1 és 100 között):\n");
String szamString = in.nextLine();
keresettSzam = Integer.parseInt(szamString);
}while (keresettSzam < 1 || keresettSzam > 100);
for(int i = 0; i <= tomb.length - 1; i++){
for(int j = i + 1; j <= tomb.length - 1; j++){
if(tomb[i] > tomb[j]){
int tarolo = tomb[i];
tomb[i] = tomb[j];
tomb[j] = tarolo;
}
}
}
System.out.println("A rendezett tömb:");
for(int i = 0; i < tomb.length; i++) {
System.out.print(tomb[i] + " ");
}
System.out.println();
int kozep = tomb.length / 2;
if((keresettSzam >= tomb[kozep])){
for(int i = kozep; i < tomb.length; i++){
if(tomb[i] == keresettSzam){
talalat = true;
keresettSzamIndex = i;
break;
}
}
}
else if(keresettSzam < tomb[kozep]){
for(int i = kozep; i >= 0; i--){
if((tomb[i] == keresettSzam)){
talalat = true;
keresettSzamIndex = i;
break;
}
}
}
if(talalat == true){
System.out.println("\nA keresett benne van a tömbben,
a(z) " +
(keresettSzamIndex+1) + ". indexen.");
}
else
System.out.println("\nA keresett szám nincs a tömbben.");
}
}
Végeredmény (például):
Tömb rendezés előtt:
8 22 35 27 61 27 86 84 53 52
Kérem, hogy adjon meg egy számot (1 és 100 között):
53
A rendezett tömb:
8 22 27 27 35 52 53 61 84 86
A keresett benne van a tömbben, a(z) 7. indexen.
Legyen most a feladat a tomb változónév átnevezése alapTomb változónévre!
A kódot először egy az egyben másoljuk a Main osztályba, majd kattintsunk arra a hivatkozásra, amelyben az átnevezendő változónév először fordul elő, ez mindig a változó deklarációja:
int [] tomb = new int[10];
Jelöljük ki a változónevet dupla egérkattintással, ekkor az Eclipse platform láthatóan szürkével kijelölte a változónév összes többi hivatkozását is.
Kattintsunk egyet rá jobb egérgombbal és a legördülő menüből adjuk ki a Refactor - Rename parancsot.
Ekkor a változónév alatt megjelenik egy kis szövegnégyzet és benne a következő utasítás olvasható:
Enter new name, press Enter to refactor
Tegyünk az utasítás szerint: írjuk be az új változónevet, majd nyomjunk meg az Enter billentyűt. Ám a gépelés során az Eclipse már folyamatosan az összes helyen írja át az új névre a régit, az Enter csak a parancs véglegesítése. Természetesen a kódban szemantikailag-tartalmilag semmi nem változott, ezért azonnal futtatható:
import java.util.*;
public class Main {
public static void main(String[] args) {
int [] alapTomb = new int[10];
int keresettSzam = 0;
int keresettSzamIndex = 0;
Random rnd = new Random();
Scanner in = new Scanner(System.in);
boolean talalat = false;
System.out.println("Tömb rendezés előtt:");
for(int i = 0; i < alapTomb.length; i++){
alapTomb[i] = rnd.nextInt(100) + 1;
System.out.print(alapTomb[i] + " ");
}
System.out.println();
do{
System.out.print("Kérem, hogy adjon meg egy számot (1 és 100 között):\n");
String szamString = in.nextLine();
keresettSzam = Integer.parseInt(szamString);
}while (keresettSzam < 1 || keresettSzam > 100);
for(int i = 0; i <= alapTomb.length - 1; i++){
for(int j = i + 1; j <= alapTomb.length - 1; j++){
if(alapTomb[i] > alapTomb[j]){
int tarolo = alapTomb[i];
alapTomb[i] = alapTomb[j];
alapTomb[j] = tarolo;
}
}
}
System.out.println("A rendezett tömb:");
for(int i = 0; i < alapTomb.length; i++) {
System.out.print(alapTomb[i] + " ");
}
System.out.println();
int kozep = alapTomb.length / 2;
if((keresettSzam >= alapTomb[kozep])){
for(int i = kozep; i < alapTomb.length; i++){
if(alapTomb[i] == keresettSzam){
talalat = true;
keresettSzamIndex = i;
break;
}
}
}
else if(keresettSzam < alapTomb[kozep]){
for(int i = kozep; i >= 0; i--){
if((alapTomb[i] == keresettSzam)){
talalat = true;
keresettSzamIndex = i;
break;
}
}
}
if(talalat == true){
System.out.println("\nA keresett benne van a tömbben,
a(z) " +
(keresettSzamIndex+1) + ". indexen.");
}
else
System.out.println("\nA keresett szám nincs a tömbben.");
}
}
Végeredmény (például):
Tömb rendezés előtt:
8 22 35 27 61 27 86 84 53 52
Kérem, hogy adjon meg egy számot (1 és 100 között):
53
A rendezett tömb:
8 22 27 27 35 52 53 61 84 86
A keresett benne van a tömbben, a(z) 7. indexen.
Refaktorálásnál vegyük figyelembe, hogy a rendszer csakis azt a változót-műveletet-objektumot képes látni (és ezáltal refaktorálás alá vonni), amelyik előzetesen deklarálva volt.