Clean Code 02

Download as pdf or txt
Download as pdf or txt
You are on page 1of 58

CLEAN CODE 02

REINŽENJERING INFORMACIONIH SISTEMA


2
• Uvod
• Nazivi (Names)
• Metode/Funkcije (Functions)
• Komentari (Comments)
• Formatiranje (Formatting)

• Objekti i strukture podataka (Objects and Data Structures)


• Upravljanje greškama (Error Handling)
• Testiranje (Unit Tests)

• Klase (Classes)
• Code Smells

• Junit Internals (primer)


• Refactoring SerialData (primer)

Reinženjering informacionih sistema 2020/2021


3
Metode/Funkcije (Functions) – Primer 1

public static String testableHtml( PageData pageData, boolean includeSuiteSetup) throws Exception {
WikiPage wikiPage = pageData.getWikiPage();
StringBuffer buffer = new StringBuffer();

if (pageData.hasAttribute("Test")) {
if (includeSuiteSetup) {
WikiPage suiteSetup = PageCrawlerImpl.getInheritedPage(SuiteResponder.SUITE_SETUP_NAME, wikiPage);
if (suiteSetup != null) {
WikiPagePath pagePath = suiteSetup.getPageCrawler().getFullPath(suiteSetup);
String pagePathName = PathParser.render(pagePath);
buffer.append("!include -setup .").append(pagePathName).append("\n");
}
}

WikiPage setup = PageCrawlerImpl.getInheritedPage("SetUp", wikiPage);


if (setup != null) {
WikiPagePath setupPath = wikiPage.getPageCrawler().getFullPath(setup);
String setupPathName = PathParser.render(setupPath);
buffer.append("!include -setup .").append(setupPathName).append("\n");
}
}
buffer.append(pageData.getContent()); * Robert C. Martin - Clean Code: A Handbook of Agile Software Craftsmanship

Reinženjering informacionih sistema 2020/2021


4
Metode/Funkcije (Functions) – Primer 1

if (pageData.hasAttribute("Test")) {
WikiPage teardown = PageCrawlerImpl.getInheritedPage("TearDown", wikiPage);
if (teardown != null) {
WikiPagePath tearDownPath = wikiPage.getPageCrawler().getFullPath(teardown);
String tearDownPathName = PathParser.render(tearDownPath);
buffer.append("\n")
.append("!include -teardown .").append(tearDownPathName).append("\n");
}
if (includeSuiteSetup) {
WikiPage suiteTeardown =
PageCrawlerImpl.getInheritedPage( SuiteResponder.SUITE_TEARDOWN_NAME,wikiPage);
if (suiteTeardown != null) {
WikiPagePath pagePath = suiteTeardown.getPageCrawler().getFullPath (suiteTeardown);
String pagePathName = PathParser.render(pagePath);
buffer.append("!include -teardown .").append(pagePathName).append("\n");
}
}
}
pageData.setContent(buffer.toString());
return pageData.getHtml();
}
* Robert C. Martin - Clean Code: A Handbook of Agile Software Craftsmanship

Reinženjering informacionih sistema 2020/2021


5
Metode/Funkcije (Functions) – Primer 1

public static String renderPageWithSetupsAndTeardowns(PageData pageData, boolean isSuite) throws Exception {


boolean isTestPage = pageData.hasAttribute("Test");
if (isTestPage) {
WikiPage testPage = pageData.getWikiPage();
StringBuffer newPageContent = new StringBuffer();
includeSetupPages(testPage, newPageContent, isSuite);
newPageContent.append(pageData.getContent());
includeTeardownPages(testPage, newPageContent, isSuite);
pageData.setContent(newPageContent.toString());
}
return pageData.getHtml();
}

* Robert C. Martin - Clean Code: A Handbook of Agile Software Craftsmanship

Reinženjering informacionih sistema 2020/2021


6
Metode/Funkcije (Functions)

Prvo pravilo za metode je da metode traba da budu kratke.


Drugo pravilo je da treba da budu još kraće.

Metode ne bi trebalo da budu duže od 20-tak linija.

Ukoliko imate selekcije ili iteracije, one ne bi trebalo da imaju više od jedne linije. Ukoliko je
potrebno da ima više linije, onda bi trebalo da koristite poziv neke druge metode.

