QUESTIONS C S 3 5 1 - D e s i g n o f L a r g e P r o g r am s LAST TIME: - Administrivia; hack talk; refactoring TODAY: - More refactoring - DeathBox smackdown: What does the spec mean? - Aspects of Java mastery: interface, program birth HOMEWORK - Review interfaces, e.g., at http://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html &ff or via JPL4 ch 4 - First project out before class Thursday! Will announce to list/webpage THE MYTH OF FINISHED SOFTWARE SOFTWARE ROT: n. Term used to describe the tendency of software that has not been used in a while to lose; such failure may be semi-humorously ascribed to bit rot. More commonly, software rot strikes when a program's assumptions become out of date. If the design was insufficiently robust, this may cause it to fail in mysterious ways. Syn. code rot. See also link rot. RECIPES FOR DISASTER CRAFT - REFACTORING CODE - 'Refactoring' is changing the design of code WITHOUT changing what the code DOES. - (Why on earth would anybody do that?? Wouldn't that be a total waste of time?) - Refactoring Hello World REFACTORING HELLO WORLD What: Evacuate 'public static void main(String[])' of any significant behavior. Why: Only Java _applications_ (as opposed to Java applets, for example) even call 'public static void main(String[])' How: (1) Add a method to the class, called perhaps 'run()' or something, (2) Migrate the behavior in the main to run(), (3) In the main, build an instance of the class and call run() on it AFTER: public class HelloWorld { public void run() { System.out.println("Hello World"); } public static void main(String[] args) { HelloWorld hw = new HelloWorld(); hw.run(); } } -> External behavior completely unchanged by the refactoring (as always) -> Internal structure of code is now more useful, more _evolvable_ -> This is not rocket surgery.. We have these patterns at our fingertips. REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. - What's the idea with this 'interface' stuff?? = An 'interface' is a _set of method signatures_. REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. - What's the idea with this 'interface' stuff?? = An 'interface' is a _set of method signatures_. - AND A SET OF BEHAVIORAL AGREEMENTS INVISIBLE TO THE COMPILER BUT CRUCIAL TO THE PROGRAMMER, SPELLED OUT IN THE INTERFACE JAVADOC! REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. - What's the idea with this 'interface' stuff?? = An 'interface' is a _set of method signatures_. - And that's all*: No method bodies, no 'state'... REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. - What's the idea with this 'interface' stuff?? = An 'interface' is a _set of method signatures_. - And that's all*: No method bodies, no 'state'... Legal or no? public interface Foo { public void woof() { System.out.println("Woof!"); } } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. - What's the idea with this 'interface' stuff?? = An 'interface' is a _set of method signatures_. - And that's all*: No method bodies, no 'state'... Legal or no? public interface Foo { public void woof() { System.out.println("Woof!"); } } Foo.java:1: interface methods cannot have b^ody REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. - What's the idea with this 'interface' stuff?? = An 'interface' is a _set of method signatures_. - And that's all*: No method bodies, no 'state'... Legal or no? public interface Foo { public void woof() { System.out.println("Woof!"); } } Foo.java:1: interface methods cannot have b^ody public interface Foo { public int woof(); public String clank(); } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. - What's the idea with this 'interface' stuff?? = An 'interface' is a _set of method signatures_. - And that's all*: No method bodies, no 'state'... Legal or no? public interface Foo { public void woof() { System.out.println("Woof!"); } } Foo.java:1: interface methods cannot have b^ody public interface Foo { public int woof(); public String clank(); } OK.. REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. - What's the idea with this 'interface' stuff?? = An 'interface' is a _set of method signatures_. - And that's all*: No method bodies, no 'state'... Legal or no? public interface Foo { public void woof() { System.out.println("Woof!"); } } Foo.java:1: interface methods cannot have b^ody public interface Foo { public int woof(); public String clank(); } OK.. public interface Foo { private int woof(); String clank(); } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. - What's the idea with this 'interface' stuff?? = An 'interface' is a _set of method signatures_. - And that's all*: No method bodies, no 'state'... Legal or no? public interface Foo { public void woof() { System.out.println("Woof!"); } } Foo.java:1: interface methods cannot have b^ody public interface Foo { public int woof(); public String clank(); } OK.. public interface Foo { private int woof(); String clank(); } Foo.java:1: modifier private not all^owed here REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. - What's the idea with this 'interface' stuff?? = An 'interface' is a _set of method signatures_. - And that's all*: No method bodies, no 'state'... Legal or no? public interface Foo { public void woof() { System.out.println("Woof!"); } } Foo.java:1: interface methods cannot have b^ody public interface Foo { public int woof(); public String clank(); } OK.. public interface Foo { private int woof(); String clank(); } Foo.java:1: modifier private not all^owed here public interface Foo { public int woof(); public String clank; } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. - What's the idea with this 'interface' stuff?? = An 'interface' is a _set of method signatures_. - And that's all*: No method bodies, no 'state'... Legal or no? public interface Foo { public void woof() { System.out.println("Woof!"); } } Foo.java:1: interface methods cannot have b^ody public interface Foo { public int woof(); public String clank(); } OK.. public interface Foo { private int woof(); String clank(); } Foo.java:1: modifier private not all^owed here public interface Foo { public int woof(); public String clank; } Foo.java:1: = expected ^ REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. - What's the idea with this 'interface' stuff?? = An 'interface' is a _set of method signatures_. - And that's all*: No method bodies, no 'state'... Legal or no? public interface Foo { public void woof() { System.out.println("Woof!"); } } Foo.java:1: interface methods cannot have b^ody public interface Foo { public int woof(); public String clank(); } OK.. public interface Foo { private int woof(); String clank(); } Foo.java:1: modifier private not all^owed here public interface Foo { public int woof(); public String clank; } Foo.java:1: = expected ^ public interface Foo { public int woof(); public String clank="honk?"; } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. - What's the idea with this 'interface' stuff?? = An 'interface' is a _set of method signatures_. - And that's all*: No method bodies, no 'state'... Legal or no? public interface Foo { public void woof() { System.out.println("Woof!"); } } Foo.java:1: interface methods cannot have b^ody public interface Foo { public int woof(); public String clank(); } OK.. public interface Foo { private int woof(); String clank(); } Foo.java:1: modifier private not all^owed here public interface Foo { public int woof(); public String clank; } Foo.java:1: = expected ^ public interface Foo { public int woof(); public String clank="honk?"; } OK..?? MORE ABOUT INTERFACES public interface Foo { public int woof(); public String clank="honk?"; } OK..?? MORE ABOUT INTERFACES public interface Foo { public int woof(); public String clank="honk?"; } OK..?? public interface Foo { public int woof(); public String clank="honk?"; } class Bar { public static void main(String[] args) { Foo f = new Foo(); System.out.println(f.clank); } } MORE ABOUT INTERFACES public interface Foo { public int woof(); public String clank="honk?"; } OK..?? public interface Foo { public int woof(); public String clank="honk?"; } class Bar { public static void main(String[] args) { Foo f = new Foo(); Foo.java:4: Fo^o is abstract; cannot be instantiated System.out.println(f.clank); } } MORE ABOUT INTERFACES public interface Foo { public int woof(); public String clank="honk?"; } OK..?? public interface Foo { public int woof(); public String clank="honk?"; } class Bar { public static void main(String[] args) { Foo f = new Foo(); Foo.java:4: Fo^o is abstract; cannot be instantiated System.out.println(f.clank); } } - interfaces do not describe objects -- they describe _aspects_ of objects. You can't construct an instance of an interface. You can only construct instances of classes that _implement_ an interface.. MORE ABOUT INTERFACES public interface Foo { public int woof(); public String clank="honk?"; } OK..?? public interface Foo { public int woof(); public String clank="honk?"; } class Bar { public static void main(String[] args) { Foo f = new Foo(); Foo.java:4: Fo^o is abstract; cannot be instantiated System.out.println(f.clank); } } - interfaces do not describe objects -- they describe _aspects_ of objects. You can't construct an instance of an interface. You can only construct instances of classes that _implement_ an interface.. public interface Foo { public int woof(); public String clank="honk?"; } class Bar implements Foo { public static void main(String[] args) { Foo f = new Bar(); System.out.println(f.clank); } } MORE ABOUT INTERFACES public interface Foo { public int woof(); public String clank="honk?"; } OK..?? public interface Foo { public int woof(); public String clank="honk?"; } class Bar { public static void main(String[] args) { Foo f = new Foo(); Foo.java:4: Fo^o is abstract; cannot be instantiated System.out.println(f.clank); } } - interfaces do not describe objects -- they describe _aspects_ of objects. You can't construct an instance of an interface. You can only construct instances of classes that _implement_ an interface.. public interface Foo { public int woof(); public String clank="honk?"; } class Bar implements Foo { Foo.java:2: Bar is not abstract and does not override abstract method woof().. public static void main(String[] args) { Foo f = new Bar(); System.out.println(f.clank); } } MORE ABOUT INTERFACES public interface Foo { public int woof(); public String clank="honk?"; } class Bar implements Foo { Foo.java:2: Bar is not abstract and does not override abstract method woof().. public static void main(String[] args) { Foo f = new Bar(); System.out.println(f.clank); } } MORE ABOUT INTERFACES public interface Foo { public int woof(); public String clank="honk?"; } class Bar implements Foo { Foo.java:2: Bar is not abstract and does not override abstract method woof().. public static void main(String[] args) { Foo f = new Bar(); System.out.println(f.clank); } } public interface Foo { public int woof(); public String clank="honk?"; } class Bar implements Foo { public int woof() { return 7; } public static void main(String[] args) { Foo f = new Bar(); System.out.println(f.clank); } } $ javac Foo.java MORE ABOUT INTERFACES public interface Foo { public int woof(); public String clank="honk?"; } class Bar implements Foo { Foo.java:2: Bar is not abstract and does not override abstract method woof().. public static void main(String[] args) { Foo f = new Bar(); System.out.println(f.clank); } } public interface Foo { public int woof(); public String clank="honk?"; } class Bar implements Foo { public int woof() { return 7; } public static void main(String[] args) { Foo f = new Bar(); System.out.println(f.clank); } } $ javac Foo.java $ java Foo MORE ABOUT INTERFACES public interface Foo { public int woof(); public String clank="honk?"; } class Bar implements Foo { Foo.java:2: Bar is not abstract and does not override abstract method woof().. public static void main(String[] args) { Foo f = new Bar(); System.out.println(f.clank); } } public interface Foo { public int woof(); public String clank="honk?"; } class Bar implements Foo { public int woof() { return 7; } public static void main(String[] args) { Foo f = new Bar(); System.out.println(f.clank); } } $ javac Foo.java $ java Foo Exception in thread "main" java.lang.NoSuchMethodError: main $ MORE ABOUT INTERFACES public interface Foo { public int woof(); public String clank="honk?"; } class Bar implements Foo { Foo.java:2: Bar is not abstract and does not override abstract method woof().. public static void main(String[] args) { Foo f = new Bar(); System.out.println(f.clank); } } public interface Foo { public int woof(); public String clank="honk?"; } class Bar implements Foo { public int woof() { return 7; } public static void main(String[] args) { Foo f = new Bar(); System.out.println(f.clank); } } $ javac Foo.java $ java Foo Exception in thread "main" java.lang.NoSuchMethodError: main $ java Bar honk? $ MORE ABOUT INTERFACES public interface Foo { public int woof(); public String clank="honk?"; } class Bar implements Foo { public int woof() { return 7; } public static void main(String[] args) { clank="BONK"; System.out.println(clank); } } MORE ABOUT INTERFACES public interface Foo { public int woof(); public String clank="honk?"; } class Bar implements Foo { public int woof() { return 7; } public static void main(String[] args) { clank="BONK"; ^ Foo.java:5: cannot assign a value to final variable clank System.out.println(clank); } } MORE ABOUT INTERFACES public interface Foo { public int woof(); public String clank="honk?"; } class Bar implements Foo { public int woof() { return 7; } public static void main(String[] args) { clank="BONK"; ^ Foo.java:5: cannot assign a value to final variable clank System.out.println(clank); } } - Interfaces can contain method signatures and field declarations = All interface method declarations are automatically public = All interface field declarations are automatically public static final - So they must be initialized.. MORE ABOUT INTERFACES public interface Foo { public int woof(); public String clank="honk?"; } class Bar implements Foo { public int woof() { return 7; } public static void main(String[] args) { clank="BONK"; ^ Foo.java:5: cannot assign a value to final variable clank System.out.println(clank); } } - Interfaces can contain method signatures and field declarations = All interface method declarations are automatically public = All interface field declarations are automatically public static final - So they must be initialized.. = Can include or omit the 'public's and 'public static final's in interface declarations. Maybe more pro to omit. MORE ABOUT INTERFACES public interface Foo { public int woof(); public String clank="honk?"; } class Bar implements Foo { public int woof() { return 7; } public static void main(String[] args) { clank="BONK"; ^ Foo.java:5: cannot assign a value to final variable clank System.out.println(clank); } } - Interfaces can contain method signatures and field declarations = All interface method declarations are automatically public = All interface field declarations are automatically public static final - So they must be initialized.. = Can include or omit the 'public's and 'public static final's in interface declarations. Maybe more pro to omit. = Interface field declarations are slightly on the bogus side.. MORE ABOUT INTERFACES public interface Foo { public int woof(); public String clank="honk?"; } class Bar implements Foo { public int woof() { return 7; } public static void main(String[] args) { clank="BONK"; ^ Foo.java:5: cannot assign a value to final variable clank System.out.println(clank); } } - Interfaces can contain method signatures and field declarations = All interface method declarations are automatically public = All interface field declarations are automatically public static final - So they must be initialized.. = Can include or omit the 'public's and 'public static final's in interface declarations. Maybe more pro to omit. = Interface field declarations are slightly on the bogus side.. public interface Foo { int woof(); String clank="honk?"; } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. How: (1) Extract the (relevant) method decls into a new interface declaration. (2) Have the class implement the new interface (3) Have previous callers of the class now refer to the interface instead REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. How: (1) Extract the (relevant) method decls into a new interface declaration. (2) Have the class implement the new interface (3) Have previous callers of the class now refer to the interface instead BEFORE: public class HelloWorld { public void run() { System.out.println("Hello World"); } public static void main(String[] args) { HelloWorld hw = new HelloWorld(); hw.run(); } } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. How: (1) Extract the (relevant) method decls into a new interface declaration. (2) Have the class implement the new interface (3) Have previous callers of the class now refer to the interface instead DURING (1): public interface HelloWorldInterface { public void run() ; } public class HelloWorld { public void run() { System.out.println("Hello World"); } public static void main(String[] args) { HelloWorld hw = new HelloWorld(); hw.run(); } } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. How: (1) Extract the (relevant) method decls into a new interface declaration. (2) Have the class implement the new interface (3) Have previous callers of the class now refer to the interface instead DURING (2): public interface HelloWorldInterface { public void run() ; } public class HelloWorld implements HelloWorldInterface { public void run() { System.out.println("Hello World"); } public static void main(String[] args) { HelloWorld hw = new HelloWorld(); hw.run(); } } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. How: (1) Extract the (relevant) method decls into a new interface declaration. (2) Have the class implement the new interface (3) Have previous callers of the class now refer to the interface instead DURING (3): public interface HelloWorldInterface { public void run() ; } public class HelloWorld implements HelloWorldInterface { public void run() { System.out.println("Hello World"); } public static void main(String[] args) { HelloWorldInterface hw = new HelloWorld(); hw.run(); } } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. How: (1) Extract the (relevant) method decls into a new interface declaration. (2) Have the class implement the new interface (3) Have previous callers of the class now refer to the interface instead AFTER: public interface HelloWorldInterface { public void run() ; } public class HelloWorld implements HelloWorldInterface { public void run() { System.out.println("Hello World"); } public static void main(String[] args) { HelloWorldInterface hw = new HelloWorld(); hw.run(); } } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. How: (1) Extract the (relevant) method decls into a new interface declaration. (2) Have the class implement the new interface (3) Have previous callers of the class now refer to the interface instead AFTER: public interface HelloWorldInterface { public void run() ; } public class HelloWorld implements HelloWorldInterface { public void run() { System.out.println("Hello World"); } public static void main(String[] args) { HelloWorldInterface hw = new HelloWorld(); hw.run(); ^ ^ } | \--Talks about the implementing class. } Talks about the interface To build something, we need a real -- all we need to call run() class.. REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. How: (1) Extract the (relevant) method decls into a new interface declaration. (2) Have the class implement the new interface (3) Have previous callers of the class now refer to the interface instead AFTER: Problem: We usually want the public interface HelloWorldInterface { _interface_ to get the 'nice public void run() ; clean' name.. } public class HelloWorld implements HelloWorldInterface { public void run() { System.out.println("Hello World"); } public static void main(String[] args) { HelloWorldInterface hw = new HelloWorld(); hw.run(); ^ ^ } | \--Talks about the implementing class. } Talks about the interface To build something, we need a real -- all we need to call run() class.. REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior -- better way Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. How: (0) Rename the class 'Foo' to something like 'FooImplementation'. Then: (1) Extract the method decls into a new interface declaration named 'Foo' (2) Have the class implement the new interface (3) Have previous callers of the class now refer to the interface instead REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior -- better way Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. How: (0) Rename the class 'Foo' to something like 'FooImplementation'. Then: (1) Extract the method decls into a new interface declaration named 'Foo' (2) Have the class implement the new interface (3) Have previous callers of the class now refer to the interface instead BEFORE: public class HelloWorld { public void run() { System.out.println("Hello World"); } public static void main(String[] args) { HelloWorld hw = new HelloWorld(); hw.run(); } } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior -- better way Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. How: (0) Rename the class 'Foo' to something like 'FooImplementation'. Then: (1) Extract the method decls into a new interface declaration named 'Foo' (2) Have the class implement the new interface (3) Have previous callers of the class now refer to the interface instead DURING (0): public class HelloWorldImpl { public void run() { System.out.println("Hello World"); } public static void main(String[] args) { HelloWorldImpl hw = new HelloWorldImpl(); hw.run(); } } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior -- better way Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. How: (0) Rename the class 'Foo' to something like 'FooImplementation'. Then: (1) Extract the method decls into a new interface declaration named 'Foo' (2) Have the class implement the new interface (3) Have previous callers of the class now refer to the interface instead DURING (1): public interface HelloWorld { public void run() ; } public class HelloWorldImpl { public void run() { System.out.println("Hello World"); } public static void main(String[] args) { HelloWorldImpl hw = new HelloWorldImpl(); hw.run(); } } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior -- better way Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. How: (0) Rename the class 'Foo' to something like 'FooImplementation'. Then: (1) Extract the method decls into a new interface declaration named 'Foo' (2) Have the class implement the new interface (3) Have previous callers of the class now refer to the interface instead DURING (2): public interface HelloWorld { public void run() ; } public class HelloWorldImpl implements HelloWorld { public void run() { System.out.println("Hello World"); } public static void main(String[] args) { HelloWorldImpl hw = new HelloWorldImpl(); hw.run(); } } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior -- better way Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. How: (0) Rename the class 'Foo' to something like 'FooImplementation'. Then: (1) Extract the method decls into a new interface declaration named 'Foo' (2) Have the class implement the new interface (3) Have previous callers of the class now refer to the interface instead DURING (3): public interface HelloWorld { public void run() ; } public class HelloWorldImpl implements HelloWorld { public void run() { System.out.println("Hello World"); } public static void main(String[] args) { HelloWorld hw = new HelloWorldImpl(); hw.run(); } } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Separate interface from behavior -- better way Why: A class often provides both method declarations and specific implementations. But a user of a class instance really only cares about the declarations plus some limited agreements as to what the declared methods do. How: (0) Rename the class 'Foo' to something like 'FooImplementation'. Then: (1) Extract the method decls into a new interface declaration named 'Foo' (2) Have the class implement the new interface (3) Have previous callers of the class now refer to the interface instead AFTER: public interface HelloWorld { <----- in HelloWorld.java public void run() ; /-----In HelloWorldImpl.java } v public class HelloWorldImpl implements HelloWorld { public void run() { System.out.println("Hello World"); } public static void main(String[] args) { HelloWorld hw = new HelloWorldImpl(); hw.run(); } } REFACTORING HELLO WORLD - THE EXPLODING CLASS (eclipse demo) REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Provide an abstract base class to encapsulate common behavior Why: An interface provides only method signatures and informal behavioral specs. But often some of the methods that are naturally part of the interface will probably be implemented the same way by (most) all interface implementations. How: (0) Rename the class 'FooImpl' (that implements interface Foo) to something like 'ConcreteFoo'. Then: (1) Move the to-be-shared fields and methods into a new abstract class 'AbstractFoo', that implements interface Foo. (3) Have Concrete Foo extend AbstractFoo rather than implementing Foo BEFORE public interface HelloWorld { public void run() ; } public class HelloWorldImpl implements HelloWorld { public void run() { System.out.println("Hello World"); } public static void main(String[] args) { HelloWorld hw = new HelloWorldImpl(); hw.run(); } } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Provide an abstract base class to encapsulate common behavior Why: An interface provides only method signatures and informal behavioral specs. But often some of the methods that are naturally part of the interface will probably be implemented the same way by (most) all interface implementations. How: (0) Rename the class 'FooImpl' (that implements interface Foo) to something like 'ConcreteFoo'. Then: (1) Move the to-be-shared fields and methods into a new abstract class 'AbstractFoo', that implements interface Foo. (3) Have Concrete Foo extend AbstractFoo rather than implementing Foo DURING (0): public interface HelloWorld { public void run() ; } public class ConcreteHelloWorld implements HelloWorld { public void run() { System.out.println("Hello World"); } public static void main(String[] args) { HelloWorld hw = new ConcreteHelloWorld(); hw.run(); } } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Provide an abstract base class to encapsulate common behavior Why: An interface provides only method signatures and informal behavioral specs. But often some of the methods that are naturally part of the interface will probably be implemented the same way by (most) all interface implementations. How: (0) Rename the class 'FooImpl' (that implements interface Foo) to something like 'ConcreteFoo'. Then: (1) Move the to-be-shared fields and methods into a new abstract class 'AbstractFoo', that implements interface Foo. (2) Have Concrete Foo extend AbstractFoo rather than implementing Foo DURING (1): public interface HelloWorld { public void run() ; } public abstract class AbstractHelloWorld implements HelloWorld { public void run() { System.out.println("Hello World"); } } public class ConcreteHelloWorld implements HelloWorld { public static void main(String[] args) { HelloWorld hw = new ConcreteHelloWorld(); hw.run(); } } REFACTORING HELLO WORLD - THE EXPLODING CLASS What: Provide an abstract base class to encapsulate common behavior Why: An interface provides only method signatures and informal behavioral specs. But often some of the methods that are naturally part of the interface will probably be implemented the same way by (most) all interface implementations. How: (0) Rename the class 'FooImpl' (that implements interface Foo) to something like 'ConcreteFoo'. Then: (1) Move the to-be-shared fields and methods into a new abstract class 'AbstractFoo', that implements interface Foo. (2) Have Concrete Foo extend AbstractFoo rather than implementing Foo AFTER: public interface HelloWorld { public void run() ; } public abstract class AbstractHelloWorld implements HelloWorld { public void run() { System.out.println("Hello World"); } } public class ConcreteHelloWorld extends AbstractHelloWorld { public static void main(String[] args) { HelloWorld hw = new ConcreteHelloWorld(); hw.run(); } } REFACTORING HELLO WORLD - THE FULLY EXPLODED CLASS BEFORE +--------------+ |HelloWorld | |--------------| | | |--------------| |void run() | |void main(..) | +--------------+ REFACTORING HELLO WORLD - THE FULLY EXPLODED CLASS BEFORE AFTER +-----------------------+ |HelloWorld (interface) | +--------------+ |-----------------------| |HelloWorld | | | |--------------| |-----------------------| | | |void run() ; | |--------------| | | |void run() | +-----------------------+ |void main(..) | +--------------+ REFACTORING HELLO WORLD - THE FULLY EXPLODED CLASS BEFORE AFTER +-----------------------+ |HelloWorld (interface) | +--------------+ +-------------------+ |\ |-----------------------| |HelloWorld | |AbstractHelloWorld |...| >| | |--------------| |-------------------| |/ |-----------------------| | | | | |void run() ; | |--------------| |-------------------| | | |void run() | |void run() { .. } | +-----------------------+ |void main(..) | | | +--------------+ +-------------------+ REFACTORING HELLO WORLD - THE FULLY EXPLODED CLASS BEFORE AFTER +-----------------------+ |HelloWorld (interface) | +--------------+ +-------------------+ |\ |-----------------------| |HelloWorld | |AbstractHelloWorld |...| >| | |--------------| |-------------------| |/ |-----------------------| | | | | |void run() ; | |--------------| |-------------------| | | |void run() | |void run() { .. } | +-----------------------+ |void main(..) | | | +--------------+ +-------------------+ ^ / \ --- | +-------------------+ |ConcreteHelloWorld | |-------------------| | | |-------------------| |void main(..) | | | +-------------------+ REFACTORING HELLO WORLD - THE FULLY EXPLODED CLASS BEFORE AFTER +-----------------------+ |HelloWorld (interface) | +--------------+ +-------------------+ |\ |-----------------------| |HelloWorld | |AbstractHelloWorld |...| >| | |--------------| |-------------------| |/ |-----------------------| | | | | |void run() ; | |--------------| |-------------------| | | |void run() | |void run() { .. } | +-----------------------+ |void main(..) | | | +--------------+ +-------------------+ ^ - This is all such a win / \ why, again? --- | +-------------------+ |ConcreteHelloWorld | |-------------------| | | |-------------------| |void main(..) | | | +-------------------+ RE|NEW CONCEPTS - CLASS, INTERFACE, PACKAGE, STATIC - What's the difference(s) between a class and an interface? - What's an abstract class? - What's the difference(s) between an abstract class and an interface? DEATHBOX OPENED - DISCUSSION (1) What spec issues did you find? (2) How did you resolve them? DEATHBOX OPENED - SPEC ISSUES? ------- Here are the rules for putting things into the DeathBox: 1. If you put anything that's not an integer, or a String containing an integer, into the DeathBox, you die. 2. If you put anything outside 6 to 60 into the DeathBox, you die. 3. If you put anything into the DeathBox that's more than three times the last thing put into the DeathBox, you die. 4. If you put the same thing into the DeathBox more than three times, you die. 5. You can't put anything into the DeathBox after you've died. 6. If the thing you put into the DeathBox doesn't cause you to die according to the rules 1-5, then you live. ------- DEATHBOX OPENED - SPEC ISSUES? ------- Here are the rules for putting things into the DeathBox: +-------+ 1. If you put anything that's not an|integer| or a String containing an integer, into the DeathBox, yo+-------+ 2. If you put anything outside 6 to 60 into the DeathBox, you die. 3. If you put anything into the DeathBox that's more than three times the last thing put into the DeathBox, you die. 4. If you put the same thing into the DeathBox more than three times, you die. 5. You can't put anything into the DeathBox after you've died. 6. If the thing you put into the DeathBox doesn't cause you to die according to the rules 1-5, then you live. ------- It says 'integer', not 'Integer'.. E.g., a short is an integer but not an Integer. Can you put a Short into the DeathBox and live? Dave chose: Yes, ditto Character and Byte, etc -- you can put in anything that's java.lang.Number except Double and Float. DEATHBOX OPENED - SPEC ISSUES? ------- Here are the rules for putting things into the DeathBox: +----------------- 1. ----------+anything that's not an integer, or a|String containing an integer| into the DeathBox, you die. +----------------- ----------+ 2. If you put anything outside 6 to 60 into the DeathBox, you die. 3. If you put anything into the DeathBox that's more than three times the last thing put into the DeathBox, you die. 4. If you put the same thing into the DeathBox more than three times, you die. 5. You can't put anything into the DeathBox after you've died. 6. If the thing you put into the DeathBox doesn't cause you to die according to the rules 1-5, then you live. ------- What does this mean?? Containing _only_ an integer? How represented? "2b|~2b" _contains_ an integer.. So does "twelve", arguably.. "f00ba"?? Dave chose: 'contains' means 'contains only', using Integer.parseInt(String) semantics DEATHBOX OPENED - SPEC ISSUES? ------- Here are the rules for putting things into the DeathBox: 1. If you put anything that's not an integer, or a String containing an integer, into the DeathBox, you die. +---------------+ 2. If you put anything|outside 6 to 60|into the DeathBox, you die. +---------------+ 3. If you put anything into the DeathBox that's more than three times the last thing put into the DeathBox, you die. 4. If you put the same thing into the DeathBox more than three times, you die. 5. You can't put anything into the DeathBox after you've died. 6. If the thing you put into the DeathBox doesn't cause you to die according to the rules 1-5, then you live. ------- 6 and 60 can live? Must be. 5, dead; 6, maybe okay. DEATHBOX OPENED - SPEC ISSUES? ------- Here are the rules for putting things into the DeathBox: 1. If you put anything that's not an integer, or a String containing an integer, into the DeathBox, you die. 2. If you put anything outside 6 to 60 into the DeathBox, you die. 3. If +----+t anything into the DeathBox that's more than three times the|last|thing put into the DeathBox, you die. +----+ 4. If you put the same thing into the DeathBox more than three times, you die. 5. You can't put anything into the DeathBox after you've died. 6. If the thing you put into the DeathBox doesn't cause you to die according to the rules 1-5, then you live. ------- 'Last' meaning 'previous' or 'final'? Is (10, 6, 2) legal? 10 is more than three times the last thing put in (2)... Dave chose: Last means 'previous' DEATHBOX OPENED - SPEC ISSUES? ------- Here are the rules for putting things into the DeathBox: 1. If you put anything that's not an integer, or a String containing an integer, into the DeathBox, you die. 2. If you put anything outside 6 to 60 into the DeathBox, you die. 3. If +----+t anything into the DeathBox that's more than three times the|last|thing put into the DeathBox, you die. +----+ 4. If you put the same thing into the DeathBox more than three times, you die. 5. You can't put anything into the DeathBox after you've died. 6. If the thing you put into the DeathBox doesn't cause you to die according to the rules 1-5, then you live. ------- 'Last' meaning 'previous' or 'final'? Dave chose: Previous.. So what about the first thing? Dave chose: No restriction by rule 3 on first thing DEATHBOX OPENED - SPEC ISSUES? ------- Here are the rules for putting things into the DeathBox: 1. If you put anything that's not an integer, or a String containing an integer, into the DeathBox, you die. 2. If you put anything outside 6 to 60 into the DeathBox, you die. 3. If you put anything into the DeathBox that's more than three times the last thing put into the DeathBox, you die. +----------+ 4. If you put the|same thing|into the DeathBox more than three times, you die. +----------+ 5. You can't put anything into the DeathBox after you've died. 6. If the thing you put into the DeathBox doesn't cause you to die according to the rules 1-5, then you live. ------- Are 'new Integer(3)' and 'new Integer(3)' (or 'new Short(3)') the 'same thing'? They're different objects..(or even different types..) Dave chose: ..Must be same _number_.. ..but it was a close call.. DEATHBOX OPENED - SPEC ISSUES? ------- Here are the rules for putting things into the DeathBox: 1. If you put anything that's not an integer, or a String containing an integer, into the DeathBox, you die. 2. If you put anything outside 6 to 60 into the DeathBox, you die. 3. If you put anything into the DeathBox that's more than three times the last thing put into the DeathBox, you die. 4. If you put the same thing into the DeathBox more than three times, you die. +---------+ 5.|You can't|put anything into the DeathBox after you've died. +---------+ 6. If the thing you put into the DeathBox doesn't cause you to die according to the rules 1-5, then you live. ------- Meaning "it's impossible to" or "I musn't"? If latter, or else what? Dave chose: Or else you die again. DEATHBOX OPENED - SPEC ISSUES? ------- Here are the rules for putting things into the DeathBox: 1. If you put anything that's not an integer, or a String containing an integer, into the DeathBox, you die. 2. If you put anything outside 6 to 60 into the DeathBox, you die. 3. If you put anything into the DeathBox that's more than three times the last thing put into the DeathBox, you die. 4. If you put the same thing into the DeathBox more than three times, you die. 5. You can't put anything into the DeathBox after you've died. 6. If the thing you put into the DeathBox doesn't cause you to die according to the rules 1-5, then you live. ------- Gah!