You are on page 1of 10

Refaktoring Lazar Nikolic 548/08

Pomocu extract method smo smanjili konstruktor i napravili novi metod paint() koji ce nam sluziti za bojenje background-a. Promenljivu int height smo izbacili jer je nepotrebna i umesto nje smo stavili this.getHeight() koja ima istu vrednost.
import java.awt.*; import javax.swing.*; public class Background extends JLayeredPane { int lineDistance; public Background(int width, int height, int lineDistance) { super(); setPreferredSize(new Dimension(width, height)); this.lineDistance = lineDistance; paint(); } public void paint(){ setOpaque(true); setBackground(Color.yellow); setForeground(Color.orange); } public void paintComponent(Graphics g) { super.paintComponent(g); //int height = getHeight(); for (int i = 0; i < this.getWidth(); i+= lineDistance) g.drawLine(i, 0, i, this.getHeight()); } } Izbacujemo import javax.swing.border.* jer se nigde ne koristi. Menjamo komentare da bi bili razumljiviji (Comments bad smell). Premestamo promenljive lastx i lasty jer je citljivije kada se nalaze na pocetku klase.

import java.awt.*; import java.awt.event.*; import javax.swing.*; //import javax.swing.border.*; public class Card extends JPanel { static int cards = 0; final static int scale = 34; final static int height = 3 * scale; final static int width = 5 * scale; // card size factor // Card format // 3x5

final static int rollover = 12; // New cards go in different position final static int offset = scale;// How far apart to put new cards

private int lastx, lasty; JTextField title; JTextArea body; JLabel costLabel; static int cost; public Card() { this("(Untitled)", ""); } public Card(Card from) { this(from.title.getText(), from.body.getText()); }

Konstruktor klase je prevelik (Long method smell) iz njega izbacujemo visak koda u nove metode. FocusAdapter se javlja dva puta u konstruktoru (Duplicate bad smell), izbacujemo ga iz konstruktora i pravimo novu klasu NewFocusAdapter koju cemo pozivati u konstruktoru.

private Card(String titleText, String bodyText) { super(); setBorder(BorderFactory.createLineBorder(Color.blue, 6)); cards++; setLayout(new BorderLayout()); JPanel top = new JPanel(new BorderLayout()); title = new JTextField(titleText); title.setBackground(Color.pink); title.addFocusListener(new NewFocusAdapter()); top.add(title, "Center"); costLabel = new JLabel(" ? "); cost = 0; top.add(costLabel, "East"); add(top, "North"); body = new JTextArea(bodyText); body.setLineWrap(true); body.setWrapStyleWord(true); body.setBackground(Color.pink); body.addFocusListener(new NewFocusAdapter()); add(body, "Center"); setLocation( (cards % rollover) * offset, (cards % rollover) * offset); setSize(width, height);

// Turn on mouse events so we can detect being dragged enableEvents( AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK); } private class NewFocusAdapter extends FocusAdapter { public void focusGained(FocusEvent e) { moveToFront(); } } private void moveToFront() { JLayeredPane background = (JLayeredPane) this.getParent(); background.moveToFront(this); }

public void processMouseEvent(MouseEvent e) { if (e.getID() == MouseEvent.MOUSE_PRESSED) { lastx = e.getX(); lasty = e.getY(); moveToFront(); } else super.processMouseEvent(e); } public void processMouseMotionEvent(MouseEvent e) { if (e.getID() == MouseEvent.MOUSE_DRAGGED) { Point here = getLocation(); setLocation((int) (here.getX() + e.getX() - lastx), (int) (here.getY() + e.getY() - lasty)); } else super.processMouseMotionEvent(e); }

Metode rotateCost() i cost()(kojem menjamo ime u getCost()) prebacujemo u posebnu novu klasu Cost(u nju cemo ubaciti i costove iz klase Table). public String title() { return title.getText(); } public boolean needsSplit() { return costLabel.getText().equals(" >3 "); } public boolean needsEstimate()

{ return costLabel.getText().equals(" ? "); } } Izbacujemo import javax.swing.event.* i import javax.swing.text.JtextComponent jer se nigde ne koriste. Izbacujemo int budget i JtabbedPane tabs jer se nigde ne koriste(Speculative Generality bad smell). Konstruktor klase je preveliki. Iz njega izbacujemo neke stvari. Za svaki ContainerListener pravimo novu klasu koju pozivamo konstruktoru klase Table. Za svaki ActionListener pravimo novu klasu koju pozivamo u klasi Table. Ovakav kod je dosta pregledniji.

import java.awt.*; import java.awt.event.*; import javax.swing.*; //import javax.swing.event.*; //import javax.swing.text.JTextComponent;

public class Table extends JFrame { public static void main(String[] args) { new Table(); } public static JComponent body; private Card selection; public static JLabel summary; public static int velocity = 1; Cost cost = new Cost(); // int budget = 4; // JTabbedPane tabs;

public Table() { super("Planning Game Simulation"); JComponent buttons = makeButtons(); this.getContentPane().add(buttons, "West"); body = new Background(1000, 1000, 190); body.addContainerListener(new NewContainerListener()); // Listen for container changes so we know when // to update selection highlight JScrollPane scroll = new JScrollPane(body); scroll.setPreferredSize(new Dimension(100, 100)); this.getContentPane().add(scroll, "Center");

summary = new JLabel("", SwingConstants.CENTER); summary.setText(cost.summary()); this.getContentPane().add(summary, "South"); this.pack(); this.setSize(800, 600); this.show(); } class NewContainerListener implements ContainerListener { public void componentAdded(ContainerEvent e) { resetSelection(); } public void componentRemoved(ContainerEvent e) { resetSelection(); } private void resetSelection() { if (selection != null) selection.setBorder(BorderFactory.createLineBorder(Color.blue, 6)); if (body.getComponentCount() == 0) { selection = null; } else { selection = (Card) body.getComponent(0); selection.setBorder(BorderFactory.createLineBorder(Color.red, 6)); } } } private JComponent makeButtons() { JPanel panel = new JPanel(new GridLayout(0, 1)); panel.add(new JLabel("Customer")); makeCustomerButtons(panel); panel.add(new JLabel(" ")); panel.add(new JLabel("Programmer")); makeProgrammerButtons(panel); JPanel outer = new JPanel(new BorderLayout()); outer.add(panel, "North"); outer.add(new JLabel(""), "Center"); return outer; } private void makeCustomerButtons(JPanel panel) { JButton button;

button = new JButton("New"); panel.add(button); button.addActionListener(new NewActionListener());

button = new JButton("Split"); panel.add(button); button.addActionListener(new SplitActionListener()); button = new JButton("Delete"); panel.add(button); button.addActionListener(new DeleteActionListener());

button = new JButton("Plan"); panel.add(button); button.addActionListener(new PlanActionListener()); } class NewActionListener implements ActionListener{ public void actionPerformed(ActionEvent e) { Card card = new Card(); body.add(card, 0); selection = card; cost.updateCost(); repaint(); } } class SplitActionListener implements ActionListener{ public void actionPerformed(ActionEvent e) { if (selection == null) return; Card card = new Card(selection); body.add(card, 0); selection = card; cost.updateCost(); body.repaint(); } } class DeleteActionListener implements ActionListener{ public void actionPerformed(ActionEvent e) { if (body.getComponentCount() == 0) return; body.remove(0); selection = null; if (body.getComponentCount() != 0) selection = (Card) body.getComponent(0); cost.updateCost(); body.repaint(); }

} class PlanActionListener implements ActionListener{ public void actionPerformed(ActionEvent e) { StringBuffer report = new StringBuffer(); // Check for cards that need est. or splitting for (int i = 0; i < body.getComponentCount(); i++) { Card card = (Card) body.getComponent(i); if (card.needsEstimate()) report.append( "Needs estimate: " + card.title() + "\n"); else if (card.needsSplit()) report.append( "Needs to be split: " + card.title() + "\n"); } if (report.length() == 0) JOptionPane.showMessageDialog( body, "Plan OK; no cards need estimates or splitting", "Issues in plan", JOptionPane.OK_OPTION); else JOptionPane.showMessageDialog( body, report.toString(), "Issues in plan", JOptionPane.OK_OPTION); } }

private void makeProgrammerButtons(JPanel panel) { JButton button; button = new JButton("Cost"); panel.add(button); button.addActionListener(new CostActionListener()); button = new JButton("Velocity"); panel.add(button); button.addActionListener(new VelocityActionListener()); } class CostActionListener implements ActionListener{ public void actionPerformed(ActionEvent e) { if (selection == null) return; cost.rotateCost(selection); cost.updateCost(); } } class VelocityActionListener implements ActionListener{ public void actionPerformed(ActionEvent e) {

velocity++; if (velocity >= 10) velocity = 1; cost.updateCost(); } }

} U klasi Table postoji i Inapropriate intimacy bad smell jer se klasa Table

oslanja na klasu Background Klasa Table je prevelika (Large class bad smell). Iz nje u novu klasu Cost prebacujemo metode updateCost(), cost(), setSummary(). Brisemo klasu Summary jer ona ostaje prazna i nista ne radi (Lazy class bad smell).
public class Cost { static int cost; public void updateCost() { Table.summary.setText(summary()); } public String summary() { StringBuffer result = new StringBuffer(); result.append( "Est. Velocity (points/iteration): " + Table.velocity + ". "); result.append("Total cost (points): " + cost() + ". "); result.append("#Cards: " + Table.body.getComponentCount() + ". "); result.append( "Est. #iterations: " + (cost() + Table.velocity - 1)/ Table.velocity + ". "); return result.toString(); } // Total cost of the set of cards private int cost() { int total = 0; for (int i = 0; i < Table.body.getComponentCount(); i++) { Card card = (Card) Table.body.getComponent(i); total += getCost(); } return total; }

public void rotateCost(Card card) { String label = card.costLabel.getText(); if (label.equals(" ? ")) { card.costLabel.setText(" 1 "); cost = 1; } else if (label.equals(" 1 ")) { card.costLabel.setText(" 2 "); cost = 2; } else if (label.equals(" 2 ")) { card.costLabel.setText(" 3 "); cost = 3; } else if (label.equals(" 3 ")) { card.costLabel.setText(" >3 "); cost = 0; } else if (label.equals(" >3 ")) { card.costLabel.setText(" ? "); cost = 0; } else { // shouldn't happen card.costLabel.setText(" ? "); cost = 0; } } public static int getCost() { return cost; } }

Postoji mogucnost Switch statement bad smell, ali switch ne radi sa stringovima pa nisam uspeo da ga implementiram.

You might also like