Treba izbegavati ugnežđene strukture i ograničiti „dubinu“ na jednu ili dve strukture.

Reinženjering informacionih sistema 2020/2021


7
Metode/Funkcije (Functions)

Metode treba da rade jednu stvar. Treba da je rade dobro. То treba da bude jedina stvar koju rade.

public void unexecuteConsecutiveRemoveCommands(Command command){


while (command isInstanceof RemoveCommand) {
executedCommands.peek().unexecute();
unexecutedCommands.push(executedCommands.pop());
command = executedCommands.peek();
}
}

1. Proverava da li se radi o remove komandi


2. Radi unexecute() komande
3. Premešta komandu sa jednog steka u drugi

Reinženjering informacionih sistema 2020/2021


8
Metode/Funkcije (Functions)

Unutar jedne funkcije treba da budemo na jednom nivou apstrakcije.

The Stepdown Rule – želimo da svaku funkciju prate druge funkcije koje se nalaze na narednom
nivou apstrakcije.

Funkcije koje nisu na istom nivou apstrakcije i koje ne obavljaju samo jednu stvar, teško možete
podeliti u sekcije.

Reinženjering informacionih sistema 2020/2021


9
Metode/Funkcije (Functions) – Primer 3

public double calculatePay(Employee e) throws InvalidEmployeeCategory {


switch (e.category) {
case PROFESSOR:
return calculateProfessorPay(e);
case ASSISTANT:
return calculateAssistantPay(e);
case TEACHING_ASSOSIATE:
return calculateTeachingAssosiatePay(e);
case NON_TEACHING_STAFF:
return calculateNonTeachingStaffPay(e);
default:
throw new InvalidEmployeeCategory(e.category);
}
}

Reinženjering informacionih sistema 2020/2021


10
Metode/Funkcije (Functions)

Switch statements:
• Dugačke.

• Narušavaju Open Closed Principle.

• Pojaviće se u velikom broju drugih metoda.

Preporuka je da se mogu koristiti:


• samo jednom,
• ukoliko se koriste za kreiranje polimorfnih objekata,
• ukoliko su skrivene iza nasleđivanja.

Reinženjering informacionih sistema 2020/2021


11
Metode/Funkcije (Functions) – Primer 3

public abstract class Employee {


public abstract double calculatePay(); Iskorišćen je dizajnerski obrazac Factory
public abstract boolean isPayday(); što je stavljeno do znanja imenovanjem
public abstract void deliverPay(double pay); interfejsa i klasa.
}

public interface EmployeeFactory {


public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType;
}

