+ All Categories
Home > Documents > 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object...

1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object...

Date post: 22-Dec-2015
Category:
View: 214 times
Download: 0 times
Share this document with a friend
42
1 Style-Oriented Approaches
Transcript
Page 1: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

1

Style-Oriented Approaches

Page 2: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

2

<spartan.programming>

Page 3: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

3

Before Spartanization (1/2) public int compare(Object o1, Object o2) {

if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName()); } if (!(o2 instanceof Cookie)) { throw new ClassCastException(o2.getClass().getName()); } Cookie c1 = (Cookie) o1; Cookie c2 = (Cookie) o2;

// Continues on next slide...

Page 4: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

4

Before Spartanization (2/2) if (c1.getPath() == null && c2.getPath() == null) { return 0; } else if (c1.getPath() == null) { // null is assumed to be "/" if (c2.getPath().equals(CookieSpec.PATH_DELIM)) { return 0; } else { return -1; } } else if (c2.getPath() == null) { // null is assumed to be "/" if (c1.getPath().equals(CookieSpec.PATH_DELIM)) { return 0; } else { return 1; } } else { return c1.getPath().compareTo(c2.getPath()); } }

Page 5: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

5

After Spartanization

public int compare(Object o1, Object o2) {

String p1 = ((Cookie) o1).getPath();

String p2 = ((Cookie) o2).getPath();

if (p1 == null && p2 == null)

return 0;

if (p2 == null)

return p1.equals(CookieSpec.PATH_DELIM) ? 0 : 1;

if (p1 == null)

return p2.equals(CookieSpec.PATH_DELIM) ? 0 : -1;

return p1.compareTo(p2);

}

Page 6: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

6

Approach: Spartan Programming• Philosophy:

• Bugs are due to inability to see all the code at once• Static simplicity => Dynamic simplicity• Methods are the groundwork of programs• 7 +/- 2 Rule

Values• Understandability• Loose Coupling• Strong Cohesion• Continuity• Compos-ability

• Principles• Eliminate duplications• Minimization of: #lines, #columns, #tokens, #characters, #variables, #branches

• Practices• Frugal use of Variables• Small Interfaces• Minimal use of Control• Careful use of Screen Space

“Minimalism isn't always the right choice, but it's rarely the wrong choice”

Page 7: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

7

Frugal use of Variables

Minimize:• Number• Scope• Accessibility • Variability • Name length• Life time• The use of arrays

Page 8: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

8

Small Interfaces

• Minimize the number of parameters• Minimize side-affecting parameters

• Parameter kind priority• Input parameters• Output parameters• Input-output parameters• Pass by name

Page 9: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

9

Minimal use of Control

• Avoid conditionals • Ternary operator (cond ? a : b)• Polymorphic messages• Encapsulation of logic inside classes

• Compact blocks• Early exits• Short branch first• Avoid deep nesting

• Avoid looping - functional style

Page 10: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

10

Careful use of Screen Space

• K&R Style• Eliminate unnecessary parenthesis/braces• Refactor code into helper methods

• Shortens the primary method

• “Hand rule”: Width, Height

Page 11: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

11

A Recipe for an Ideal Class

•Prefixed with a 1-2 lines javadoc comment•Less than 4 instance fields – preferably final•Priority: no accessors, getter only, getter + setter•Final fields can be public•3-4 public methods•Less than 100 LOC•Methods are less than 10 lines•enable(), disable() rather than setEnabled(boolean b)•Must override toString() •All fields initialized by constructor•Short variable names: $, m, o, etc.•Order: Fields, constructors, toString(), equals(), hash(), public

methods, private methods

•Most warnings turned on (in particular, “un-used XXX”)

Page 12: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

12

An Even Stricter Approach

•One level of indentation per method•The “else” keyword is forbidden•Wrap all primitives and strings•One dot per line•Don’t abbreviate names•class < 50 LOC, package < 10 classes•Less than three instance fields•A collection field precludes other fields•No getters/setters

Jeff Bay, “Object Calisthenics”The ThoughtWorks Anthology

Page 13: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

13

</spartan.programming>

Page 14: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

14

<cohesion>

Page 15: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

15

Low Cohesion

// class DatePanel

public void processKey(KeyEvent e) { ... if ((keycode == KeyEvent.VK_LEFT) || (keycode == 226))

update(Calendar.DAY_OF_YEAR, -1); if ((keycode == KeyEvent.VK_RIGHT) || (keycode == 227)) update(Calendar.DAY_OF_YEAR, 1); if ((keycode == KeyEvent.VK_PAGE_UP)) update(Calendar.MONTH, -1); ... if ((!e.isControlDown()) && (!e.isShiftDown())) { model.clearSelection(); if (e.isShiftDown()) model.addSelection(model.getDate()); ...

Page 16: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

16

High Cohesion // class DatePanel public void processKey(KeyEvent e) {

boolean changed = updateCalendar(e.getKeyCode()); if (changed) updateModel(e); fireKeyListenerKeyPressed(e); }

private boolean updateCalendar(int keycode) { if ((keycode == KeyEvent.VK_LEFT) || (keycode == 226)) update(Calendar.DAY_OF_YEAR, -1); else if ((keycode == ...) update(...) else return false; return true; }

private void updateModel(KeyEvent e) { if ((!e.isControlDown()) ...

Page 17: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

17

</cohesion>

Page 18: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

18

<coupling>

Page 19: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

19

Coupling w/ ResultSet private List<String> names = new ArrayList<String>();

public void collectNames(ResultSet rs, int n) { for(int i = 0; i < n; ++i) { if(!rs.next()) return; names.add(rs.getString(0));

} }

Page 20: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

20

Coupling w/ Iterator

private List<String> names = new ArrayList<String>();

public void collectNames(Iterator<String> iter, int n) { for(int i = 0; i < n; ++i) { if(!iter.hasNext()) return; names.add(iter.next()); } }

Page 21: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

21

Even Less Coupling

public interface Processor { public void process(String s); }

public void setProcessor(Processor arg) { p = arg; }

private Processor p;

public void collectNames(Iterator<String> iter, int n) { for(int i = 0; i < n; ++i) { if(!iter.hasNext()) return; p.process(iter.next()); } }

// => More Versatility, but less easy to use

Page 22: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

22

</coupling>

Page 23: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

23

<naming>

Page 24: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

24

General• Highly important

• Understandability without delving into details

• Avoid hiding of fields with variables

• A good metaphor may help: Figure, Page

• Classes – Nouns• File• Account• SymbolTable

• Methods – Verbs• open()• withdraw()• lookup()

Page 25: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

25

Types •Nouns: Figure, Account

• Sometimes –er suffix: Formatter, Loader

•Popularity => Simple name• Frequent usage: typing a variable• Frequent usage: superclass

•Communicate similarities & differences• Add a prefix to the superclass

class TextFormatter extends Formatter { ... }

•Avoid “Object” in class names

•Single form for enum typesenum Pet { CAT, DOG }

Page 26: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

26

Interfaces vs .Classes

•Interfaces will usually be a popular type

class ColoredFigure implements Figure { ... }

•-able is a common suffix for interfaces• Denotes a mixin-like protocol unit

•If both interface & concrete class are popular

abstract class AbstractFigure implements IFigure { ... }

class Figure extends AbstractFigure { ... }

Page 27: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

27

Common Naming Schemes

InterfaceSuperclassRoot ClassSub Classes

FigureAbstractFigureDefaultFigure

FigureAbstractFigureConcreteFigure

FigureColoredFigureResizableColoredFigureFixedColoredFigure

IFigureAbstractFigureFigure

ResizableFigureResizableFigure

Page 28: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

28

Methods

•Verbs: paint(), remove()

•boolean setters/getters• isVisible()• setVisible(boolean)• show(), hide() // More explicit

•Getters• getX()• x()

•Setters• setX(int)• x(int)

Page 29: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

29

Variables•result•results•count, n•curr, each•i, j•arg•List<Message> messages•Map<String,String> addressFromName •that•lhs, rhs•iconA, iconB•Event event; Painter painter;•Event e; Painter p;•isEmpty; // Better than: if(!notEmpty) ...

Page 30: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

30

<hungarian.notation>

Page 31: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

31

Hungarian Notation is Bad

•Prefix specifies the type/stroage of the variable

•C• ulDistance = Unsigned Long• bEnabled = Boolean • paulData = Pointer to Array of Unsigned Long• szName = Zero terminated String

•Java• pX = Parameter• fY = Field (sometimes “m” for Member)• sfZ = Static Field

•Considered outdated (or even evil)• Overly verbose• Obviated by: smart IDEs, short methods/classes

Page 32: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

32

Hungarian Notation is Great

•Prefix specifies “pseudo subtype”

•Pseudo subtypes examples:• Integers: Row vs. Column• Integers: Dollars vs. Cents• Strings: text vs. HTML

Page 33: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

33

Is Address HTML-ed?

String str = person.getDetails(“address”);...

String adr = str;

...

record.setField(“location", adr);

...

String address = record.getField(“location"); ...

out.println(“Send to: <i>” + address + “</i>”); // Did we remember to call htmlEncode() ??

Page 34: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

34

Hungarian Notation to the Rescue

Let’s apply this convention

•Strings coming from the user are considered text• Must be stored in variables prefixed with “t”• The same goes for database columns

•htmlEncode() translates a “t” prefix to “h”• Strings returned from htmlEncode() are considered HTML• Must be stored in a variable prefixed with “h”

•Assignments allowed only if prefixes match

Page 35: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

35

Is tAddress HTML-ed? String tStr = person.getDetails(“address”);

...

String tAdr = tStr;

...

record.setField(“tLocation", tAdr);

...

String tAddress = record.getField(“tLocation");

...

out.println(“Send to: <i>” + tAddress + “</i>”); // Clearly, tAddress was not htmlEnocde-d

Page 36: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

36

Rename: tAddress => hAddress String tStr = getOrderDetails(“address”);

...

String tAdr = tStr;

...

record.setField(“tLocation", tAdr);

...

String hAddress = record.getField(“tLocation"); // violation of our convention !!

...

out.println(“Send to: <i>” + hAddress + “</i>”);

Page 37: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

37

Correct Code – All Prefixes Match String tStr = getOrderDetails(“address”);

...

String tAdr = tStr;

...

record.setField(“tLocation", tAdr);

...

String hAddress = htmlEncode(record.getField(“tLocation"));

...

out.println(“Send to: <i>” + hAddress + “</i>”);

Page 38: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

38

</hungarian.notation>

Page 39: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

39

</naming>

Page 40: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

40

Eyetracking

Page 41: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

41

Benefits of Narrow Code

•We don’t read stuff on the right-hand side•Stacktrace•Debugability of if statements•Debugability of return values•Explaining variables

•=> Prefer tall, narrow code• Over short, wide

Page 42: 1 Style-Oriented Approaches. 2 3 Before Spartanization (1/2) public int compare(Object o1, Object o2) { if (!(o1 instanceof Cookie)) { throw new ClassCastException(o1.getClass().getName());

42

Fix it in the language

“For example, I want the next C grammar to define that a space comes between any keyword and an opening parenthesis. "if (foo)" would be legal, but "if(foo)" would not. Not a warning, not optionally checked, but actually forbidden by the language parser. Flat out illegal. Can't compile.

... There is not now, nor will there ever be, a programming style whose benefit

is significantly greater than any of the common styles. Get real. Discovering a style that improves your productivity by more than a few percent over the common styles is about as likely as discovering a new position for sex.”

Ken Arnold, “Style is Substance”www.artima.com


Recommended