Programming in the Large Advanced Software Engineering Stefan Maetschke School for Information Technology and Electrical Engineering The University of Queensland 2nd Semester 2008 Text book: J. Niño and F.A. Hosch. An Introduction to Programming and Object Oriented Design using Java Version 5.0. 3rd Edition! Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Introduction 1 Ch 1 Quote First things first, but not necessarily in that order. Doctor Who course topics Week 1 2 3 4 5 6 7 8 9 10 11 12 13 Topic Introduction Data abstraction/Class design Data abstraction/Class design Specification and Testing Design Interfaces Inheritance Exceptions and File I/O Threads (semester break) Graphical User Interfaces Collections Generics/Iterators ... we can change that! Chapters 0 1, 2 3, 4 5,6 7, 8 9 10, 11 15, 16 17 17 12, 14 20/22 there is much more there is much more we don't talk about Version control systems Setup integration server Testing methodologies ... you see only my point of view but there are many others ... This course covers the basics of Java and Software Engineering. There is much more to learn ... two question What is the percentage of large software projects that fail? > 30 developers Failure: not in budget, not in time or functionality missing What is the main reason that large software projects fail? why this course 70% of large software projects "fail" (budget, time, function) (The Chaos Report (2009)) big != small combinatorial explosion in complexity abstraction/decomposition/simplicity are paramount abstraction, modules, interfaces and unit tests main problems: management, ignoring the user, ... => extreme programming => Scrum There is much more bad than good code out there! It is up to you to do better! secrets to success Confidence Level Success Factors Executive support 18 User involvement 16 Experienced project manager 14 Clear business objectives 12 Minimized scope 10 Standard software infrastructure 8 Firm basic requirements 6 Formal methodology 6 Reliable estimates 5 Other criteria 5 Chaos Report (2000), http://www.softwaremag.com/archive/2001feb/collaborativemgt.html why Java "modern" language object-oriented garbage collector Java-doc generics, exceptions, ... widely used rock solid excellent documentation huge library (> 3000 classes) more strict than Python, Perl, Scheme => suited for large projects googliness google for: X language C Java C++ C# Perl Python Ruby Scala Haskell kilo-hits 2008 2009 53,000 7,760 1,290 1,020 1,150 527 470 394 212 199,000 26,200 14,100 7,870 4,870 7,680 4,970 2,960 418 and the winner is… http://shootout.alioth.debian.org/ median relative execution time, Ubuntu : Intel® Q6600® quad-core, 13 Benchmarks, 20.07.09 eclipse - JDT Java IDE based on the Eclipse framework Free Huge community Very stable and active, new milestone version every six weeks Java, SWT, JFace Fast, "native" user interface Platforms: Windows, Linux, HP-UX, AIX, Solaris, QNX, Mac OS X Auto Building, Perspectives, Folding editor, Syntax highlighting, Content assist, Auto Completion, Quick Fix, Local History, Code Formatter, ... Good JUnit integration CVS, Subversion Ant, Maven RCP: Rich Client Applications some eclipse plug-ins Over 1000 plugins: http://eclipseplugins.2y.net/eclipse/plugins.jsp Some highlights CheckStyle: Checks coding standards: http://eclipse-cs.sourceforge.net/ FindBugs: Uses rules to find (possible) bugs: http://findbugs.sourceforge.net/ PDM: Finds possible bugs: http://pmd.sourceforge.net/ Metrics: Calculates software metrices http://metrics.sourceforge.net/ Sysdeo: Web development http://www.sysdeo.com/eclipse/tomcatplugin Profiler: A profiler http://eclipsecolorer.sourceforge.net/index_profiler.html Mini-Tute Problem def digit_sum(s): Simplify v = 0.0 for i in range(0,len(s)): if ord(s[i]) > ord('9') or ord(s[i]) < ord('0'): raise ValueError v = v + (ord(s[i])-ord('0')) return int(v) Example: digit_sum("1234") -> 10 Mini-Tute Solution def digit_sum(s): return sum(map(int,s)) Much nicer, isn't it? Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Introduction 1 Ch 1 Quote Let me put it this way: today is going to be a learning experience. Unknown contents A bit of Scheme, Python, Perl, Java, Scala Java in anger Short demo of Eclipse/JDK Guidelines for good code Analysis of some Java code Mini-tutorial Scheme :-| fact(n) = 1*2*3*...*n (define (fact n) (if (= n 0) 1 (* n (fact (- n 1))))) (fact 7) there are certainly enough brackets Perl :-( sub fact { my $prod = 1; $prod *= $_ for 2..shift; return $prod; } &fact(7) really ugly! Python :-) def fact(n): prod = 1 for i in range(2,n+1): prod *= i return prod straight forward but neither elegant nor efficient! def fact(n): short and efficient return reduce(lambda a,b: a*b, xrange(2,n+1), 1) def fact(n): return n*fact(n-1) if n else 1 recursive and elegant Java :-O public class MyMath { public static long fact(int n) { long prod = 1; for(long i=2; i<=n; i++) prod *= i; return prod; } public static void main(String[] args) { System.out.println(MyMath.fact(7)); } } wow! Scala :-)) def fact(n :Int): Int = if(n==0) 1 else n*fact(n-1) def fact(n :Int) = (1/:(2 to n))(_*_) cool! Java in anger - compilation e.g. Eclipse editor interprets byte code javac Hello.java Hello.java code, a text file compiler Hello.class byte code JVM Java in anger - types, variables type variable name(s) int x, y; variable declaration String str; x = 1; y = 0; value assignment str = "text"; int z = x+1; combined declaration and assignment Java in anger - control structures if(x==0) { for(int i=0; i<10; i++) { return 0; } System.out.println(i); } else { return x/y; } int i = 0; while(i<10) { switch(ch) { case '1': x=1; break; case '2': x=2; break; default : x=0; } System.out.println(i++); } Java in anger - method public class MyClass { access modifier return type method name parameters public double dist(double x, double y) { double d = x-y; local variable return d*d; } } return statement return value methods are always part of a class! Java in anger - classes package au.edu.uq.csse2002.helloworld; package declaration public class HelloWorld { class definition private static void output(String text) { System.out.println(text); class method } public static void main(String[] args) { HelloWorld.output("Hello World"); } } main method Eclipse demo code analysis What a software developer thinks… What I look for when I mark… Criteria Proper formatting (style guide) Complete java doc Simplicity Robustness Encapsulation Extensibility good code 1. 2. 3. 4. 5. 6. line length ≤ 80 complexity ≤ 10 no code duplication follows language style value-adding comments automated tests This is the most important slide of the entire course! just because your code is complex does not make it good code. simplicity is the ultimate sophistication - Leonardo da Vinci example code bad and good Mini-Tute Problem class NameTable(object): """A table of names""" def __init__(self, nameList): self.__table = nameList def set(self, i, name): self.__table[i] = name def __str__(): return " ".join(self.__table) nameList = ["Calvin", "Luther"] nameTable = NameTable(nameList) nameTable.set(1,"Hobbes") print nameTable -> Calvin Hobbes print nameList This is a tricky one! Encapsulatio n broken here! What's the output? Mini-Tute Solution class NameTable(object): """A table of names""" def __init__(self, nameList): self.__table = nameList[:] def set(self, i, name): self.__table[i] = name def __str__(): return " ".join(self.__table) This fixes the problem! Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Data Abstraction/Classes 2 Ch 1,2 quote If you lie to the compiler, it will get its revenge! Henry Spencer contents Dynamic versus static typing Object Oriented Paradigm Template for a class Implementation genomic sequence class Implementation test class dynamic/static typing dynamic typing: Type of variable, method is automatically determined and can be changed: Python: pi = 3.14; pi = "three point four" def square(x): return x*x static typing: Type of variable, method must be specified explicitly and cannot be changed: Java, C, C++, C#: double pi = 3.14; int square(int x) { return x*x; } type inference: Type of variable is inferred from type of given value, variable, parameter: Scala: def square(x :Int) = x*x; Java types (primitives): boolean, byte, char, int, long, float, double object oriented programming Object models some data and functions of a real world entity/object Object Oriented (OO) means aggregation of data and corresponding functions plus more Encapsulation Abstraction Polymorphism Inheritance Class is a template of an object Object is an example of a class Instance is a realization of a specific object class in Python The template class Person: def __init__(self, name, age): self.age = age self.name = name constructor member variables homer = Person("Homer Simpson", 36) An instance instantiation class in Java Simplified! This is not the true way! class Person { String name; int age; Person(String name, int age) { this.name = name; this.age = age; } } in contrast to Python we need type and new here Person homer = new Person("Homer Simpson", 36); template executable class public class ClassName { // here go the constants/member variables public ClassName() { // Constructor // initialization of member vars and other stuff } // here go the methods public static void main(String[] args) { // main method } } human genome first human genome sequenced (draft) in 2000 ($300 million US) ~ 25000 genes 3 billion base pairs (= 750MB) $1000 genome in a few years The 1000 genomes project started in 2008 exponential increase in sequence data deoxyribonucleic acid (DNA) sequence browser genomic sequence class Specification DNA: 4 letter alphabet (A,C,T,G) circular genomes exist (bacteria) biological coordinates start at 1 extraction of subsequences immutable (or maybe not) much, much more ... Test toy implementation of JUnit Mini-Tute This is horrible code!!! class LousyModuloCounter { int max1, inc2, c; public LousyModuloCounter(int max, int inc) { max1 = max; /* init max */ inc1 = inc; // init inc c = 1; // init c Write } something public void inc() { better! c = c + inc1; for(int i=100; i>0; i = i-1) { int imax; if(c >= i*imax) {c = c - i*imax; break;} }}} Mini-Tute Solution class ModuloCounter { private int modulus; private int increment; private int counter; public ModuloCounter(int increment, int modulus) { this.increment = increment; this.modulus = modulus; this.counter = 0; } public void increment() { counter = (counter+increment) % modulus; } public int get() { return counter; } } No javadoc for brevity but should be there. Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Data Abstraction/Classes 2 Ch 1,2 quote Simplicity rules! me contents Defensive programming Encapsulation Implementation genomic sequence class Implementation test class defensive programming anticipate modifications/usage/bugs that would cause the code to break What's a potential problem? int i = 0; while(i != 100) { // do something i++; } techniques: design by contract (assertions) exceptions HMB // // // // post- & preconditions app still "crashes" you have to handle them "Hat of the Mean Bastard" encapsulation hide internal variables, methods and implementation from outside => provide stable interface/specification => interns can be changed without affecting depending code => functionality can be extended/modified easily keep interface as general/small as possible access qualifiers Access for variables and methods public: from the outside protected: only from derived class private: only within the class genomic sequence class Specification DNA: 4 letter alphabet (A,C,T,G) circular genomes exist (bacteria) biological coordinates start at 1 extraction of subsequences immutable (or maybe not) much, much more ... Test toy implementation of JUnit Mini-Tute class MyLittleMathLib { public double frac(double x, double y) { return x/y; } public boolean equals(double x, double y) { return x==y; } public int fact(int n) { if(n==0) return 1; return n*fact(n-1); } } Make it more robust! Mini-Tute Solution class MyLittleMathLib { private static double EPS = 1e-10; public double frac(double x, double y) { if(Math.abs(y) < EPS) return Double.Nan; return x/y; } public boolean equals(double x, double y) { return Math.abs(x-y) < EPS; } public long fact(int n) { if(n>50) throw new IllegalArgumentException(“...”); long prod = 1; for(int i=2;i<=n; i++) prod *= i; return prod } } Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Data Abstraction/Classes 3 Ch 3,4 quote It's OK to figure out murder mysteries, but you shouldn't need to figure out code. You should be able to read it. Steve McConnell contents Static methods and variables Final classes, methods and variables Sequence class continued Alphabet Alphabet Factory JUnit Static Distinguishes between class and instance variables Static variable is class specific Static method can access static variables directly but not others Used for constants, instance IDs, Factories, Singletons, ... See also Math package http://java.sun.com/docs/books/tutorial/java/javaOO/cla ssvars.html Final variables: a final variable can be set once and only once. Essentially a constant. Instance vars: a final instance var can be set only once methods: a final method cannot be overridden nor hidden classes: a final class cannot be extended a final reference does not protect the referenced object against modification! final can increase efficiency (allows optimization) http://renaud.waldura.com/doc/java/final-keyword.shtml Sequence class cont... Alphabet AlphabetFactory Mini-Tute /** * Lousy implementation that prints out * names of account holders and current amounts. * @param names Array of account holder names * @param amounts Array of account amounts **/ public void printAccounts(String[] names, Integer[] amounts) { for(int i=0; i<names.length; i++) System.out.println(names[i]+": "+amounts[i]); } it works but we can do better! Mini-Tute Solution better but not good enough class Account { public String name; public int amount; } one array instead of two is better but ... good naming! "accountsArray " would be sub-optimal! public void printAccounts(Account[] accounts) { for(int i; i<accounts.length; i++) { Account account = accounts[i]; System.out.println(account.name+": "+account.amount); } } Mini-Tute Solution - much better class Account { private String name; private int amount; ... // constructor and other stuff here public String toString() { return name+": "+amount; } } class Accounts implements Iterable { private ArrayList<Account> accounts; ... // getter, setter and other stuff here } public void print(Accounts accounts) { for(Account account : accounts) System.out.println(account); } Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Data Abstraction/Classes 4 Ch 3,4 quote Adding manpower to a late software project makes it later. Brooks Law contents Design by contract Design Patterns Factory Singleton Sneak peak inheritance JUnit Sequence class continued design by contract - DbC Contract between client and server Precise description of interface specification Precondition: What is expected? Postcondition: What is guaranteed? Invariant: What is maintained? DbC frameworks Python: PyDBC Scheme: PLT Scheme extension Java: C4J, jContractor, Modern Jass, ... Integral part of Eiffel DbC example public class MyMath { private static double epsilon = 1e-10; // numerical accuracy public static void setEpsilon(double epsilon) { this.epsilon = epsilon; a tiny bit } artificial! ... /** * @requires n >= 0 && n < 50 * @ensures this.factorial(n) > 0 Contract * @invariant eps **/ public static double factorial(int n) { if(n==0) return 1; return n*factorial(n-1); artificial too } } DbC: javadoc & implementation javadoc: only words... @requires: precondition @ensures: postcondition @invariant: class invariants implementation… if statements assertions exceptions DbC frameworks (=> (=> (=> (=> clutters code) kills app) preferred) recommended) C4J example @ContractReference(contractClassName = "CalculatorContract") public class Calculator { public double divide(double x, double y) { return x / y; } } public class CalculatorContract { public void classInvariant() { // Nothing to do here } public void pre_divide(double x, double y) { assert y != 0; } } design patterns … so I implemented a Factory method to create Singleton instances and used a Façade to … Recipes for reoccurring problems in software design Gang of Four (GoF): E. Gamma, R. Helm, R. Johnson, and J. Vlissides Design Patterns: Elements of Reusable Object-Oriented Software, 1995 GoF describe 23 patterns => Creational, structural and behavioral patterns http://en.wikipedia.org/wiki/Design_Patterns factory method to create objects... public class AlphabetFactory { static final Alphabet alphabetDNA = new Alphabet("ACTG"); static final Alphabet alphabetRNA = new Alphabet("ACUG"); public static Alphabet create(String alphabetName) { if(alphabetName.equals("DNA")) return alphabetDNA; if(alphabetName.equals("RNA")) return alphabetRNA; throw new IllegalArgumentException( "Invalid alphabet: "+alphabetName); } } singleton public class Singleton { private static Singleton instance; private Singleton() {...} public static Singleton getInstance() { if(instance == null) instance = new Singleton(); return instance; } } there is always only one instance private constructor static instance Singleton singleton = Singleton.getInstance(); preview inheritance Generalization: is-a relationship derived class inherits attributes/methods from base class JUnit Greatest invention since Sliced Bread! Testing framework for automated tests to test the code document spec find bugs quickly allow refactoring Mini-Tute import static java.lang.Double.NaN; public double divide(double x, double y) { double result; if(y == 0) { result = NaN; That's an } easy one! else { Simplify! result = x/y; } return result; } Mini-Tute Solution import static java.lang.Math.abs; import static java.lang.Double.*; public double divide(double x, double y) { return abs(y)<=MIN_VALUE ? NaN : x/y; } import static java.lang.Double.*; public double divide(double x, double y) { try { return x/y; } catch(ArithmeticException ae) { return Nan; } } ...or with exceptions ! Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Specification & Testing 4 Ch 5,6 quote Any fool can write code that a computer can understand. Good programmers write code that humans can understand. Martin Fowler contents KISS or MISS Design by contract - some advice Assertions - quickly Testing - a bit more KISS or MISS That simply means KISS! The most consequential impediment to writing correct, maintainable code is complexity. Nino & Hosch, Chapter 5, Programming and object oriented design using Java KISS: Keep it Simple, Stupid! MISS: Make it Simple, Stupid! Design by Contract Recap: @require: precondition: What is expected? @ensure: postcondition: What is guaranteed? class invariant: What is maintained? my suggestions: in real life if DbC then it needs to be automated, e.g. C4J use exceptions for preconditions in public methods use assertions only for postconditions/invariants prefer functionality to assertions/exceptions assertions: enable for development, disable in release assertion assert bool_expr; assert bool_expr : error_str; assert y!=0 : "Division by zero"; must be enabled can be caught and re-thrown but exception is then the better solution try { assert y!=0: "Division by zero"; } catch( AssertionError ae ) { // exception handler System.out.println("Gotcha!"); throw ae; // re-throw } assertions - enable Assertions must be enabled VM argument "-ea" Eclipse: Run Dialog testing Functional testing black box test tests behavior of entire system use cases frequently not automated :-( low coverage :-( performed by test department Unit testing white box test tests individual methods test driven development automated :-) high coverage :-) implemented by developer IMHO: Unit tests are more important than functional tests unit tests test now or never required coverage depends on application: (nuclear power station <-> personal stamp collection management system) automated tests <= JUnit testing frameworks test border cases test examples from equivalency groups test only within current context the more complex the method the more extensive the test full coverage is usually impossible you can test for invalid input => Exception write simple methods and testing is easy JUnit 3 and 4 New in JUnit 4 no inheritance from junit.framework.TestCase required anymore uses annotation: @Test Parametric tests: @Parameters Exception tests: Timeout tests Ignore tests: @Test(expected=IndexOutOfBoundsException.class) @Test(timeout=1) @Ignore("not ready yet") and more ... JUnit 4 & Eclipse JUnit test case wizard Run dialog Mini-Tute a b c 1 2 3 CyclicString cs = new CyclicString("abc"); cs.charAt(1); // -> 'a' cs.charAt(0); // -> 'c' cs.charAt(2); // -> 'b' cs.charAt(3); // -> 'c' cs.charAt(4); // -> 'a' public class CyclicString { private String string; CyclicString(String string) { this.string = string; } public char charAt(int index) { ... } } Implement this! Mini-Tute Solution public char charAt(int index) { int length = string.length(); if(index < 1) index += length; if(index > length) index -= length; return string.charAt(index-1); } public char charAt(int index) { int length = string.length(); index = (index-1) % length; if(index < 0) index += length; return string.charAt(index); } Doesn’t deal with multiple wraps! Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Design 5 Ch 7,8,16 quote Programming can be fun, so can cryptography; however they should not be combined. Kreitzberg and Shneiderman contents UML Stream based IO ArrayList & HashSet Sequence class continued … maybe Mini tute UML Unified Modeling Language (1996) J. Rumbaugh, G. Booch, I. Jacobson "... is a graphical language for visualizing, specifying, constructing, and documenting the artifacts of a software-intensive system." UML models can be automatically transformed into Java developed to describe object oriented systems supports three different views Behavior Structure Dynamics 13 diagrams UML - diagram types http://en.wikipedia.org/wiki/Unified_Modeling_Language UML - use case diagram http://dn.codegear.com/article/31863 UML - class diagram http://dn.codegear.com/article/31863 UML - sequence diagram http://dn.codegear.com/article/31863 Input/Output streams Input stream Output stream http://java.sun.com/docs/books/tutorial/essential/io/streams.html Stream based IO Tutorial: http://java.sun.com/docs/books/tutorial/essential/io/ Byte streams: raw binary data Character streams: characters Buffered streams: optimized streaming Scanning and formatting: Scanner, format IO from command line: stdin, stdout, stderr Data streams: primitive data types and strings Object streams: serialization File readers and writers File Output try { BufferedWriter out = new BufferedWriter( new FileWriter("example.txt")); out.write("Mary Poppins\n"); out.flush(); // flush Mary out.write("supercalifragilistic\n"); out.close(); } catch (IOException ioe) { // do something } http://www.exampledepot.com/egs/java.io/WriteToFile.html?l=rel File Input try { BufferedReader in = new BufferedReader( new FileReader("example.txt")); String line; while ((line = in.readLine()) != null) { System.out.println(line); } in.close(); } catch (IOException ioe) { // do something } http://www.exampledepot.com/egs/java.io/ReadLinesFromFile.html ArrayList<Object> import java.util.ArrayList; Generics ArrayList<String> names = new ArrayList<String>(); names.add("Calvin"); names.add("Hobbes"); names.add("Susi"); Can't be a primitive type! System.out.println(names.get(1)); // print Hobbes for(String name : names) System.out.println(name); // print all names.clear(); // all gone http://www.exampledepot.com/egs/java.io/ReadLinesFromFile.html HashSet<Object> Generics again import java.util.HashSet; HashSet<String> nameSet = new HashSet<String>(); nameSet.add("Calvin"); nameSet.add("Hobbes"); nameSet.add("Hobbes"); // duplicate! System.out.println(nameSet.size()); // -> 2 if(nameSet.contains("Susi") System.out.println("Susi is there"); for(String name : nameSet) // print "Calvin","Hobbes" System.out.println(name); http://www.exampledepot.com/egs/java.io/ReadLinesFromFile.html Mini-Tute public class NameTable { Mutable or private String[] names; immutable? public NameTable(int size) { this.names = new String[size]; } public String get(int index) {return names[index];} public String set(int index, String name) {names[index]=name;} public int size() {return names.length;} public (static) copy(NameTable nameTable) { Bit NameTable newTable = new NameTable(nameTable.size()); for(int i=0; i<nameTable.size(); i++) newTable.set(nameTable.get(i)); Find a better return newTable; } solution! } NameTable newTable = (new NameTable(0)).copy(otherTable); NameTable newTable = NameTable.copy(otherTable); ugly! Mini-Tute Solution 1 public class NameTable { private String[] names; public NameTable(int size) { this.names = new String[size]; } public NameTable(NameTable that) { Copy this(that.size); for(int i=0; i<size(); i++) this.names[i] = that.names[i]; } public String get(int index) {...} public String set(int index, String name) {...} public int size() {...} } NameTable newTable = new NameTable(otherTable); constructor What if we want to have an immutable one?! Mini-Tute Solution 2 public class NameTable { private String[] names; public NameTable(String[] names) { this.names = new String[names.length]; for(int i=0; i<names.length; i++) this.names[i] = names[i]; } public NameTable(NameTable that) { this(that.names); } public String get(int index) {...} // no more set() -> immutable public int size() {...} } What about: this.names = that.names No loop: is that cool? Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Design 5 Ch 7,8 quote Optimism is an occupational hazard of programming: feedback is the treatment. Kent Bent contents Software life cycle Top-down & bottom-up Ends of the spectrum Waterfall Model Extreme Programming Agile methods Intro Generics software design Software life cycle http://www.acerimmeronline.com/vb/html/software_development.html top-down & bottom-up Top-Down starts with skeleton code stepwise refinement integration of components usually simple extensive specification required lots of mock code required unit-testing more difficult less likely to produce reusable components less likely to produce superfluous code Bottom-Up implement basic functions first (libraries) typical for object oriented programming more agile leads to reusable components easier to maintain (components are less interlinked) integration/interface problems are more likely danger of over-engineering Usually a mix of both! I recommend to favor bottom-up Waterfall model you can't go back! Only for tiny problems or as high level guideline. http://www.integrationarchitect.org/wp-content/uploads/2008/02/waterfall_model1.png Waterfall Model purely sequential (no feedback loops) very extensive planning and specification comprehensive documentation simple to use requires highly accurate analysis requires almost perfect design changes are not supported works only for very small or very stable problems outdated! Waterfall with feedback Still assumes you are finished when you are finished... http://www.wittmannclan.de/ptr/cs/slcycles.html Spiral model What you deliver is not what the customer wants! ... and here we go again... More realistic and successful! http://www.outsource2india.com/software/process.asp Extreme Programming User stories on-site customer pair programming small, frequent releases 1-3 weeks iterations test driven (unit tests) constant refactoring simplicity http://www.extremeprogramming.org XP - Process http://www.vtt.fi/inf/pdf/publications/2002/P478.pdf Agile Methods incremental with rapid cycles (weeks) cooperative (customer and developer working together) straightforward (methods is easy to learn/apply/modify) adaptive (able to change quickly) http://www.vtt.fi/inf/pdf/publications/2002/P478.pdf Comparison There are book-shelves of literature on software methodology! •Scrum •Extreme Programming •Lean Software Development •Unified Process •Rational Unified Process •Dynamic Systems Development Method •Prince2 •Microsoft Solutions Framework •Capability Maturity Model Integration •Feature Driven Development •Crystal •... http://www.vtt.fi/inf/pdf/publications/2002/P478.pdf Generics - toy example @SuppressWarnings("unchecked") // extremly ugly! public class Stack<E> { private E[] stack = (E[])new Object[1000]; // ugly but needed private int n = 0; public void push(E element) { stack[n++] = element; } public E pop() { return stack[--n]; } } Stack<String> stack = new Stack<String>(); stack.push("foo"); String elem = stack.pop(); Error checking and other stuff is missing! Mini-Tute Which of the following conditional statements is true? "abc" == "abc" "abc".equals("abc") "abc".equals(new String("abc")) "abc" == new String("abc") "abc" == (new String("abc")).intern() Easy, apart from this one. Guess... Mini-Tute Solution "abc" == "abc" TRUE "abc".equals("abc") TRUE "abc".equals(new String("abc")) TRUE "abc" == new String("abc") FALSE "abc" == (new String("abc")).intern() TRUE Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Interfaces 6 Ch 9 quote There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult. C.A.R Hoare contents interfaces subtyping strategy pattern interfaces interface only specifies abstract methods (and constants) no implementation cannot be instantiated introduces layer of abstraction substitute for multiple inheritance (avoids diamond problem) public interface ISearch { public final int NOT_FOUND = -1; public int search(String str); public int searchNext(int oldPos, String str); } interface implementation public class EditBox implements ISearch { private String text; public int search(String str) { return text.indexOf(str); } public int searchNext(int oldPos, String str) { return text.indexOf(str, oldPos); } public int length() { // not from interface! return text.length(); } } subtype EditBox is subtype of ISearch ISearch EditBox A B subtype is more powerful or at least as powerful as the supertype (added functionality) subtype inherits all the non-private methods of the supertype signatures of methods must match subtype can have (and usually has) additional methods IF B is a subtype of A THEN B can be used wherever A can be used! subtyping - examples B is subtype of A class A {…} class B extends A {…} A B≥A B A B A B a b a b = = = = new new new new A() B() B() A() x interface A {…} class B implements A {…} interface A {…} interface B extends A {…} void foo(A a) {…} => foo(new A()) => foo(new B()) void foo(B b) {…} => foo(new A()) x => foo(new B()) dynamic & static type A A foo(A a) { return a } A A B B a a b b = = = = foo(new A()) foo(new B()) foo(new B()) (B)foo(new B()) Need to cast though! x B Static type mismatch! Dynamic types match! dynamic type - bad example! class AlphabetDNA {…} class AlphabetAA {…} not related urgs! class AlphabetFactory { public Object create(String name) { if(name.equals(“AA”) return new AlphabetAA(); if(name.equals(“DNA”) return new AlphabetDNA(); } } cast required! possible runtime error! Alphabet alphabet = (Alphabet)AlphabetFactory.create("DNA"); dynamic type - good example interface Alphabet {…} class AlphabetDNA implements Alphabet {…} class AlphabetAA implements Alphabet {…} super class phew, better class AlphabetFactory { public Alphabet create(String name) { if(name.equals(“AA”) return new AlphabetAA(); if(name.equals(“DNA”) return new AlphabetDNA(); } } no casting, save! Alphabet alphabet = AlphabetFactory.create("DNA"); dynamic/duck vs. static typing Python: What does it do? Java: What does it do? def add(a,b): return a+b public int add(int a, int b) { return a+b; } add(1,2) # 3 add('a','b') # 'ab' add([1],[2]) # [1,2] public String add(String a, String b) add('1',2) public Tree add(Tree a, Tree b) add('1',2); runtime error :( compile time error :) def add(a:Int, b:int) = a+b Scala: Type inference comparable<T> public interface Comparable<T> { public int compareTo(T o); } compare returns • a negative value if this < o • zero if this equals o • a positive value if this > o java.lang Collections.sort - comparable Collections.sort(List<T> list) ArrayList<Students> students = new ArrayList<Students>(); Collections.sort(students); class Student implements Comparable<Student> { private String name; private int age; public int compareTo(Student that) { return this.name.compareTo(that.name); } } java.util comparator<T> public interface Comparator<T> { public int compare(T o1, T o2); public boolean equals(Object obj); } compare returns • a negative value if o1 < o2 • zero if o1 equals o2 • a positive value if o1 > o2 usually no need to override equals() java.util Write your own! Collections.sort - comparator Collections.sort(List<T> list, Comparator<? super T> c) ArrayList<Students> students = new ArrayList<Students>(); Collections.sort(students, new NameComparator()); Collections.sort(students, new AgeComparator()); class NameComparator implements Comparator<Student> { public int compare(Student s1, Student s2) { return s1.name.compareTo(s2.name); } } class AgeComparator implements Comparator<Student> { public int compare(Student s1, Student s2) { return s1.age - s2.age; } } java.util anonymous class ArrayList<String> strings = new ArrayList<String>(); // sort according to string length Collections.sort(strings, new Comparator<String>() { public int compare(String s1, String s2) { return s1.length() - s2.length(); } } ); strategy pattern strategy pattern - UML strategy pattern - skeleton interface ISpellChecker { class SpellChecker { public void run(String text); private ISpellChecker spellChecker; } public void setSpellChecker(ISpellChecker spellChecker) { this.spellChecker = spellChecker; } public void run(String text) { spellChecker.run(text); } } class CheckEnglish implements ISpellChecker { public void run(String text) {...} } class CheckGerman implements ISpellChecker { public void run(String text) {...} } mini tutorial Mini-Tute reduce: 1+2+3+4 = 10 1*2*3*4 = 24 public int reduce(char op, int[] data) { Ugly & int result = data[0]; Inefficient! for(int i=1; i<data.length; i++) { Write a better if(ch=='+') result = result+data[i]; version! if(ch=='-') result = result-data[i]; if(ch=='*') result = result*data[i]; if(ch=='/') if(data[i]!=0) result = result/data[i]; } return result; } Mini-Tute Solution public interface IOperator { public int calc(int a, int b); } Operator interface public class OperatorDivision implements IOperator { public int calc(int a, int b) { Operator implementation: return b==0 ? 1 : a/b; handles special case nicely } } public int reduce(IOperator op, int[] data) { int result = data[0] for(int i=1; i<data.length; i++) Guess what! result = op.calc(result, data[i]) Strategy pattern! return result; } Mini-Tute Example int[] data = new int[]{1,2,3,4}; reduce(new OperatorPlus(), data); reduce(new OperatorMinus(), data); anonymous class reduce(new IOperator() { public int calc(int a, int b) { return a % b; // modulo }}); Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Interfaces 6 Ch 9 quote Inside every large program, there is a small program trying to get out. C.A.R. Hoare contents static casting autoboxing multiple inheritance iterable interface instanceof abstract classes observer pattern model-view-controller architecture static casting up-casting: (double)314 down-casting: (int)3.14 auto-casting: 10*3.14 double d = 3.14; int i = (int)d; int min = ... int max = ... double progress = i/(double)(max-min); double progress = i/(max-min); usuall y wrong! Autoboxing nope! ArrayList<int> numbers = new ArrayList<int>(); ArrayList<Integer> numbers = new ArrayList<Integer>(); without for(int i=0; i<100; i++) numbers.add(new Integer(i)); “auto”boxin int sum = 0; g for(Integer number : numbers) sum += number.intValue()*number.intValue(); for(int i=0; i<100; i++) numbers.add(i); int sum = 0; for(Integer number : numbers) sum += number*number; with autoboxin g instanceof checks the type of an object try to avoid – it’s BAD if possible use polymorphism instead String name(Object o) { if(o instanceof A) return "is A"; if(o instanceof B) return "is B"; } ugly: run-time errors, inefficient, error prone interface INamed { String name(); } String name(INamed o) { return o.name(); } elegant: compile-time errors, efficient, robust "multiple" inheritance interface extends interface class extends interface interface implements class class class class class extends class interface Iterable<T> interface Implementing this interface allows an object to be the target of the "foreach" statement. Iterable set of public class Students implements Iterable<Student> { private Set<Student> set = new HashSet<Student>(); unique students ... public Iterator<Student> iterator() { implementation return set.iterator(); Iterable interface } } Students students = new Students(); for(Student student : students) System.out.println(student.name): foreach loop uses Iterable interface abstract classes indicated by keyword "abstract" partial implementation cannot be instantiated between an instantiable class and an interface interface methods are implicitly abstract AbstractDrawable public abstract class AbstractDrawable { private Position position = new Position(0,0); public void moveTo(Position position) { this.position.set(position); } Circle public abstract void draw(); } public class Point extends AbstractDrawable { public void draw() {}; } http://java.sun.com/docs/books/tutorial/java/IandI/abstract.html Point example ArrayList Marker interfaces: no spec. of methods Serializable, RandomAccess => instanceof // good practice List<String> list = new ArrayList<String>(); example HashSet // good practice Set<String> set = new HashSet<String>(); oberver pattern - UML event handling user interfaces Model-view-controller architecture one to many relationship Java Observer interface Observable class Model-View-Controller view selection View state change state query user gestures notify change Controller Model e.g. Powerpoint Controller: Menus Views: Normal view, Print view, Slide show, Slide sorter, ... Model: List of graphical objects plus more ... Mini-Tute public class VectorInt { protected int[] data; public VectorInt(int n) { data = new int[n]; } } Someone didn't switch on his/her brain! public class VectorDouble { protected double[] elems; public VectorDouble(int size) { elems = new double[size]; } } Does it public class VectorMath { work? public static product(Object vector1, Object vector2) { double sum = 0.0; if(vector1 instanceof VectorInt) for(int eindex=0; eindex < ((VectorInt)vector1).data.length; eindex++) sum += ((VectorInt)vector1).data[eindex]* ((VectorInt)vector2).data[eindex]; if(vector1 instanceof VectorDouble ) for(int eindex=0; eindex < ((VectorDouble)vector1).data.length; eindex++) sum += ((VectorDouble)vector1).elems[eindex]* ((VectorDouble)vector2).elems[eindex]; This is simply return sum; DISGUSTING } ! } Mini-Tute Questions what's good about that code? nothing ... alright, next to nothing. At least there are classes. what's bad about that code? 1. different names of instance vars in vector classes (data vs. elems) 2. instance variables in vector classes are not encapsulated 3. direct access to vector memory 4. Objects as parameters for product() 5. usage of instanceof 6. no error checking for proper input types (e.g. product(new Blah(), new Bang()) returns 0) 7. "eindex" as an index variable in loop 8. code duplication (two for loops) 9. forced casting to vector type 10. ... Mini-Tute Solution public interface IVector { public double get(int index); public int size(); } Ppublic class VectorInt implements IVector { private int[] data; public VectorInt(int n) { data = new int[n]; } public double get(int index) { return data[index]; } public int size() { return data.length; } } public class VectorDouble implements IVector { private double[] data; public VectorDouble(int n) { data = new double[n]; } ... // same as for VectorInt } public class VectorMath { public static product(IVector vector1, IVector vector2) { double sum = 0.0; for(int i=0; i < Math.min(vector1.size(),vector2.size()); i++) sum += vector1.get(i)*vector2.get(i); return sum; } } Mini-Tute Solution 2 Generic s public class Vector<T> implements IVector { private T[] data; public VectorInt(int n) { data = (T[])new Object[n]; } public double get(int index) { return data[index]; } public int size() { return data.length; } } less code but more memory and a bit slower. IVector vector = new Vector<Integer>(100); Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Inheritance 7 Ch 10,11 quote Prolific programmers contribute to certain disaster. Niklaus Wirth contents inheritance equals() hashCode() HashTable<K,E> inheritance no inheritance for private attributes/methods no inheritance for final classes or methods no inheritance for constructors derived class must call constructor of super class (or default constructor of super class is called automatically) no multiple inheritance for classes (only for interfaces) transitive (C≥B≥A => C≥A) http://java.sun.com/docs/books/tutorial/java/concepts/inheritance.html class extension B extends A class A { public void a() {...} } A +a() B≥A B +b() class B extends A { public void b() {...} } A a = new A() => a.a() => a.b() x B b = new B() => b.b() => b.a() A a = new B() => a.a() => a.b() x => ((B)a).b() class extension - access Access level modifiers: class A { public pub() {...} protected pro() {...} private pri() {...} } class B extends A { ... } B b = new B() => b.pub() => b.pro() => b.pri() x no way to protect a method in a class and its derived classes! Same for class attributes You cannot extend final classes! final class C { ... } super duper class A { public A() {...} } class B extends A { don't public B(...) { have too super(); } } class A { public A(p1, p2, ...) { ... } } class B extends A { public B(...) { super(p1, p2, ...); } } without super the default constructor is called if there is no default constructor super(...) must be called! super(...) must be first line in constructor of subclass don't call overridable methods in constructor class A { } you have default constructor class B extends A { public B(...) { super(); don't } have too } constructor & overriding constructors should not use overridable methods use final to protect methods against overriding and classes against extension public class B extends A { private int[] data; public class A { public A() { init(); } super() public B(int n) { // init data data = new int[n]; init(); } uh! public void init() { ... // do something } public void init() { for(int i=0; i<data.length; i++) data[i] = 1; } } public final void init() { ... // do something } Boom! } inheritance is transitive A +a() B≥A B +b() C≥B C +c() => C ≥ A class A { public void a() {...} } class B extends A { public void b() {...} } class C extends B { public void c() {...} } A.a() B.a(), B.b() C.a(), C.b(), C.c() overloading means multiple methods with the same name but different parameter(s) (type, number) different return type is not sufficient overloading happens at compile time (static) invocation depends on type Doesn' class PrintStream { void print(int i); void print(Object obj); void print(String s); class Nope { int find(); String find(); } print(42); print(new Integer(42)) print("42") void write(int b); void write(byte[] buf, int off, int len); } t work! overriding method with same name and parameters but different implementation in subclass class A { public int foo(int x) { // do THIS } } class A { public int foo(int x) { // do THIS } } class B extends A { public int foo(int x) { // do THAT } Overridin } g class B extends A { public int foo(int x) { super.foo(x); // do THIS // and then do THAT } } foo() from super class! overriding overriding happens at run time (dynamic) class A { public void foo() { // do THIS } } A a = new A(); a.foo(); // A.foo() class B extends A { public void foo() { // do THAT } } ((A)b).foo(); B b = new B(); B.foo(); // B.foo() // B.foo() A a = new B(); a.foo(); // B.foo() equals implemented in root class Object determines whether some other Object is "equal to" this one consistent: multiple invocations of x.equals(y) return same value reflexive: x.equals(x) symmetric: x.equals(y) ==> y.equals(x) transitive: x.equal(y) && y.equals(z) ==> x.equals(z) null: x.equals(null) == false // implementation in Object public boolean equals(Object o) { return o == this; } equals - how to implement equals for Object and not for a subtype use the == operator to check if references are equal use the instanceof operator to check for correct type cast the argument to the correct type check equality of significant fields must be reflexive, symmetric, transitive, consistent implement only for immutable objects override hashCode public boolean equals(Object o) { if(o == this) return true; if(o instanceof X) { Only for X x = (X)o; efficiency! return x.foo.equals(this.foo); } return false; } equals - example public class Address { private String street; private int number; public boolean equals(Object o) { if(o == this) return true; if(o instanceof Address) { Address a = (Address)o; return a.street.equals(this.street) && a.number == this.number; } return false; } } hashCode implemented in root class Object must be overridden if equals() is overridden must be consistent if two objects are equal() they must have the same hash code if two objects are NOT equal() they should have different hash codes but need not public class Address { private String street; private int number; public int hashCode() { return 17 + street.hashCode() + 37 * number; } } Prime is always cool! HashMap generic hash, see also HashSet and Hashtable in java.util stores key-value pairs uses hashCode() public class AddressBook { private HashMap<Address, String> map; public AddressBook() { map = new HashMap<Address, String>(); } public add(Address address, String name) { map.put(address, name); } public String getName(Address address) { map.get(address); } } Only works when hashCode() is overridden Hash table approx. constant access time used in HashSet, HashMap, ... maps integers to memory cells/bins 1 = mod 4 0 12 Collision hashCode - how to real good hash code implementation is tricky! but a reasonably good approximation is: start with some prime number, e.g. 17 convert each field compared in equals as follows boolean byte, char, short long double Object c c c c c = = = = = field ? 1 : 0 (int)field (int)(field ^ (field >>> 32)) (int)Double.doubleToLongBits(field) field.hashCode() aggregate via result = 37 * result + c public int hashCode() { int result = 17; result = 37 * result + c_1; result = 37 * result + c_2; ... result = 37 * result + c_n; return result; } Mini-Tute public class GeometricalThingy { private int type, x1,y1,x2,y2; ... // Some constructors here public String name() { switch(type) { case 0: return "Point"; case 1: return "Line"; case 2: return "Rectangle"; } } Another piece of disgustin g code! public int length() { // only for lines if(type == 1) // Line return sqrt(sqr(x1-x2)+sqr(y1-y2)); throw new UnsupportedOperationException("Length only for lines."); } public int area() {...} // only for rectangles } Mini-Tute Solution public abstract class GeometricalThingy { private String name; protected int x, y; protected GeometricalThingy(String name) { this.name=name; } public String name() { return name; } } public class GeometricalPoint extends GeometricalThingy { public GeometricalPoint() { super("Point"); } } public class GeometricalLine extends GeometricalThingy { private int x2, y2; public GeometricalLine() { super("Line"); } public int length() {...} } public class GeometricalRectangle extends GeometricalThingy { ... public int area() {...} } Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Inheritance and Stuff 7 Ch 10, 11 quote True refinement seeks simplicity. Bruce Lee contents enums inheritance & composition adapter pattern regular expressions enums // classic approach public static final public static final public static final Old style! for int int int enums SEQTYPE_DNA = 0 SEQTYPE_RNA = 1 SEQTYPE_AA = 2 not type safe (you can pass another int value) no namespace (prefix, e.g. SEQTYPE_ is required) no string representation (print out of constant gives only number) // enums, since 5.0 enum SeqType {DNA, RNA, AA} there is a lot more to it! enums - more enums can have data and/or methods assigned enums are iterable (.values()) enums have string representation public enum Operation { PLUS { double eval(double MINUS { double eval(double TIMES { double eval(double DIVIDE { double eval(double x, x, x, x, double double double double y) y) y) y) { { { { return return return return x x x x // Do arithmetic op represented by this constant abstract double eval(double x, double y); } http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html + * / y; y; y; y; } } } } }, }, }, }; enums - and more public static void main(String args[]) { double x = Double.parseDouble(args[0]); double y = Double.parseDouble(args[1]); for (Operation op : Operation.values()) System.out.printf("%f %s %f = %f\n", x, op, y, op.eval(x,y)); } $ java Operation 4 2 4.000000 PLUS 2.000000 = 6.000000 4.000000 MINUS 2.000000 = 2.000000 4.000000 TIMES 2.000000 = 8.000000 4.000000 DIVIDE 2.000000 = 2.000000 inheritance & composition inheritance skeleton <- interface IThingy AbstractThingy Dingus Gimzo Doodad <- abstract class Whatsis <- classes extension vs composition extension: better code reuse, polymorphism, easy composition: better encapsulation, higher flexibility, tricky extension composition Superclass is-a ComposedClass has-a CoreClass Subclass => prefer composition over extension (simpler, more robust) adapter pattern adapter pattern - UML simply a wrapper makes two interfaces/classes compatible to each other adaptor contains instance of the class it wraps used when extension of adaptee is not possible or when there are many targets (=> avoid interface clutter) adapter pattern - example Target public interface IVector { public void set(int index, float value); public float get(int index); } Client public class LinAlgebra { public static double product(IVector v1, IVector v2); } MyVector implements IVector would not work! Why? public class MyVector { public void set(double value, int index); public double get(int index); Adapter } public class VectorAdapter implements IVector { private MyVector myVector; Adaptee public void set(int index, float value) { myVector.set(value, index); } public float get(int index) { return (float)myVector.get(index); } } regular expressions Reg(ular)?\s+Ex(pres{2}ions)? intro succinct syntax to describe string patterns: colou?r(ed|s)? -> color, colour, colors, coloured, ... not necessarily very readable: \d\d?[\.\-]\d\d?[\.\-]\d\d(\d\d)? Ken Thompson, QED editor, 1966 natively in Perl, Ruby, ... as library in Python, Java, ... java.util.regex http://java.sun.com/docs/books/tutorial/essen tial/regex/index.html Regex - basics abc a|b a* a+ a? a{2,3} [abc] [^abc] [a-zA-Z] (ab)|b . (.)\1 -> -> -> -> -> -> -> -> -> -> -> -> abc a, b Ø, a, aa, aaa, ... a, aa, aaa, ... Ø, a aa, aaa a, b, c not a, b, c a..z, A..Z ab, b matches every letter matches all pairs NFA Nondeterministic Finite Automaton (NFA) backtracking sub-expressions: ( ) back-references: \1 (a | b)*abb abb, aabb, babb, ... http://www.codeproject.com/KB/recipes/regex.aspx Pattern & Matcher Pattern: compiled regular expression Matcher: Matching engine Pattern pattern = Pattern.compile("a?b"); Matcher matcher = pattern.matcher("ababbb"); if(matcher.matches()) System.out.println("Matches entire string"); while(matcher.find()) { String match = matcher.group(); int start = matcher.start(); int end = matcher.end(); } regex in Java examples public String reduceWhitespace(String str) { Pattern pattern = Pattern.compile("\\s+"); Matcher matcher = pattern.matcher(str); return matcher.replaceAll(" "); } "a small test" => "a small test" public List<String> extractTime(String str) { List<String> matches = new ArrayList<String>(); Pattern pattern = Pattern.compile("(\\d?\\d:\\d\\d(pm|am)?)"); Matcher matcher = pattern.matcher(str); while(matcher.find()) matches.add(matcher.group()); 1:35pm return matches; 12:01 } ... special characters character classes predefinded char classes boundary matchers Mini-Tute I i() A C B c() a() ab() b() Mini-Tute Solution? This isn't it! I interface +i() no implementation A B C +a() +b() +c() +ab() +ab() +i() +i() +i() Mini-Tute Solution Most likely! There are others AB I interface +i() no implementation abstract C +ab() +c() +i() +i() A B +a() +b() Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 code review 8 Ch 15,16 quote Susie: You’d get a good grade without doing any work. Calvin: So? Susie: It’s wrong to get rewards you haven’t earned. Calvin: I’ve never heard of anyone who couldn’t live with that. Calvin & Hobbes contents code review code review systematic examination of code frequently as peer review extremely time consuming very useful to bring novices up to speed also to achieve consistent coding style highly effective in finding flaws/bugs pair-programming is a light-weight alternative http://en.wikipedia.org/wiki/Code_review the solution there were only three interesting pieces of code, the rest was supposed to be trivial and boring - "supposed to be"! solution - contains This was supposed to be trivial and boring! Can't get any simpler! Read the java doc and know what is available! solution - record Consistent, straightforward variable name. Don't invent anything fancy This was the only slightly interesting part solution - constructor NGramSet intern() to store identical n-grams only once. Was not expected! solution - similarity There are alternatives but this is straightforward for-each loop count/(double)keySet.size() would have been shorter. Maybe helper variable for keySet.size() unit test for this case is actually missing solution - find -1 guarantees that there is always one match. bad naming. Should have been: bestSigma and bestRecord you need to store the best record AND the best similarity code review / feedback a lot of it ... code review one @param tag for each parameter comment not aligned wrong comment variable names should start in lower case new variable is not necessary: text = text.toLowerCase() ngramSet would have been better. No "of" brackets not necessary but save code review line comment (//) would have been sufficient inconsistent indentation. Tabs ? explicit iterator not necessary but good name: Copy and Paste is good! double for a counter: avoids casting but is, hmm casting since iter is not typed but should have upper case variable name if-else here is a bit complex. There is a shorter way but good to take care of keySet.size() == 0 code review Why not just "text". "givenData" is very generic. inconsistent indentation. Tabs ? line too long Can be done shorter code review upper case variable names init with zero will cause prob. later on. What if there is only matches with sim = 0 bad choice for variable name: Meaning is wrong can't work: BestSimScore is not updated use line comment instead code review A state machine! to split a string into n-grams. Way too complex but fun ;-) Otherwise very nice code! And it works too! But the complexity is dangerous. Nobody would dare to touch that code. code review Author of the state machine! What SIGMA is may not be known! double counter not necessary since casting later one. typed iterator this time. for-each loop would have been better. surrounding brackets not needed casting here, therefore not double intersect needed maybe "keySize" instead code review indentation no helper variable required The solution. One line! nGramSet has a contains() method. Overly complex code review Good doc, but parameter description should start with upper case letter. Two loops are not need. There is a substring() method no var names in uppercase Test not needed. Just convert every letter to lower case Adding up strings is inefficient. Use StringBuilder for this code review Too much commenting! Elegant solution! A bit less efficient than counting but good. good names! not needed. NGramSet has size() method Without comments more readable code review non-ASCII characters! Copy and Paste from Word/PDF code duplication code duplication code review I wouldn't use this here. easier to store reference to the record instead of index for-each loop over records would be simpler good name but should be "tempSet" inefficient. Similarity is calculated twice Too much commenting. Don't write complete sentences code review oops! unnecessary comment good comment nice intern() ensures that identical n-grams are stored only once. code review for-each over records is good here is a confusion. Similarity is compared against an index. Can't work Again, better to store best record instead index of best record code review Too many blank lines. When more than ten block in groups of at least two Nice comments but a bit too much, e.g. this is obvious method does nothing in case of an error, hmm no need to count elements in a set: nGramSet.size() code review start with upper case line too long good blocking of lines I wouldn't use that many brackets but it is okay variable name "n" is okay. Type "double" is hmm code review not needed. this can never be null! I wouldn't use this here but it is okay indentation unnecessary if-else. It is a boolean expression already. Return it code review start with upper case unnecessary counter. recordArray.length does the job. code review naming could be better close call. use > later on and it doesn't work for-each loop would be better good line blocking, good comments code review loop var should be declared within loop line comments! code review don't start with upper case variable name too long redundant comment line comments right above line. Too many blank lines I don't think this works. Operator precedence! one case would have been sufficient code review C/C++ style. In Java define vars where needed line comments! And indentation! See how difficult it is to decide what is a new method and what a code block not needed and again: for-each loop and storing of record reference would have been better code review goes beyond spec. We implement that latter not needed should be before the text manipulations and is not needed too long code review avoid describing "how" (spec does that). Describe "what" instead. not needed good implementation "record" would have been perfect code review not a good name. "i" is for indices only just "Records:\n" is more efficient StringBuilder style. Isn't more efficient than "+" for strings though code review not a good name. comment redundant not needed not needed loop runs to long code review takes longer to read the comment than the code helper variable not needed. Comment would have done the job not "usually". Always! code review set? Should be ngram conveys no information if-else not needed and confusing. code review missing param description not needed Looks like static method call now. Use lower case names for variables code review Python style Way too complex! It implies that it does something complex but it actually does not! limbo? limboo? not needed code review Python style maybe not. line comment there is not good overly complex code C/C++ style code review character wise copy of an immutable string object into a character array. No needed and overly complex code review storing all sigma for each record in extra array and then searching that array for max sigma is inefficient and overly complex. If your code is more than 10 lines long, something is probably wrong code review indentation and other problems. Don't mix tabs and spaces. See how ugly it gets. Use spaces only! code review Bracket position is C style. Some Java people do that too but I don't recommend it. (other problems too) code review Too many helper variables. Use them only if you need them. (other problems too) code review 15 lines where one is needed. Overly complex code review Python style This is beautiful. I like that! Never thought about that. a bit too much commenting for my taste not for the "test". there is a reason beyond that code review redundant comment see that! dangerous! no helper variable required code review variable names! too much commenting variable names! see how difficult that becomes to read! summary highly interesting and educating common problems ignoring available methods => overly complex or awkward code overly complex code => slow, error prone, hard to maintain, difficult to read, ... variable names meaningful, consistent, < 10 chars comments meaningful, short, only when needed indentation follow language style, no tabs! there were perfect solutions - it's possible! philosophical Code is to a programmer like a chess board is to a chess player. me An experienced coder/player can see with one glance whether it makes sense, what it does and whether there is a problem (for short pieces of code < 10 lines). Use an awkward chess board with additional pieces and you don't see anything anymore (follow the style, simple code). For short code it takes longer to read the comment than to read the code Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Exceptions/Cloning 8 Ch 15,16 questions & quotes The best way to get a project done faster is to start sooner. Jim Highsmith contents exceptions cloning exceptions avoid code cluttering replace if-statements and error return codes separating error-handling code from "regular" code allow to group or to differentiate errors are automatically propagated can be forwarded or re-thrown (chained) can be checked or unchecked you can make up your own http://java.sun.com/docs/books/tutorial/essential/exceptions/index.html non-exception vs exception http://java.sun.com/docs/books/tutorial/essential/exceptions/index.html exceptions - skeleton try { // something that } catch (Exception1 e) // handle case 1 } catch (Exception2 e) // handle case 2 } . . . finally { // always executed } can go boom! throwing zone { { catching zone regardless what happens exceptions - example try { reader = new FileReader(new File("MyFile.txt")); ... } catch (FileNotFoundException fnf) { System.out.println("Can't find file!\n"+fnf); } catch (IOException ioe) { System.out.println("Can't access file!\n"+ioe); } catch (Exception e) { System.out.println("Something went wrong!\n"+e); } finally { reader.close(); } exception propagation c b a call stack a(b(c())) http://java.sun.com/docs/books/tutorial/essential/exceptions/definition.html forward exceptions pass exception handling to calling method you have to declare checked exceptions if there is no good way to deal with an exception in the current context, leave it to the caller public String readFile(String fname) throws IOException, FileNotFoundException { FileReader reader = new FileReader(new File(fname)); } public String readFile(String fname) throws Exception { FileReader reader = new FileReader(new File(fname)); } When you react the same way in any case exceptions class hierarchy Throwable Error Exception checked unchecked RuntimeException MyException MyException checked and unchecked checked try - catch required or must be listed in the procedure’s header inherited from Exception use when the exception can be expected during normal execution, or is hard to avoid, or beyond the control of the programmer unchecked try - catch not required, no need to be listed in the procedure’s header inherited from RuntimeException use when the exception is unlikely to occur Tendency is to go away from checked exceptions chained exceptions catch clause throws a new exception useful to change exception type or to add information frequently used to make checked exceptions unchecked, which is a questionable practice! try { ... } catch (Exception e) { throw new OtherException("File problem!", e); } creating exceptions Do you need an exception type that isn't represented by those in the Java platform? Would it help users if they could differentiate your exceptions from those thrown by classes written by other vendors? Does your code throw more than one related exception? public class MyException extends Exception public MyException() { super(); } public MyException(String s) { super(s); } } http://java.sun.com/docs/books/tutorial/essential/exceptions/creating.html best practice use checked exception if client can do something useful, otherwise unchecked use standard Java exceptions if you don't provide additional information use "finally" to clean up code (open files, database connections, ...) document exceptions (@throws) and test them (unit test) do not use catch(Exception e) to avoid dealing with different exception types. Catch specific exceptions if possible. do not ignore/suppress exceptions (though there is sleep and clone) do not use exception for flow control http://java.sun.com/docs/books/tutorial/essential/exceptions/creating.html don't misuse Exceptions only for exceptions! public void frac(int[] array) { for(int i=0; i<array.length; i++) { try { array[i] = 1/array[i]; } catch(Exception e) { array[i] = 0; } } this is not the way! } http://java.sun.com/docs/books/tutorial/essential/exceptions/creating.html cloning cloning Sheep dolly2 = (Sheep)dolly1.clone(); purpose: create a copy (shallow/deep) of an object default implementation creates a shallow copy ugly: clone() returns an instance of type Object, checked CloneNotSupportedException(), clone() is not supported by abstract classes e.g. List, problems with final attributes, copies transient attributes, ... => avoid clone and use copy constructors or factory method instead. cloning - example public class Student implements Cloneable { protected String name; // immutable protected Address address; // mutable! public Object clone() throws CloneNotSupportedException { Student copy = (Student)super.clone(); copy.name = name; // no need to clone! copy.address = (Address)address.clone(); deep copy return copy; } } copy constructor public class Student { protected String name; protected Address address; } // immutable // mutable! no need to copy public Student(Student student) { immutables this.name = student.name; this.address = new Address(student.address); copy } constructor Constructor that takes the same object it constructs as parameter code simpler than with cloning and no exceptions! mini-tutorial public abstract class AbstractRecordReader implements Iterable<Record> { public Record find(String key) { ... for (Record record : records) ... } Why an abstract super class? } public class RecordReader extends AbstractRecordReader { ... records.add(new Record(text)); ... } How do we get records from here to AbstractRecordReader? mini-tutorial : intermezzo for(Type element : Iterable<Type> ) recap for-each loop What comes in here? It is a reference to an instance of a class that has the Iterable<Type> interface works? for(Record record : records) YES, but we don't have it for(Record record : AbstractRecordReader) NO, not an instance for(Record record : new RecordReader()) YES, but doesn't make sense for(Record record : this) YES, cool! But why mini-tutorial : a solution public abstract class AbstractRecordReader implements Iterable<Record> { private Records records = new Records(); records in abstract class public void add(Record record) { records.add(record); } public Record find(String key) { for (Record record : records) ... } public Iterator<Record> iterator() { returns records.iterator(); } add method to fill records } public class RecordReader extends AbstractRecordReader { ... add(new Record(text)); ... } Boring, a bit complex, but works. Alternatively: pass records via constructor but as usual we can do better! mini-tutorial : solution public abstract class AbstractRecordReader implements Iterable<Record> { public Record find(String key) { ... for (Record record : this) ... } this is it! } public class RecordReader extends AbstractRecordReader { private Records records = new Records(); ... records.add(new Record(text)); ... public Iterator<Record> iterator() { returns records.iterator(); } } Why/how does it work? Why is this better than the other stuff? Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Graphical User Interfaces 9 Ch 17 quote The best performance improvement is the transition from the nonworking state to the working state. John Ousterhout contents graphical user interfaces history examples design rules swing - first steps Graphical User Interface (GUI) A GUI provides graphical elements (Icons, Menus, Buttons, ...) to perform actions. easier to learn less efficient than CLI in the long run (CLI: Command Line Interface) a lot more work to implement! http://en.wikipedia.org/wiki/Graphical_user_interface history GUI - the beginning http://www.catb.org/~esr/writings/taouu/html/ch02s05.html 1973, Xerox Alto 606*808 monochrome display. 3-button mouse. 2.5 MB removable disks. 16-bit microcode programmable CPU custom-built from TTL chips. A total address space of 64 KB GUI - the beginning 2 Alto (1973): Icons, Windows, Scrollbars, Sliders Star (1981): Desktop metaphor 30 years ago: Lousy progress ! http://www.catb.org/~esr/writings/taouu/html/ch02s05.html GUI History 1973, Alto, Xerox PARC. 1990, Windows 3.0, Microsoft 1984, Macintosh, Apple 1999, GNOME 1.0 2001, Windows XP, Microsoft 1985, C64, Geos 1985, Windows 1.0, Microsoft http://toastytech.com/guis/guitimeline.html design GUI Design Designing a good GUI is an art* and a crucial part for the success of a system (see iPhone) There are design rules and style guides (to avoid the biggest mistakes) There are even design patterns In the end, it again boils down to simplicity! (http://www.cs.helsinki.fi/u/salaakso/patterns/) *just like designing good software is an art. UI - Guidelines? Always use cute icons, buttons, and graphics. Everyone loves big red hearts, pink bunnies, and yellow smily faces. Don't be afraid to experiment with colors! Use as many as you can. Your application should play fun sounds while operating to keep the users entertained. Never, ever, under any circumstance use the OS-native graphical controls or widgets. Users get bored of the same old buttons, text boxes, and stuff. Avoid including a preferences or options dialog. Instead, let the user use the standard OS provided text editor or an editor of their choosing to edit text configuration files. . Users need time to think about what they are doing and get coffee. Your application should always take at least 5 minutes to load even on the fastest available computer. To get the most screen space, force your application to always run maximized. Use the most exotic fonts you can find. File browsing dialogs are not needed, users can easily remember and type in long file paths. If your program implements keyboard shortcuts be original and make them completely different from any other applications. ... http://toastytech.com/guis/uirant.html bad examples 1 Popup dialog under linux Appears when closing Inkscape and I always press the wrong button Occurred while copying a file from inside a zip archive bad examples 2 Download your driver! Meaning? Sure of what? bad examples 3 Part of a user manual. Can you read it?! A bit unorganized I would say! interface hall of shame There are many more... Have a look at the Interface hall of shame (http://homepage.mac.com/bradster/iarchitect/shame.htm) conventions conventions are arbitrary but important decimal system angles weights ... Decimal Clock, French Revolution, 1793 follow the conventions of the domain you develop software for! 10 design rules Visibility of system status Keep users informed about what is going on. System should speak the users' language. Support undo and redo. Follow platform conventions. Either eliminate error-prone conditions or check for them beforehand. Minimize the user's memory load by making objects, actions, and options visible. Allow users to tailor frequent actions (Shortcuts). Dialogues should not contain information which is irrelevant or rarely needed. Error messages in plain language, indicate the problem, suggest a solution. Provide help, list concrete steps, be succinct. Match between system and the real world User control and freedom Consistency and standards Error prevention Recognition rather than recall Flexibility and efficiency of use Aesthetic and minimalist design Help users recognize, diagnose, and recover from errors Help and documentation http://www.useit.com/papers/heuristic/heuristic_list.html swing Swing Swing: Set of libraries to build graphical user interfaces hundreds of classes! complex Demos: c:\Program Files\Java\jdk\demo\jfc\ Tutorials: http://java.sun.com/docs/books/tutorial/ui/index.html http://java.sun.com/docs/books/tutorial/uiswing/start/inde x.html http://zetcode.com/tutorials/javaswingtutorial/ http://www.javabeginner.com/java-swing-tutorial.htm HelloWorld import javax.swing.*; Hello World public class HelloWorld extends JFrame { public HelloWorld() { add(new JLabel("Hello World")); setSize(100, 100); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); pack(); setVisible(true); } public static void main(String args[]) { new HelloWorld(); } } hierarchical structure JFrame JFrame JPanel JButton containers JPanel JLabel components JButton JLabel mini - tutorial mini - tutorial 1 What's wrong here? Red color for an okay operation An erroneous operation "completed successfully"! Should be check boxes instead of radio buttons and only two of them of course. Hard to read. Green for deletion of a db!? mini - tutorial 2 Too many tabs! And a few more? Terrible colors and shapes Too unspecific! I don't know what to say! Too much text and setting up a key mapping is not an error (wrong icon)! Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 User interfaces 9 Ch 17 quote contents Swing Components Containers Event listeners JTable Survey AWT/Swing & SWT/JFace AWT (Abstract Window Toolkit) Swing Sun sits on top of AWT lightweight => not directly related to native peer more comprehensive then AWT "higher order" functions SWT (Standard Widget Toolkit) the beginning heavyweight => rendered by native peer on specific platform minimum common denominator Used by Eclipse closer to AWT then to Swing faster, more native then Swing but less object oriented and less support, documentation JFace Used by Eclipse sits on top of SWT "higher order" function Eclipse JFC Java Foundation Classes Abstract Window Toolkit (AWT) Swing Java2D Look And Feel (LAF) Internationalization ... Swing class hierachy http://www.javabeginner.com/java-swing-tutorial.htm components - principle component = class Properties Methods Events JButton JButton button = new JButton("Cancel"); button.setForeground(Color.blue); button.requestFocus(); button.addActionListener(new ActionListener...); components - 1 Buttons Combo boxes Lists Menus Sliders Text Fields Labels components - 2 Tool tips Progress bars Colour choosers File choosers Tables Text Trees typical structure JFrame JFrame JPanel containers JButton JPanel JLabel components JButton JLabel bottom up Listener Create: Frame Panel Components Listeners Add: JLabel JButton JPanel listeners to components components into panel panel into frame JFrame layout manager layout manager A layout manager determines the size and position of the components within a container Components can provide size and alignment hints but a container's layout manager has the final say It is an object that implements the LayoutManager interface and of course you can implement your own one http://java.sun.com/docs/books/tutorial/uiswing/layout/visual.html some layouts BorderLayout FlowLayout CardLayout NORTH WEST CENTER EAST Left to right, One at a time Top to bottom SOUTH GridLayout GridBagLayout JButton null none, manual setting of coordiantes http://java.sun.com/docs/books/tutorial/uiswing/layout/visual.html layout examples http://java.sun.com/docs/books/tutorial/uiswing/layout/visual.html aggregation of layouts JButton JButton JTextArea aggregation of layouts JButton JButton JFrame NORTH JPanel: FlowLayout JPanel: BorderLayout CENTER JTextArea event listeners event listener register at an event source, e.g. JButton, JPanel, ... event source has list of all registered listeners and notifies about events, e.g. button pressed, mouse moved, ... Event Source register register notify Listener_1 Listener_2 implementation listener implement listener interface application class inner class anonymous class listener should return quickly (runs in dispatch thread!) app implements listener public class MyApp implements ActionListener { private int clickCounter; public MyApp() { ... JButton button = new JButton("Cancel"); button.addActionListener(this); ... } private void actionPerformed(ActionEvent e) { clickCounter++; } } inner listener class public class MyApp { private int clickCounter; public MyApp() { ... JButton button = new JButton("Cancel"); button.addActionListener(new MyListener()); ... } private class MyListener implements ActionListener { public void actionPerformed(ActionEvent e) { clickCounter++; } } } anonymous listener class public class MyApp { private int clickCounter; public MyApp() { ... JButton button = new JButton("Cancel"); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { clickCounter++; }}); ... } } containers intermediate containers Root pane Layered pane Content pane Glass pane Root pane ‘Invisibly’ attached to top-level container Created by Swing when JFrame is created Manages everything between top-level container and components Places menu bar and content pane in an instance of JLayeredPane layered pane provides a third dimension for positioning components (depth, or Z order). allows overlapping components Adding a component to a layered pane, depth is specified as an integer. Menu sits there http://java.sun.com/docs/books/tutorial/uiswing/components/layeredpane.html content pane Usually a JPanel Contains everything except menu bar for most Swing applications JPanel panel = new JPanel(); panel.add(new JLabel("label")); panel.add(...); frame.setContentPane(panel); glass pane Not structured into components event catching painting Used for ‘weird’ interface behavior, rarely used. http://www.java2s.com/Code/Java/Swing-JFC/DemonstrateuseofGlassPane.htm JTable JTable How to use tables: http://java.sun.com/docs/books/tutorial/uiswing/components/table.html Swing tables class diagram JTable +setModel TableModel AbstractTableModel +getRowCount +getColumnCount +getValueAt abstract methods to implement DefaultTableModel +getDataVector +setDataVector uses Vector of Vectors to store data mini - tutorial mini - tutorial 1 Too many buttons a lot of redundancy here! no need for combo boxes here 20 flags?! What are they good for? Not a good method to set a clock mini - tutorial 2 What is CR? Press M to cancel? What is cancel button for? I don't know anymore what I want! Good idea but bad realization. A big nuisance! Should be aligned with left side and in a table Why not just "yes" and "no"? Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Collections 10 Ch 12,(13),14 quote Good judgment comes from experience, and experience comes from bad judgment. Frederick P. Brooks contents assignment 2 assignment 3 demo collections Lists Sets assignment 2 NGramSet Only protected to be testable. Should be private. For a non-private method String would have been the better return type. protected static StringBuilder convert(String text) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < text.length(); i++) { char ch = Character.toLowerCase(text.charAt(i)); if ((ch < 'a' || ch > 'z') && (ch < '0' || ch > '9')) ch = '_'; builder.append(ch); Usage of regular expression is } possible here. Shorter code but less efficient. return builder; } NGramSet protected NGramSet(String text, int n1, int n2) { if (n1 > n2) throw new IllegalArgumentException( "n1 larger than n2!"); StringBuilder builder = convert(text); for (int n = n1; n <= n2; n++) for (int i = 0; i+n <= builder.length(); i++) ngramSet.add(builder.substring(i, i + n).intern()); } Works for StringBuilder. No need to convert to String! protected NGramSet(String text, int n) { this(text, n, n); } Record public class Record { private String text; private NGramSet ngramSet; public Record(String text) { this.text = text; this.ngramSet = new NGramSet(text); } ... } too easy... AbstractRecordReader public abstract class AbstractRecordReader implements Iterable<Record> { public Record find(String key) { double bestSigma = -1.0; Record bestRecord = null; NGramSet keySet = new NGramSet(key); we discussed this already... for (Record record : this) { double sigma = record.ngramSet().similarity(keySet); if (sigma > bestSigma) { bestSigma = sigma; bestRecord = record; } } return bestRecord; } } RecordReader public RecordReader(Reader inputReader, String splitPattern) throws IOException { Pattern pattern = Pattern.compile(splitPattern); BufferedReader reader = new BufferedReader(inputReader); StringBuilder builder = new StringBuilder(); String line; while ((line = reader.readLine()) != null) builder.append(line).append("\n"); for (String text : pattern.split(builder)) records.add(new Record(text.trim())); reader.close(); } readLine kills \n. We have to add it. again, no need to convert to string. RecordReader public RecordReader(File inputFile, String splitPattern) throws IOException { this(new FileReader(inputFile), splitPattern); } trivial, but has to happen in this(...) public RecordReader(String inputString, String splitPattern) throws IOException { this(new StringReader(inputString), splitPattern); } assignment 3 - GUI Window title Search field Search button selected match similarity scores in percent Table with best matches Divider of split pane Record text of match selected in table Record field collections mini-recap import java.util.Collection; // Interface import java.util.ArrayList; // Implementation import java.util.HashSet; // Implementation ... Collection coll1 = new ArrayList(); Collection coll2 = new HashSet(); ... col1.add("Test"); ... if(col1.isEmpty()) return false; collections A collection — sometimes called a container — is an object that groups multiple elements into a single unit. The collections framework is a unified architecture for representing and manipulating collections. It contains: Interfaces Implementations Algorithms collections are generic: interface Collection<E> AbstractCollection implements some functionality collection may throw UnsupportedOperationException (which is ugly) http://java.sun.com/docs/books/tutorial/collections/index.html grand overview advantages Reduces programming effort. Increases program speed and quality. Allows interoperability among unrelated APIs. Reduces effort to learn and to use new APIs. Reduces effort to design new APIs. Fosters software reuse. powerful stuff! get familiar with it! http://java.sun.com/docs/books/tutorial/collections/index.html base interfaces Collection: Set: List: Queue: Map: SortedSet: no duplicates ordered collection typically FIFO order maps keys to values maintains order http://java.sun.com/docs/books/tutorial/collections/interfaces/index.html base interfaces http://en.wikibooks.org/wiki/Java:Collections collection interface http://java.sun.com/docs/books/tutorial/collections/interfaces/collection.html collection support for-each loop: for(Object o : collection) System.out.println(o) have iterators: can be converted to arrays: String[] a = c.toArray(new String[0]); http://java.sun.com/docs/books/tutorial/collections/interfaces/collection.html sets - class diagram http://en.wikibooks.org/wiki/Java:Collections set inherits from collections but adds nothing however, no duplicates three implementations HashSet: fast, not ordered TreeSet: slower, but ordered LinkedHashSet: medium, ordered, more memory http://java.sun.com/docs/books/tutorial/collections/interfaces/set.html set - example public static <T> Collection<T> findDups(Collection<T> c) { Collection<T> dups = new LinkedList<T>(); Set<T> set = new HashSet<T>(); for(T e : c) if(!set.add(e)) dups.add(e); return dups; } Set<T> s = new HashSet<T>(); is good practice! set.add() returns false if element is already in set. http://java.sun.com/docs/books/tutorial/collections/interfaces/set.html set - operations there are no set methods such as union, intersection, difference but ... "set operations" above are non-destructive note that these methods are NOT set specific http://java.sun.com/docs/books/tutorial/collections/interfaces/set.html list - class diagram http://en.wikibooks.org/wiki/Java:Collections list - interface http://java.sun.com/docs/books/tutorial/collections/interfaces/list.html list lists are ordered collections inherited from Collection but with additional methods: positional access search richer Iterator range-operations two implementations: ArrayList: fast positional access LinkedList: better for insertions, deletions http://java.sun.com/docs/books/tutorial/collections/interfaces/list.html list - example swap two elements of a list random shuffling of list elements => note there is a Collections.shuffle() already! http://java.sun.com/docs/books/tutorial/collections/interfaces/list.html list - iterator List implements ListIterator http://java.sun.com/docs/books/tutorial/collections/interfaces/list.html list - range view replaces for(fromIndex, toIndex) loops remove a range of elements from a list find an element in a range http://java.sun.com/docs/books/tutorial/collections/interfaces/list.html list - Algorithms sort shuffle reverse rotate swap replaceAll fill copy binarySearch indexOfSubList lastIndexOfSubList All to find in java.utils.Collection s http://java.sun.com/docs/books/tutorial/collections/interfaces/list.html mini tutorial StringBuilder builder = new StringBuilder(); while ((line = bufferedReader.readLine()) != null) builder.append(line.toString()+"\n"); Can we do better? What do you think about this? static protected StringBuilder convert(String text){ return new StringBuilder(text.toLowerCase().replaceAll("\\W", "_")); } static public <E> void replace(List<E>, E val, E newVal) { for (ListIterator<E> it = list.listIterator(); it.hasNext(); ) if (val == null ? it.next == null : val.equals(it.next())) it.set(newVal); Why and how } does it work? mini tutorial solution StringBuilder builder = new StringBuilder(); while((line = bufferedReader.readLine()) != null) builder.append(line).append("\n"); no creation of temporary string anymore static protected StringBuilder convert(String text){ return new StringBuilder(text.toLowerCase().replaceAll("\\W", "_")); } nice! Would be perfect for String as return type static public <E> void replace(List<E>, E val, E newVal) { for (ListIterator<E> it = list.listIterator(); it.hasNext(); ) if (val == null ? it.next == null : val.equals(it.next())) it.set(newVal); deals with null values to replace } in an elegant way Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Collections 10 Ch 12,14 questions & quotes When someone says, "I want a programming language in which I need only say what I want done," give him a lollipop. Alan Perlis contents collections queues maps about consequences a short story about wrong package names and other software bugs ... simple software errors Mars Polar Lander lost (misinterpretation of vibration due to leg-deployment as touch down) $120 Million lost Mars Climate Orbiter crashed when entering mars atmosphere (Mix of metric and English units in navigation software) $330 Million lost Ariane 5 self-destructed (safety measure) shortly after lift-off (bad floating point to integer conversion) $500 Million lost Patriot missile battery fails to intercept Iraqi Scud missile (rounding error of internal clock) 28 killed, 98 wounded 1980 NORAD reports US under missile attack (software ignored possible circuit failure) 1983 Soviet satellite reports incoming missiles (software misinterpreted sun beam reflections on clouds) to read: http://en.wikipedia.org/wiki/Stanislav_Petrov bugs & consequences it is not important how big the bug is! it is the consequences that count! collections queues and maps queue - class diagram - there are more queue classes ... ArrayBlockingQueue, ConcurrentLinkedQueue, DelayQueue, LinkedBlockingQueue, LinkedList, PriorityBlockingQueue, PriorityQueue, SynchronousQueue http://en.wikibooks.org/wiki/Java_Programming/Collection_Classes#Queue queue - interface typically FIFO exception: priority queues can be bound (upper limit for number of elements) methods in two flavors (exception, special value) LinkedList implements Queue<E> interface http://java.sun.com/docs/books/tutorial/collections/interfaces/queue.html queue - example priority queue to sort list elements Priority according to Comparable Internally implemented as a binary tree note there is a Collections.sort() method already http://java.sun.com/docs/books/tutorial/collections/interfaces/queue.html map - class diagram http://en.wikibooks.org/wiki/Java:Collections map - interface http://java.sun.com/docs/books/tutorial/collections/interfaces/map.html map maps keys to values no duplicate keys keys need to be immutable keys: hashCode() implementation supports iteration over keys, values and pairs the three main implementations: HashMap: fast, keys not ordered TreeMap: slower, keys ordered LinkedHashMap: medium, keys ordered, more memory http://java.sun.com/docs/books/tutorial/collections/interfaces/map.html map - example public static <T> void histogram(Collection<T> c) { Map<T, Integer> map = new HashMap<T, Integer>(); for(T e : c) { Integer freq = map.get(e); map.put(e, freq == null ? 1 : freq + 1); } System.out.println(map); } Map<K,V> s = new HashMap<K,V>(); is good practice! http://java.sun.com/docs/books/tutorial/collections/interfaces/map.html map - views keySet — the Set of keys. values — The Collection of values. entrySet — the Set of key-value pairs. Pairs are return as Map.Entry objects. iterating over the keys of a map: iterating over the key-value pairs of a map: http://java.sun.com/docs/books/tutorial/collections/interfaces/map.html more mapping keys common to two maps: remove keys in map that exist in another map remove entries in map that exist in another map http://java.sun.com/docs/books/tutorial/collections/interfaces/map.html when to use what List ArrayList: constant access time, slow insertion and deletion LinkedList: linear access time, fast insertion and deletion LinkedList: FIFO (no sorting), fast PriorityQueue: sorted, slower HashMap/Set: fast, keys not ordered TreeMap/Set: slower, keys ordered, can be sorted LinkedHashMap/Set: medium, keys ordered outdated see java.util.concurrent see java.utils.Collections Queue Map/Set Hashtable, Vector complexity O() Collection with 65536 elements Quadratic O((N-1)*N/4) 1,073,725,440 Insertion sort => efficient algorithm is much more important than efficient implementation! http://www.digilife.be/quickreferences/PT/Java%20Collections%20Framework.pdf synchronized wrappers thread-safe collections https://java.sun.com/docs/books/tutorial/collections/implementations/wrapper.html unmodifiable wrappers immutable collections https://java.sun.com/docs/books/tutorial/collections/implementations/wrapper.html convenience implementations List view of an array: to use an array as a list/collection multiple-copy list: to initialize a collection with a value immutable singleton set: to remove all elements of a specific value https://java.sun.com/docs/books/tutorial/collections/implementations/convenience.html mini - tutorial public interface Text { public String getLine(int number); } public class SpellChecker { public boolean isCorrect(Text text) {...} } public class ExtTextField implements Text { private JTextField textField; public ExtTextField(JTextField textField) { this.textField = textField; } public String getLine(int number) { return textField.getText(); } } What design pattern has been applied? mutable or immutable and is there a problem? Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Generics 11 Ch 20 quote I know that you believe that you understood what you think I said, but I am not sure you realize that what you heard is not what I meant. Robert McCloskey contents JAR files Generics JAR files JAR file JAR = Java ARchive compressed resources (classes, source, images, sound, documentation, ...) based on ZIP => unpack with WinZip, ... "executable" if JRE is installed properly can be signed => security privileges can be sealed => version consistency can be obfuscated => hampers reverse engineering portable http://java.sun.com/docs/books/tutorial/dep loyment/jar/basicsindex.html basics create a JAR file: jar cf jar-file input-file(s) Eclipse: File->Export... run a JAR file: java -jar app.jar (needs Main-class in manifest) or simply double-click view its contents jar tf jar-file create jar file - example jar cvf TicTacToe.jar TicTacToe.class audio images automatically adds manifest file http://java.sun.com/docs/books/tutorial/deployment/jar/build.html application entry point application entry point tells Java VM which main method of which class to invoke. Signature of entry point: public static void main(String[] args) specified in manifest file Main-Class: mypackage.MyClass e.g. Main-Class: calculator.Calculator manifest file created by default and required stored at META-INF/MANIFEST.MF describes how JAR is used specifies application entry point manifest must end with a new line! manifest must be encoded in UTF8 UTF8: unicode but backwards compatible to ASCII UTF-8 intermezzo 8-Bit UCS/Unicode Transformation Format variable length character encoding for Unicode backwards compatible with ASCII (128 chars) may start with Byte Order Mark: BOM: EFBBBF to mark UTF-8 () => manifest must NOT have a BOM! JAR classpath referencing of classes in other JAR files outside a JAR files Class-Path: jar1-name jar2-name directory-name/jar3name path on local drive (not within JAR file!) doesn't allow you to put all jars of an application into one single JAR => but there are tools for that package versioning package version in manifest file http://java.sun.com/docs/books/tutorial/deployment/jar/packageman.html sealing sealing: all classes of a package must be archived in the same JAR file ensures version consistency you cannot add new classes to a package from the outside entry in manifest file package name must end with "/" http://java.sun.com/docs/books/tutorial/deployment/jar/sealman.html signing electronic signature sign: jarsigner jar-file alias verify: jarsigner -verify jar-file user can grant special security privileges Applets: accessing file system public and private keys private key signs public key verifies procedure: Signer signs JAR file using private key corresponding public key is placed in jar file user verifies deployment Tools to create a single JAR One-JAR http://one-jar.sourceforge.net Fat Jar Eclipse Plugin http://fjep.sourceforge.net Tools to wrap a JAR file in a window executable JSmooth http://jsmooth.sourceforge.net/ Launch4j http://launch4j.sourceforge.net Lift-Off http://liftoff.sourceforge.net JSmooth open source, GPL creates standard windows .exe binary allows icon for executable allows command line arguments searches automatically for best JRE if no JRE installed, installs automatically or points user to website you can bundle your application with an JRE http://jsmooth.sourceforge.net Generics example - class generics public class Stack<T> { private List<T> elements = new ArrayList<T>(); public void push(T element) { elements.add(element); } public T pop() { int top = elements.size()-1; T result = elements.get(top); elements.remove(top); return result; } } Stack<Double> stack = new Stack<Double>(); stack.push(3.14); double pi = stack.pop(); example - method generics public class Tools { public static <T> void fill(List<T> list, T value, int n) { for(int i=0; i<n; i++) list.add(value); } public static <T> T middle(List<T> list) { return list.get(list.size()/2); } } List<String> list = new ArrayList<String>(); Tools.fill(list, "something", 10); String middle = Tools.middle(list); Number - intermezzo Number: super class of Integer, Double, ... example - bound type public class Stats { public static <T extends Number> void init(List<T> l, T e, int n) { for(int i=0; i<n; i++) l.add(e); } public static <T extends Number> double mean(List<T> l) { double sum = 0.0; for(T e : l) sum += e.doubleValue(); return sum; } } List<Double> list = new ArrayList<Double>(); Stats.init(list, 1.0, 10); double mean = Stats.mean(list); generics Generics is not about implementing functionality. Generics is about designing robust software! Generics increase type safety through static typing. Generics reduce casting and allow generic data structures, e.g. Stack<Double> Generics are implemented by type erasure. Generic type information is only available at compile time. Advantage: works with legacy code (uses raw type). Disadvantage: Some things don't work as expected: T[] a = new T[100] Generics are easy to use but difficult to implement (most of the time)! why static typing - 1 what does this code do? def add(a, b): # some miracle A bit of Python int add(int a, int b) { // less of a miracle } Object add(Object a, Object b) { // another miracle } emulating dynamic typing why static typing - 2 def add(a, b): return a+b Fails at runtime int add(int a, int b) { return a+b; } Fails at compile time Object add(Object a, Object b) { return a.add(b); Fails at runtime } before and now public void print_info(Collection c) { for(Object s : c) System.out.println(((Student s).name()); System.out.println(((Student s).address()); System.out.println(((Student s).phone()); } public void print_info(Collection<Student> c) { for(Student s : c) System.out.println(s.name()); System.out.println(s.address()); System.out.println(s.phone()); } with 1.4 with 1.5 old and new public interface IStack { public int size(); public void push(Object item); public Object top(); public void pop(); } public interface IStack<E> { public int size(); public void push(E item); public E top(); public void pop(); } without Generics with Generics the rules The type parameter is included in angular brackets after the class name for class generics or in front of the method name for method generics. Any non-keyword identifier can be used for the type parameter, but by convention, typically an uppercase one letter name is used, e.g. T or E. The type parameter can be used like other types used in the definition of a class or method. The type plugged in for a type parameter must always be a reference type: It cannot be a primitive type such as int, double, or char. But there is auto-boxing! Reference types include arrays. some limitations There are places where an ordinary class name would be allowed, but a type parameter is not allowed. In particular, the type parameter cannot be used in expressions using new to create a new object. Nope! T obj = new T(); You can't T[] a = new T[10]; do that! The type parameter can also not be used as a constructor name or like a constructor: Arrays such as the following are illegal: Stack<String>[] a = new Stack<String>[10]; There are more (subtle) problems caused by the erasure mechanism mini -tutorial public abstract class Person { public String name(); } public class Student extends Person { ... public class Staff extends Person { } ... } public class Utils { public static void printNames(List persons) { for (Object person : persons) if (person instanceof Person) System.out.println( ((Person)person).name() ); } } List<Student> persons = new ArrayList<Student>(); Utils.printNames(persons); Is it any good? Does it work? mini tutorial - first idea public class Utils { public static void printNames(List<Person> persons) { for (Person person : persons) System.out.println( person.name() ); } } List<Person> persons = new ArrayList<Student>(); Utils.printNames(persons); Nice so far! but can't do this :-( Student is subtype of Person BUT List<Student> is NOT subtype of List<Person>! mini tutorial - solution public class Utils { public static <T extends Person> void printNames(List<T> persons) { for (Person person : persons) System.out.println( person.name() ); } } List<Student> students = new ArrayList<Student>(); Utils.printNames(students); List<Staff> staff = new ArrayList<Staff>(); Utils.printNames(staff); That works now! Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Serialization 12 Ch 21,22 quote If you lie to the compiler, it will get its revenge. Henry Spencer contents serialization serialization Object serialization state persistent storage data deserialization persistence: preserve the state of an object beyond the running time of the program: saving an edited text document as a file storing application settings within the registry writing object states to an SQL database ... serialization: mechanism to achieve persistence take all member variables (= state) of an object and save them somewhere, somehow example - serialize public class Document implements Serializable { private String author; Marks an object as private Text text; serializable ... } Needs to implement Serializable as well Document doc = new Document(); try { ObjectOutputStream oos = ObjectOutputStream( new FileOutputStream("Document.ser")); oos.writeObject(doc); Serialization, oos.close(); no need to } catch(IOException ioe) { serialize "text" separately // do something } example - deserialize Document doc = null; try { ObjectInputStream ois = ObjectInputStream( new FileInputStream("Document.ser")); doc = (Document)ois.readObject(); Class cast required ois.close(); } catch(IOException ioe) { // do something or not } catch(ClassNotFoundException cnfe) { cast can fail! // you've got a problem } serializable import java.io (Serializable, ObjectOutputStream, ObjectInputStream) Objects are not per default Serializable Serializable is marker interface (no methods) serializes in binary format => byte stream (can be encrypted) serializes referenced objects automatically if they implement Serializable as well (they have to if they are not transient!) a NotSerializableException is thrown when trying to serialize a class object that is not serializable allows to transport objects across machines, e.g. remote method invocation (RMI) it doesn't matter if member variable are private or protected they are serialized => breaks encapsulation transient and static variables are NOT serialized some classes cannot be serialized, e.g. Threads Swing objects can be serialized but they are platform specific (not recommended) double trouble objects and their referenced objects build graph Java serialization takes that into account and does not serialize objects twice, but ... ObjectOutputStream oos = new ObjectOutputStream(...); Document doc = new Document(); doc.setText("to be or"); oos.writeObject(doc); doc.setText("not to be"); oss.writeObject(doc); // serializes "to be or" // update state // not serialized! call oos.reset() transient marks member variables as NOT being serialized transient variables are set to their default values during deserialization => you usually need to do something extra public class Document implements Serializable { private transient int docID; you usually don't private transient File tempBackup; want to store the private String author; private Text text; and the handle of your ... temporary automatic } backup file is prob. transient too. temporary ID of a loaded document. custom serialization override writeObject, readObject need to be private call default serialization first private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); ... // do your own stuff } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); ... // do your own stuff } versioning problem: class object gets serialized and class definition changes due to software update. question: can serialized class be deserialized/loaded or not solution: serialVersionUID version number of a class => store during serialization a class can be deserialized when the serialVersionUID of the class definition and the serialized class are identical if serialVersionUIDs do not match an InvalidClassException is thrown if no serialVersionUID is provided, it is generated automatically (hidden) serialVersionUID static final long serialVersionUID = 7526472295622776147L; generated serialVersionUID is hash code derived from class properties such as name, member variables, ... and highly sensitive to class changes but you can make up your own. Nothing wrong with: serialVersionUID = 1L but you have to know what is a compatible class modification evolving classes: certain changes in a class definition are compatible, e.g. adding fields, with the serialized object other are not! During deserialization additional fields will be initialized with default values. compatible changes • • • • • • • • Adding fields Adding classes Removing classes Adding writeObject/readObject methods Removing writeObject/readObject methods Adding java.io.Serializable Changing the access to a field Changing a field from static to non-static or transient to non-transient http://java.sun.com/javase/6/docs/platform/serialization/spec/version.html#6678 incompatible changes • Deleting fields • Moving classes up or down the hierarchy • Changing a non-static field to static or a non-transient field to transient • Changing the declared type of a primitive field • Changing the writeObject or readObject method so that it no longer writes or reads the default field data • Changing a class from Serializable to Externalizable or vice versa • Changing a class from a non-enum type to an enum type or vice versa • Removing either Serializable or Externalizable • Adding the writeReplace or readResolve method to a class can be incompatible http://java.sun.com/javase/6/docs/platform/serialization/spec/version.html#6678 creating a serialVersionUID eclipse: quickfix Java: serialver -show if you don't create your own serialVersionUID, one is created automatically (hidden, hash code), which means that almost any change of the class definition will be incompatible with the serialized object. summary implement Serializable create serialVersionUID (using serialver, eclipse, whatever, ...) when class definition changes, decide if changes are compatible with previous definition when compatible keep serialVersionUID (test that extensively!) when incompatible create new serialVersionUID (and provide format/version converter) any object referenced or any superclass has to implement Serializable as well inner classes should not implement Serializable denote serialized fields with @serial other ways Standard serialization is easy but not very efficient (speed, size) output is not human readable => difficult to debug => format/version conversion tricky alternatives: implement your own serialization via Externalizable use other serialization frameworks Hibernate: Maps classes to SQL database tables JSX: Serializes objects to XML ... Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 threads 12 - quote Real computer scientists despise the idea of actual hardware. Hardware has limitations, software doesn't. Anon contents threads the Joel test process vs thread processes: own execution environment - specifically own memory heavy weight threads: live within a process share execution environment - specifically memory light weight Thread class example own class must extend Thread implements run() method start() starts the thread public class HelloWorldThread extends Thread { public void run() { for(int i=0; i<100; i++) System.out.println("Conquer the world!"); } public static void main(String args[]) { (new HelloWorldThread()).start(); } } important Thread methods setName(): guess what setPriority(): priority: 1...10 start(): starts the thread sleep(): sends a thread to sleep, can be interrupted join(): wait for this thread to terminate getState(): NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED isAlive(): test if thread is alive ... deprecated methods: Guess why! It turned out these methods stop(), suspend(), resume(), destroy() Thread are tricky! are not really threadsafe! two ways public class MyThread extends Thread { public void run() { ... } public static void main(String args[]) { (new MyThread()).start(); } } public class MyRunnable implements Runnable { public void run() { ... } public static void main(String args[]) { (new Thread(new MyRunnable())).start(); } } sleep & interrupt Thread.sleep(msec): suspends thread execution for the specified time allows other threads to work can be interrupted => interrupted flag interrupts are used to terminate/control thread Thread.interrupted(): tests if thread has been interrupted and clears flag. Static method usually used to terminate this thread. isInterrupted(): tests if thread has been interrupted and does NOT clear the flag. Non-static method usually used to test status of another thread. sleep & interrupt - example public class MyThread extends Thread { public void run() { while(!done) { ... // do something really smart here try { Thread.sleep(100); } catch (InterruptedException e) { return; } } } public static void main(String args[]) { Thread thread = new MyThread(); thread.start(); ... // do something in main thread thread.interupt(); this is the way to stop a } thread. Not thread.stop()! } don't wanna sleep you don't want to waste time in sleep() need to call Thread.interrupted() periodically public class NumberCruncher extends Thread { public void run() { while(isCrunching()) { some heavy ... // crunch, crunch, ... processing in if (Thread.interrupted()) this loop return; } clears } interrupt } status flag join the party join(): current thread waits for another thread to finish public class ConquerWorld { private class BuildEvilRobots extends Thread { public void run() { ... // build the really evil type } } public static void main(String args[]) { // start conquering with big announcement Thread thread = new BuildEvilRobots(); thread.start(); thread.join() // proceed with conquering } } synchronization - stack - 1 public class Stack10 { private String[] stack = new String[10]; private int n = 0; public int size() { return n; } public void push(String value) { stack[n++] = value; } public String pop() { return stack[--n]; } THREAD1: } if(stack.size() < 10) stack.push("test"); not threadsafe push() and pop() are not atomic operations! THREAD2: if(stack.size() > 0) stack.pop(); you have to be LUCKY that this works! synchronization - stack - 2 public class Stack10 { private String[] stack = new String[10]; private int n = 0; thread-safe public synchronized int size() { return n; } public synchronized void push(String value) { stack[n++] = value; } public synchronized String pop() { methods are now return stack[--n]; synchronized and } push() and pop() } are now atomic operations synchronization when one thread is executing a synchronized method all other threads that want to use synchronized methods of the same object are blocked. can't synchronize constructors too much synchronization => dead locks too little synchronization => consistency errors you can synchronize statements: public void push(String value) { assert(stack != null); e.g. no need to sync. assert() synchronized(stack) { stack[n] = value; finer control over n = n+1; synchronization but } tricky! Careful! } immutable objects are thread-safe no synchronization is required conditions: no setters all fields final and private declare class as final (no overriding) don't reference to mutable objects (create a copy if necessary) Swing application 2+more threads main thread => main method => window Event Dispatch Thread => GUI worker threads => long running tasks most Swing components are NOT thread safe => reason: it is incredibly difficult to do => you need to synchronize, which is tricky! => but there is help: SwingWorker ... SwingWorker Swing application run in the Event Dispatch Thread and long running tasks block GUI Solution: run computationally expensive tasks in separate thread => worker thread SwingWorker is abstract, generic helper class that simplifies the creation and management of worker threads SwingWorker provides all functionality typically needed for worker threads: progress, status, interim results, cancellation, ... => powerful stuff Extending class must implement doInBackground() method, which encapsulates the long running task SwingWorker class result type intermediate results abstract class SwingWorker<T,V> { } abstract T doInBackground(); T get(); void execute(); void done(); boolean isCancelled(); does the main processing void publish(V...chunks); void process(List<V> chunks); ... sends data to process(...) getter for final result starts the worker called when finished indicates cancel from outside receives published data example - bad No SwingWorker Document doc; ... JButton button = new JButton("Load Document"); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { doc = loadHugeDoc(); User interface } blocked while }); loading document example - better Document doc; ... JButton button = new JButton("Load Document"); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { (new SwingWorker<Document, Void>() { public Document doInBackground() { return loadHugeDoc(); runs as separate worker thread } public void done() { doc = get(); get() runs in Event } Dispatch Thread }).execute(); } loading the document as one chunk means no progress bar }); and you can't cancel! publish & process class TableSwingWorker extends SwingWorker<DefaultTableModel, Object[]> { private final DefaultTableModel tableModel; public TableSwingWorker(DefaultTableModel tableModel) { this.tableModel = tableModel; } protected DefaultTableModel doInBackground() { while(Object[] row = loadRow() && !isCancelled()) publish((Object[]) row); load table row by row return tableModel; and update shown table } protected void process(List<Object[]> rows) { process() runs in Event for (Object[] row : rows) { Dispatch Thread tableModel.addRow(row); } } } http://java.sun.com/javase/7/docs/api/javax/swing/SwingWorker.html propertyChange - progress class TableSwingWorker extends SwingWorker<DefaultTableModel, Object[]> { ... protected DefaultTableModel doInBackground() { for(int i=0; i<rowNumber && !isCancelled(); i++) { publish((Object[]) loadRow(i)); setProgress(100*i/rowNumber); } return tableModel; show progress bar } while loading table } final JProgressBar progressBar = new JProgressBar(0, 100); TableSwingWorker tableWorker = new TableSwingWorker(tableModel); tableWorker.addPropertyChangeListener( new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if ("progress".equals(evt.getPropertyName())) { progressBar.setValue((Integer)evt.getNewValue()); } } }); tableWorker.execute(); http://java.sun.com/javase/7/docs/api/javax/swing/SwingWorker.html propertyChange - status class SwingWorkerCompletionWaiter extends PropertyChangeListener { private JDialog dialog; public SwingWorkerCompletionWaiter(JDialog dialog) { this.dialog = dialog; } public void propertyChange(PropertyChangeEvent event) { if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.DONE == event.getNewValue()) { dialog.setVisible(false); dialog.dispose(); } } } JDialog dialog = new JDialog(owner, true); displays dialog until swingWorker.addPropertyChangeListener( swingWorker is done new SwingWorkerCompletionWaiter(dialog)); swingWorker.execute(); dialog.setVisible(true); http://java.sun.com/javase/7/docs/api/javax/swing/SwingWorker.html problems deadlock: two or more threads are waiting for each other livelock: two or more threads are too busy to communicating to do their actual work starvation: a thread can get access to a shared resource because other threads accessing the resource too frequently thread interference: two threads performing interleaving operations on a shared resource memory inconsistency: two threads have inconsistent views on what should be the same data Problems appear "randomly". Debugging essentially not possible. Unit tests do not work. Have to be fixed through reasoning only! memory consistency errors class Counter { private int c = 0; public void increment() { c++; not an atomic operation, is c = c +1 } public void show() { System.out.println(c); } } 1. Thread A: increment(). 2. Thread B: show() may print 0 or 1 does not nec. see the change caused by Thread A thread interference class Counter { private int c = 0; public void increment() { c++; not an atomic operation, } is c = c +1 public void decrement() { c--; not atomic } public int value() { return c; } } 1. Thread A: Retrieve c. 2. Thread B: Retrieve c. 3. Thread A: Increment retrieved value; result is 1. 4. Thread B: Decrement retrieved value; result is -1. 5. Thread A: Store result in c; c is now 1. 6. Thread B: Store result in c; c is now -1. tips avoid threads whenever possible when using threads multiply your time estimate by a factor of 5 to 10 synchronize sparsely but sufficiently -> ha ha ha! do as little work as possible within a synchronized region take advantage of higher level support (e.g. SwingWorker) whenever possible don't use thread priorities to solve synchronization/liveness problems test extensively on different machines under different loads and operating systems document thread safety there is no trial-and-error approach with thread. You really need to understand what's going on! these tips/slides barely scratching the surface. Read a lot more before implementing threads Joel test by Joel Spolsky: 1. Do you use source control? 2. Can you make a build in one step? 3. Do you make daily builds? 4. Do you have a bug database? 5. Do you fix bugs before writing new code? 6. Do you have an up-to-date schedule? 7. Do you have a spec? 8. Do programmers have quiet working conditions? 9. Do you use the best tools money can buy? 10. Do you have testers? 11. Do new candidates write code during their interview? 12. Do you do hallway usability testing? http://www.joelonsoftware.com/articles/fog0000000043.html mini tutorial public class StoppableThread extends Thread { private boolean stop = false; public void run() { while(!stop) { // work really hard } } public void requestStop() { stop = true; } } Effective Java, J. Bloch Does it work? If you are lucky it works most of the time... mini tutorial - solution public class StoppableThread extends Thread { private boolean stop = false; public void run() { while(!getStop()) { // work really hard } } private synchronized getStop() { return stop; } public synchronized void requestStop() { stop = true; } } Effective Java, J. Bloch no problems with memory inconsistency for boolean stop variable but ... ... no guarantee that update of stop variable is observed as intended without synchronized access! Programming in the Large Advanced Software Engineering course: topic: week: reading: CSSE2002/7023 Information theory 13 - quote A language that doesn't affect the way you think about programming, is not worth knowing Alan Perlis contents recap: list and iterators information theory lists & iterators linked list single linked list linear access time constant insertion/removal time List Node first next content next content next content null Iterator java.util iterates over the elements of a data structure public interface Iterator<E> hasNext() next content null next() next next content remove() Iterable java.lang allows an object to be the target of the "foreach" statement. public interface Iterable<T> iterator/iterable example public class StackIterator implements Iterator<String>, Iterable<String> { private String[] stack = new String[100]; private int index = 0, n = 0; public boolean hasNext() { return index < n; } n = #stack elements implementation of push, pop, ... skipped public String next() { if(index >= n) throw NoSuchElementException(); return stack[index++]; } Iterator<String> public void remove() { throw new UnsupportedOperationException(); } public Iterator<String> iterator() { return this; } } Iterable<String> information theory bits and guessing What's a BIT? => smallest unit of information: it's binary: e.g. true/false, on/off, yes/no, tails/heads Guess a number between 1 and 10. (e.g. is the number larger than 4? => yes/no) What's the optimal strategy and how much information(= guesses/bits) do you need in the worst case? => binary search, log2(10) = 3.3 => 4 guesses http://java.sun.com/docs/books/tutorial/java/concepts/inheritance.html binary search tree 1 2 3 4 5 6 7 8 9 10 n numbers <6 <4 <2 1 <5 <3 2 <9 3 4 <7 5 6 <10 <8 7 9 log2(n) 10 8 => log2(10) = 3.3 decisions on average => optimal strategy if all numbers are equally probable uncertainty n equally probable events, p = 1/n uncertainty u = log2(n) = -log2(1/n) • how many guesses until you are certain • if only one possible outcome: p=1 => u = log2(1) = 0 => no uncertainty = boring • 10000 options => u = log2(10000) = 13.3 average uncertainty avg(u) avg(u) = - 1/n * log2(1/n) = -log2(1/n) information entropy n possible events xi with different prob. p(xi) uncertainty u(xi) = -log2(p(xi)) average uncertainty avg(u) = Shannon's Information Entropy H p(x ) u(xi) = - p(x ) log2(p(xi)) H(X) = i i more entropy measure of boringness/redundancy of a system smallest number of bits per symbol required to describe a symbol stream (=>channel capacity) upper bound for lossless compression algorithms Shannon entropy for English = 0.6-1.3 (bpc) bits per character (bpc) There are other entropies (Gibbs, Boltzman, ...) entropy of literary styles Bible - King James Jane Austen - Sense and Sensibility, Northanger Abbey, Persuasion, Mansfield Park James Joyce - Ulysses, Portrait of the Artist as a Young Man => you can also do "language recognition" (zip different languages and compare file sizes) http://www.stat.purdue.edu/people/homepages/yiannis/PAPERS/english.ps.gz generating text First order letter model: ocroh hli rgwr nmielwis eu ll nbnesebya th eei alhenhttpa oobttva nah Second order letter model: on ie antsoutinys are t inctore st be s deamy achin d ilonasive tucoowe Third order letter model: in no ist lat whey cratict froure birs grocid pondenome of demonstures First order word model: representing and speedily is an good apt or come can different natural Second order word model: the head and in frontal attack on an english writer that the character huffman tree "this is an example of a huffman tree" http://en.wikipedia.org/wiki/Huffman_coding huffman encoding David A. Huffman, 1952, MIT entropy encoding algorithm lossless compression variable code length prefix code (no code is prefix of another code) theoretically best possible encoding for symbol stream (provided probabilities are exact and stable) for equiprobable symbols huffman code becomes block code (e.g. ASCII code) creation of Huffman tree is O(n*log(n)) http://www.siggraph.org/education/materials/HyperGraph/video/mpeg/mpegfaq/huffman_tutorial.html mini-tutorial Given: - 120 Students - a web server (limited capacity) - a submission deadline a 5pm Question: At what time do you submit? 1. at 5:00pm because nobody ever will submit at 5pm 2. at 5:30pm because everyone will have submitted by then 3. at 4:59pm because that is just before the deadline 4. at least 2h before the deadline because that is cool 5. doesn't matter because you don't believe in deadlines Hint! link to wisdom How To Become A Hacker http://catb.org/~esr/faqs/hacker-howto.html