public class EmployeeFactoryImpl implements EmployeeFactory {


public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType {
switch (r.type) {
case PROFESSOR:
return new ProfessorEmployee(r) ;
case ASSISTANT:
return new AssistantEmployee(r);
case TEACHING_ASSOCIATE:
return new TeachingAssociateEmploye(r);
case NON_TEACHING_STAFF:
return new NonTeachingTeachingEmploye(r);
default:
throw new InvalidEmployeeType(r.type);
}
}
Reinženjering informacionih sistema 2020/2021
12
Metode/Funkcije (Functions)

Argumenti funkcije:
• Idealan broj argumenata koje funkcija treba da ima je nula

• Jedan argument je malo lošiji izbor

• Dva argumenta još malo lošiji

• Tri argumenta su već loš izbor

• Četiri i više argumenta zahtevaju posebna opravdanja

Razlozi:
• Otežano razumevanje koda

• Otežano pisanje testova

Reinženjering informacionih sistema 2020/2021


13
Metode/Funkcije (Functions)

Ulazni i povratni argumenti:

• public boolean isAreaClosed(Shape s)

• public void trimExtraSpaces(String s)

Reinženjering informacionih sistema 2020/2021


14
Metode/Funkcije (Functions)

Ulazni i povratni argumenti:

public boolean isAreaClosed(Shape s) – povratni tip podatka je boolean

public void trimExtraSpaces(String s) - povratni tip podatka je String nad kojim je vršena operacija

Dva najčešća razloga za prosleđivanje jednog argumenta metodi:


• postavljenje pitanje o argumentu
• vršenje operacija nad argumentom

Reinženjering informacionih sistema 2020/2021


15
Metode/Funkcije (Functions)

Vršenje operacija nad argumentom


- public void trimExtraSpaces(String s)

- appendFooter(s)

Da li je s ulazni ili povratni argument?

Reinženjering informacionih sistema 2020/2021


16
Metode/Funkcije (Functions)

Vršenje operacija nad argumentom


- public void trimExtraSpaces(String s)

- appendFooter(s);

Da li je s ulazni ili povratni argument?

public void appendFooter(StringBuffer report)

Reinženjering informacionih sistema 2020/2021


17
Metode/Funkcije (Functions)

Vršenje operacija nad argumentom


- public void trimExtraSpaces(String s)

- appendFooter(s);

Da li je s ulazni ili povratni argument?

• public void appendFooter(StringBuffer report)

Generalno, bilo bi mnogo bolje kada bi se this koristilo kao povratni argument

• report.appendFooter();

Reinženjering informacionih sistema 2020/2021


18
Metode/Funkcije (Functions)

Korišćenje više argumenata je nekada sasvim opravdano:


• public Point(int x, int y)
• public Point(int x, int y, int z)

Ukoliko postoji potreba za više argumenata, postoji mogućnost da se neki od argumenata smeste u
objekat:
• public Circle(int x, int y, int radius)
• public Circle(Point p, int radius)

Nazivi argumenata
• write(s)
• write(status)

Reinženjering informacionih sistema 2020/2021


19
Metode/Funkcije (Functions) – Primer 4

public class UserValidator {


private Cryptographer cryptographer;

public boolean checkPassword(String userName, String password) {


User user = UserGateway.findByName(userName);
if (user != User.NULL) {
String codedPhrase = user.getPhraseEncodedByPassword();
String phrase = cryptographer.decrypt(codedPhrase, password);
if ("Valid Password".equals(phrase)) {
Session.initialize();
return true;
}
}
return false;
}*

* Robert C. Martin - Clean Code: A Handbook of Agile Software Craftsmanship

Reinženjering informacionih sistema 2020/2021


20
Metode/Funkcije (Functions) – Primer 4

public class UserValidator {


private Cryptographer cryptographer;

public boolean checkPassword(String userName, String password) {


User user = UserGateway.findByName(userName);
if (user != User.NULL) {
String codedPhrase = user.getPhraseEncodedByPassword();
String phrase = cryptographer.decrypt(codedPhrase, password);
if ("Valid Password".equals(phrase)) {
Session.initialize();
return true;
}
- Skrivene funkcionalnosti
}
- Radi više stvari od jedne
return false;
}*

* Robert C. Martin - Clean Code: A Handbook of Agile Software Craftsmanship

Reinženjering informacionih sistema 2020/2021


21
Metode/Funkcije (Functions)

Metode treba da rade nešto ili da odgovaraju na neko pitanje, ne treba da rade i jedno i drugo.

public boolean set(String attribute, String value);

Postavlja vrednost attribute na value i vraća true ukoliko atribut sa vrednošću attribute postoji, a false
ukoliko ne postoji.

To nam omogućava da pravimo:

if(set(“username”,“testuser”))

* Robert C. Martin - Clean Code: A Handbook of Agile Software Craftsmanship

Reinženjering informacionih sistema 2020/2021


22
Metode/Funkcije (Functions)

try/catch blokovi

• premestiti telo try/catch blokova u posebne metode

• ukoliko metoda treba da ima try/catch blok neka počne sa try i ne bi trebalo da ima ništa nakon
catch/final

Reinženjering informacionih sistema 2020/2021


23
Metode/Funkcije (Functions) – Primer 5

try/catch blokovi

public void delete(Page page) {


try {
deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey());
}
catch (Exception e) {
logger.log(e.getMessage());
}

* Robert C. Martin - Clean Code: A Handbook of Agile Software Craftsmanship

Reinženjering informacionih sistema 2020/2021


24
Metode/Funkcije (Functions) – Primer 5

try/catch blokovi

public void delete(Page page) {


try {
deletePageAndAllReferences(page);
}
catch (Exception e) {
logError(e);
}
}

private void deletePageAndAllReferences(Page page) throws Exception {


deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey());
}

private void logError(Exception e) {


logger.log(e.getMessage());
* Robert C. Martin - Clean Code: A Handbook of Agile Software Craftsmanship
}

Reinženjering informacionih sistema 2020/2021


25
Metode/Funkcije (Functions)

Kako poštovati pravila za metode?

• napisaćete metode sa pogrešnim nazivima,


• napisaćete metode sa velikim brojem argumenata,
• napisaćete metode sa ugnježdenim strukturama,
• imaćete mnogo dupliranog koda, ali

• pre nego što komitujete kod koji ste napisali, uradićete refaktoring/reinženjering, učinićete ga
čistim/čistijim, nastaće nove klase, nove metode, i taj proces ne bi trebalo da bude „strašan“, jer
imati testove koji će vam pomoći u ovom zadatku.

Pitanja?

Reinženjering informacionih sistema 2020/2021


26
Komentari (Comments)

Reinženjering informacionih sistema 2020/2021


27
Komentari (Comments)

package shapes;

public class Point extends Shape {


private int x; //x koordinata tacke
private int y; //y koordinata tacke

//prazan konstruktor
public Point() {
}

//konstruktor koji kreira tačku sa koordinatama koje su proleđene kao argumenti


public Point(int x, int y) {
this.x = x;
this.y = y;
}

Reinženjering informacionih sistema 2020/2021


28
Komentari (Comments)

//konstruktor koji kreira tacku sa koordinatama koje su proledjene kao argumenti


public Point(int x, int y) {
this.x = x;
this.y = y;
}

//konstruktor koji kreira tacku sa koordinatama i bojom koje su prosledjene kao argumenti
public Point(int x, int y, Color color) {
this(x, y);
setColor(color);
}

Reinženjering informacionih sistema 2020/2021


29
Komentari (Comments)

//metoda koja vraća vrednost x koordinate


public int getX() {
return x;
}

//metoda koja vraća vrednost y koordinate


public int getY() {
return y;
}

//metoda koja postavlja vrednost x koordinate na vrednost prosledjenog argumenta


public void setX(int x) {
this.x = x;
}

Reinženjering informacionih sistema 2020/2021


30
Komentari (Comments)

//metoda koja postavlja vrednost y koordinate na vrednost prosledjenog argumenta


public void setY(int y) {
this.y = y;
}

//metoda koja pomera tacku na koordinate prosledjena kao argumenti


public void moveTo(int x, int y) {
setX(x);
setY(y);
}
}

Reinženjering informacionih sistema 2020/2021


31
Komentari (Comments)

• Mogu da pomognu

• Mogu da zaguše kod

• Mogu da budu netačni/zbunjujući

• Sa aspekta CleanCode-a predstavljaju neophodno zlo

Reinženjering informacionih sistema 2020/2021


32
Komentari (Comments)

• Mogu da pomognu

public void testCompareTo() throws Exception {


WikiPagePath a = PathParser.parse("PageA");
WikiPagePath ab = PathParser.parse("PageA.PageB");
WikiPagePath b = PathParser.parse("PageB");
WikiPagePath aa = PathParser.parse("PageA.PageA");
WikiPagePath bb = PathParser.parse("PageB.PageB");
WikiPagePath ba = PathParser.parse("PageB.PageA");

assertTrue(a.compareTo(a) == 0); // a == a
assertTrue(a.compareTo(b) != 0); // a != b
assertTrue(ab.compareTo(ab) == 0); // ab == ab
assertTrue(a.compareTo(b) == -1); // a < b
assertTrue(aa.compareTo(ab) == -1); // aa < ab
assertTrue(ba.compareTo(bb) == -1); // ba < bb
assertTrue(b.compareTo(a) == 1); // b > a
assertTrue(ab.compareTo(aa) == 1); // ab > aa
assertTrue(bb.compareTo(ba) == 1); // bb > ba
}*

* Robert C. Martin - Clean Code: A Handbook of Agile Software Craftsmanship

Reinženjering informacionih sistema 2020/2021


33
Komentari (Comments)

• Mogu da pomognu

//checks is student has required average grade to enroll into phd studies
if(student.getAverageGrade()>AVERAGE_GRADE_REQUIREMENT)

Reinženjering informacionih sistema 2020/2021


34
Komentari (Comments)

• Mogu da budu netačni/zbunjujući


o Komentare je potrebno održavati
▪ Kod je promenjen, a komentar je ostao kao pre promene
▪ Komentar ne odgovara onome što metoda radi

Reinženjering informacionih sistema 2020/2021


35
Komentari (Comments)

Sa aspekta Clean Code-a predstavljaju neophodno zlo


• Kada god je to moguće, šta kod radi treba da bude jasno iz naziva metoda i varijabli

Šta ne bi trebalo da radite:


- da koristite komentare kako bi pratili verzije datoteke (VCS – Version Control System)
- da koristite komentare da vodite evidenciju o tome koje poslednji menjao datoteku (VCS)
- da pišete komentare samo zato što vam je neko rekao da to treba da radite
- da komentarišete delove koda
- iako je sasvim normalno da tokom rada zakomentarišete neku liniju ili metodu,
zakomentarisan kod ne bi trebalo da se nađe u vašem komitu

//Copyright (C) 2002 by ITGuys, All rights reserved

Sa stranice ISP početka 2000.-tih


//Do not copy this code without permission or I’ll cut your little fingers off

Reinženjering informacionih sistema 2020/2021


36
Formatiranje (Formatting)

Vertikalno formatiranje
• Koliko linija koda treba da bude u jednoj klasi?
o zavisi od toga šta klasa rad
▪ najčešće ipak zavisi od toga kako je kod pisan
▪ poželjno je da klase imaju što manji broj linija

* Robert C. Martin - Clean Code: A Handbook of Agile Software Craftsmanship

Reinženjering informacionih sistema 2020/2021


37
Formatiranje (Formatting)

public class Point extends Shape { public class Point extends Shape {
private int x; private int x;
private int y; private int y;
public Point(int x, y, Color color) {
public Point(int x, int y, Color color) { this.x = x;
this.x = x; this.y = y;
this.y = y; setColor(color);
setColor(color); }
} public void moveTo(int x, int y) {
this.x = x;
public void moveTo(int x, int y) { this.y = y;
this.x = x; }
this.y = y;
} }

Reinženjering informacionih sistema 2020/2021


38
Formatiranje (Formatting)

public class Point extends Shape { public class Point extends Shape {
private int x; private int x;
private int y; private int y;

public Point(int x, int y, Color color) {


this.x = x; public Point(int x, int y, Color color) {
this.y = y; this.x = x;
setColor(color);
} this.y = y;
setColor(color);
public void moveTo(int x, int y) { }
this.x = x;
this.y = y; public void moveTo(int x, int y) {
} this.x = x;
this.y = y;
}

Reinženjering informacionih sistema 2020/2021 }


39
Formatiranje (Formatting)

Deklarisanje varijabli

• Varijable treba da budu deklarisane što je moguće bliže kodu u kojem će se koristiti
• Varijable koje se koriste u iteracijama, treba da budu deklarisane unutar iteracije
• Varijable instance treba da budu deklarisane na početku klase

Reinženjering informacionih sistema 2020/2021


40
Formatiranje (Formatting)

Point druga = new Point();


public boolean equals(Object obj) {

if (obj instanceof Point) {
public boolean equals(Object obj) {
Point druga = (Point)obj;
if (obj instanceof Point) {
if (getColor().equals(druga.getColor()) &&
druga = (Point)obj;
x==druga.getX() &&
if (getColor().equals(druga.getColor()) &&
y==druga.getY())
x==druga.getX() &&
return true;
y==druga.getY())
else
return true;
return false;
else
}
return false;
else
}
return false;
else
}
return false;
}

Reinženjering informacionih sistema 2020/2021


41
Formatiranje (Formatting)

Vertikalno formatiranje

• Metode između kojih postoji zavisnost, treba da budu blizu jedna druge u vertikalnom
formatiranju, naravno, onoliko koliko je to moguće.

• Metode koje pripadaju istim logičkim segmentima, treba da budu vertikalno bliske.

Reinženjering informacionih sistema 2020/2021


42
Formatiranje (Formatting)

public moveTo(int x, int y,) { public moveTo(int x, int y,) {


this.x = x; this.x = x;
this.y = y; this.y = y;
} }

public void moveBy(int x, int y) { public boolean contains(int x, int y) {


moveTo(this.x+x, this.y+y); Point kliknuta = new Point(x, y);
} if (distance(kliknuta)<=3)
return true;
public boolean contains(int x, int y) { return false;
Point kliknuta = new Point(x, y); }
if (distance(kliknuta)<=3)
return true; public void moveBy(int x, int y) {
return false; moveTo(this.x+x, this.y+y);
} }

Reinženjering informacionih sistema 2020/2021


43
Formatiranje (Formatting)

public int getX() { public int getX() {


return x; return x;
} }

public int getY() { public boolean contains(int x, int y) {


return y; Point kliknuta = new Point(x, y);
} if (distance(kliknuta)<=3)
return true;
public void setX(int x) { return false;
this.x = x; }
}
public int getY() {
public void setY(int y) { return y;
this.y = y; }
}

Reinženjering informacionih sistema 2020/2021


44
Formatiranje (Formatting) – Primer 6

@Override
public void draw(Graphics g) {
g.setColor(getColor());
g.drawOval(this.getCenter().getX() - this.radius, getCenter().getY() - getRadius(),
this.getRadius() * 2, this.getRadius() * 2);

fill(g);
if (isSelected()) {
g.setColor(Color.BLUE);
g.drawRect(getCenter().getX() - 3, getCenter().getY() - 3, 6, 6);
g.drawRect(getCenter().getX() + getRadius() - 3, getCenter().getY() - 3, 6, 6);
g.drawRect(getCenter().getX() - getRadius() - 3, getCenter().getY() - 3, 6, 6);
g.drawRect(getCenter().getX() - 3, getCenter().getY() + getRadius() - 3, 6, 6);
g.drawRect(getCenter().getX() - 3, getCenter().getY() - getRadius() - 3, 6, 6);
g.setColor(Color.BLACK);
}
}

Reinženjering informacionih sistema 2020/2021


45
Formatiranje (Formatting) – Primer 6

public boolean contains(Point p) {


return center.distance(p.getX(), p.getY()) <= radius;
}

public Point getCenter() {


return center;
}

public void setCenter(Point center) {


this.center = center;
}

public int getRadius() {


return radius;
}

Reinženjering informacionih sistema 2020/2021


46
Formatiranje (Formatting) – Primer 6

public void setRadius(int radius) throws Exception {


if (radius >= 0)
this.radius = radius;
else
throw new Exception();
}

public String toString() {


return "Circle: " + "Center= (" + center.getX() + "," + center.getY() + "), " + "Radius=" +
radius + ", " + "OuterColor=" + Integer.toString(getColor().getRGB()) + ", " +
"InnerColor=“ + Integer.toString(getInsideColor().getRGB());

@Override
public void moveBy(int byX, int byY) {
center.moveBy(byX, byY);
}

Reinženjering informacionih sistema 2020/2021


47
Formatiranje (Formatting) – Primer 6

@Override
public int compareTo(Object o) {
if (o instanceof Circle) {
return (this.radius - ((Circle) o).radius);
}
return 0;
}

@Override
public void fill(Graphics g) {
g.setColor(getInsideColor());
g.fillOval(this.getCenter().getX() + 1 - this.radius, getCenter().getY() + 1 - getRadius(),
(this.getRadius() - 1) * 2, (this.getRadius() - 1) * 2);
}

Reinženjering informacionih sistema 2020/2021


48
Formatiranje (Formatting) – Primer 6

@Override public void setRadius(int radius) throws Exception {…}


public void draw(Graphics g) {
… public String toString() {…}
fill(g);
if (isSelected()) { @Override
… public void moveBy(int byX, int byY) {…}
}
} @Override
public int compareTo(Object o) {…}
public boolean contains(Point p) {…}
@Override
public Point getCenter() {…} public void fill(Graphics g) {…}

public void setCenter(Point center) {…}

public int getRadius() {…}

Reinženjering informacionih sistema 2020/2021


49
Formatiranje (Formatting)


@Override
public void draw(Graphics g) {

fill(g);
if (isSelected()) {
drawSelection(g);
}
}

public void fill(Graphics g) {…}

public void drawSelection(Graphics g) {…}


Reinženjering informacionih sistema 2020/2021


50
Formatiranje (Formatting)

Horizontalno formatiranje

* Robert C. Martin - Clean Code: A Handbook of Agile Software Craftsmanship

Reinženjering informacionih sistema 2020/2021


51
Formatiranje (Formatting)

Horizontalno formatiranje

• razmak (space) oko operatora dodele =, =+…


• „nazubljivanje“ koda…
• dogovor oko pravila kada se radi u timu

Izbegavati
• pisanje „kratkih“ metoda u jednoj liniji

public void setX(int x){ this.x =x;}

public void setX(int x){


this.x = x;
}

Reinženjering informacionih sistema 2020/2021


52
Formatiranje (Formatting)

public class CodeAnalyzer implements JavaFileAnalysis {


private int lineCount;
private int maxLineWidth;
private int widestLineNumber;
private LineWidthHistogram lineWidthHistogram;
private int totalChars;

public CodeAnalyzer() {
lineWidthHistogram = new LineWidthHistogram();
}

public static List<File> findJavaFiles(File parentDirectory) {


List<File> files = new ArrayList<File>();
findJavaFiles(parentDirectory, files);
return files;
}
* Robert C. Martin - Clean Code: A Handbook of Agile Software Craftsmanship

Reinženjering informacionih sistema 2020/2021


53
Formatiranje (Formatting)

private static void findJavaFiles(File parentDirectory, List<File> files) {


for (File file : parentDirectory.listFiles()) {
if (file.getName().endsWith(".java"))
files.add(file);
else if (file.isDirectory())
findJavaFiles(file, files);
}
}

public void analyzeFile(File javaFile) throws Exception {


BufferedReader br = new BufferedReader(new FileReader(javaFile));
String line;
while ((line = br.readLine()) != null)
measureLine(line);
}

* Robert C. Martin - Clean Code: A Handbook of Agile Software Craftsmanship

Reinženjering informacionih sistema 2020/2021


54
Formatiranje (Formatting)

private void measureLine(String line) {


lineCount++;
int lineSize = line.length();
totalChars += lineSize;
lineWidthHistogram.addLine(lineSize, lineCount);
recordWidestLine(lineSize);
}

private void recordWidestLine(int lineSize) {


if (lineSize > maxLineWidth) {
maxLineWidth = lineSize;
widestLineNumber = lineCount;
}
}

public int getLineCount() {


return lineCount; * Robert C. Martin - Clean Code: A Handbook of Agile Software Craftsmanship
}

Reinženjering informacionih sistema 2020/2021


55
Formatiranje (Formatting)

public int getMaxLineWidth() {


return maxLineWidth;
}

public int getWidestLineNumber() {


return widestLineNumber;
}

public LineWidthHistogram getLineWidthHistogram() {


return lineWidthHistogram;
}

public double getMeanLineWidth() {


return (double)totalChars/lineCount;
}

* Robert C. Martin - Clean Code: A Handbook of Agile Software Craftsmanship

Reinženjering informacionih sistema 2020/2021


56
Formatiranje (Formatting)

public int getMedianLineWidth() {


Integer[] sortedWidths = getSortedWidths();
int cumulativeLineCount = 0;
for (int width : sortedWidths) {
cumulativeLineCount += lineCountForWidth(width);
if (cumulativeLineCount > lineCount/2)
return width;
}
throw new Error("Cannot get here");
}

private int lineCountForWidth(int width) {


return lineWidthHistogram.getLinesforWidth(width).size();
}

* Robert C. Martin - Clean Code: A Handbook of Agile Software Craftsmanship

Reinženjering informacionih sistema 2020/2021


57
Formatiranje (Formatting)

private Integer[] getSortedWidths() {


Set<Integer> widths = lineWidthHistogram.getWidths();
Integer[] sortedWidths = (widths.toArray(new Integer[0]));
Arrays.sort(sortedWidths);
return sortedWidths;
}
}

* Robert C. Martin - Clean Code: A Handbook of Agile Software Craftsmanship

Reinženjering informacionih sistema 2020/2021


58
Formatiranje (Formatting)

Pitanja?

Reinženjering informacionih sistema 2020/2021

You might also like