🎧 New: AI-Generated Podcasts Turn your study notes into engaging audio conversations. Learn more

Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...

Full Transcript

Object-Oriented Software Development Principles Overview Dr. Bruno Schäffer © 2023 Chapter 1: Introduction Chapter 2: Principles Chapter 3: Class Libraries Chapter 4: Design Patterns Chapter 5: Testing Chapter 6: Refactoring Chapter 7: Frameworks Object-Oriented Software Developmen...

Object-Oriented Software Development Principles Overview Dr. Bruno Schäffer © 2023 Chapter 1: Introduction Chapter 2: Principles Chapter 3: Class Libraries Chapter 4: Design Patterns Chapter 5: Testing Chapter 6: Refactoring Chapter 7: Frameworks Object-Oriented Software Development – Principles 2 Contents • • • • • • Object vs. value Types and classes Subtypes and subclasses Interfaces and abstract classes Generic classes Aspect-oriented programming Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 3 Java Naming Conventions • • • • Classes • • Nouns, first letter of each word is capitalized (camel case) Example: ShadowedBox Interfaces • • Start with I, first letter of each internal word is capitalized (camel case) Example: IMouseListener Methods • • First letter lowercase, first letter of each internal word is capitalized (camel case) Example: setCoordinate Constants • • All uppercase, words are separated by “_” (screaming snake case) Example: MAX_ITEMS Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 4 Object vs. Value - Types of Equality Reference Equality = ObjectReference1 ObjectReference2 Teacher lastName: "Mathison" subject: "Theory of Everything" Identifier Equality Teacher id: 255 lastName: "Mathison" subject: "Theory of Everything" = Teacher id: 255 lastName: "Mathison" subject: "Theory of Nothing" Structural Equality Address street: "Main Avenue 42" zipCode: "8001" city: "Napoli" Dr. Bruno Schäffer © 2023 = Address street: "Main Avenue 42" zipCode: "8001" city: "Napoli" Object-Oriented Software Development – Principles 5 Object vs. Value Value Object Models entities from a domain Represents a descriptive aspect of a domain Identity is explicitly defined (identifier identity) Identity is implicitly defined (structural identity) Lifecycle (creation, mutation, deletion) No lifecycle Can exist independently Only exists as part of an object Mutable state Immutable state Can be shared ➜ mind the side effects State can only be interpreted (different representations) Can be safely shared Examples account, payment, person Dr. Bruno Schäffer © 2023 integer, float, character, monetary value, account number, color, date, address Object-Oriented Software Development – Principles 6 Object vs. Value • • • A type has either object or value semantics • Implementation has to follow semantics! Value semantics has to provide immutability • Advantages: simple, easy sharing und thread-safeness Java is not consistent with values • • Class "Integer" is implemented with value semantics • • Instances of Integer are immutable BigInteger, BigDecimal etc. have value semantics, too Class "Date" is implemented with object semantics • • • Mutable ➜ side effects Date is deprecated and (partially) replaced by Calendar Java 8 introduced a sensible Date implementation ➜ LocalDate, LocalTime, LocalDateTime - Inspired by Joda-Time Value semantics Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 7 Sharing is not always obvious public class Rectangle { private Point origin private Point corner Groovy public Rectangle(Point origin, Point corner) { this.origin = origin; this.corner = corner } public Point getOrigin() { return origin } public Point getCorner() { return corner } public String toString() { return “((${origin.@x},${origin.@y}),(${corner.@x},${corner.@y}))" } } Rectangle r1 = new Rectangle(new Point(0, 0), new Point(1, 1)) Rectangle r2 = new Rectangle(r1.getOrigin(), r1.getCorner()) assert r1.toString() == "((0,0),(1,1))" assert r2.toString() == "((0,0),(1,1))" r2.getCorner().move(5, 5) assert r1.toString() == "((0,0),(5,5))" assert r2.toString() == "((0,0),(5,5))" Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 8 How to implement an immutable class in Java? • • • • • No mutators • • State can only be retrieved but not changed Alternatively use copy on write: • All mutating operations create a copy of the receiver, apply changes to it and return the copy Class must not be extensible • Use public final class … All fields must be final • Prohibit changes after initialization All fields must be private • Prohibit changes to final fields, e.g. non-zero arrays Exclusive access to mutable components • • References to mutable objects are not available to other clients Defensive copies of client-provided objects Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 9 Java Records • • • • Java Record is an immutable container of a set of fields • Introduced in Java 16 Compiler generates all the necessary boilerplate code • Constructor, equals, hashcode, getters Record may additionally contain: • • Constructors and instance methods Static fields and methods Some IDEs can also generate this boilerplate code for a traditional class but: • • • Generated code may obscure the purpose of the class Reader is challenged to verify the correctness Changes necessitate re-generation of code Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 10 Immutable Java Class vs. Java Record Traditional immutable Java Class public final class Point { private final int x; private final int y; public Point(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public int getY() { return y; } public boolean equals(Object o) { … } public int hashCode() { … } public String toString() { … } } Java Record public record Point (int x, int y) {} Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 11 Object vs. Value – Takeaways Class has either object or value semantics Decide explicitly about object/value semantics Immutable objects have no side effects Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 12 Types and Classes • • Type: abstract description of properties of a set of objects Class: implementation of a type Object ➜ Class ➜ Interface ➜ Type Static type checking • • • • • Class/interface is considered a type Provided in languages such as Java, C++, … Assignment compatibility only along the type hierarchy Upcasting – downcasting Explicit typing improves readability, reliability and efficiency Dr. Bruno Schäffer © 2023 Dynamic type checking • • • • • • Protocol of an object implicitly defines the type • Protocol is the set of messages understood by an object Provided in languages such as JavaScript, Groovy More flexible than static type checking Assignment compatibility is not restricted by the type hierarchy Implicit typing reduces readability, reliability and efficiency Type inference can deduce types and provide implicit static typing Object-Oriented Software Development – Principles 13 Prototypes – JavaScript • • • Some languages get by without classes, e.g. JavaScript Prototypes and delegation replace classes and inheritance Example: //constructor definitions JavaScript function Student(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; Student.prototype.toString = function () { return this.firstName + " " + this.lastName; } } function Teacher(lastName, subject) { this.lastName = lastName; this.subject = subject; Teacher.prototype.toString = function () { return this.lastName + ": " + this.subject; } } Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 14 Prototypes – JavaScript var student = new Student("Jonathan", “Pine"); var teacher = new Teacher("Mathison", "Theory of Everything"); JavaScript var person = new Object(); Object.setPrototypeOf(person, student); console.log(person.toString()); // --> Jonathan Pine Object.setPrototypeOf(person, teacher); console.log(person.toString()); // --> Mathison: Theory of Everything teacher person prototype lastName: “Mathison” subject: “Theory of Everything” prototype Teacher constructor toString prototype Object student firstName: “Jonathan” lastName: “Pine” prototype Dr. Bruno Schäffer © 2023 Student constructor toString prototype constructor … prototype Object-Oriented Software Development – Principles 15 Types and Classes – Takeaways Class is a type specification and an implementation Prototypes and delegation are an alternative to classes Static type checking: readability, reliability and efficiency Dynamic type checking: flexibility Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 16 Subtype – Subclass Subtype Subclass Is-a-Relationship Has-a-Relationship T‘ is a subtype of T if T-objects can always be replaced by T‘-objects T’ is a subclass of T if T’ is derived from T but T-objects cannot be replaced by T’-objects Example from the Smalltalk class library: Collection ! Set SequenceableCollection Bag ! Dictionary OrderedCollection ! SortedCollection Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 17 Principle of Substitutability Subtype must fulfill the Principle of Substitutability (Liskov Substitution Principle) • • • Subtype must provide at least the interface of its base type • • Restrictions are not permitted! Access privileges may only be the same or weaker Pre- and postconditions • • Preconditions must not be narrowed by a subtype Postconditions must not be widened by a subtype Exceptions • • Subtypes must not throw new exceptions Unless: exception is a subtype of the exception thrown by the base type Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 18 Subtyping vs. Subclassing • Subtyping • • • • • Interface inheritance Protocol is extended (restriction violates subtyping) • • Rectangle Inheritance defines an “is-a relationship” • Adheres to principle of substitutability! ! Protocols of base class and subclass are very similar Window bounds Subclassing • • Component Implementation inheritance Little compliance between base class and subclass • • Base class is just a minor implementation detail of the subclass Code reuse Subclassing defines a “has-a relationship” Composition should be used instead • Rectangle ! Window Makes implementation replaceable Distinction between subtype and subclass is essential in software design Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 19 Type Checking • Static type checking • • • Type errors are usually detected at compile time Enables the generation of efficient target code (e.g. byte code) Type errors can still occur at run-time (e.g. by type casting) Map map = new HashMap(); map.abs(); • Dynamic type checking • • Flexibility at the expense of readability, reliability, and efficiency Developer is responsible for invoking valid methods def aList = new ArrayList<Date>(); aList.abs(); • Compiler detects invalid method call Groovy „MissingMethodException“ at run-time Dynamic type checking ≠ weak type checking Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 20 Type Checking • • • Static type checking • • Static type checking ensures that a message is understood by an object Dynamic binding selects the appropriate method based on the dynamic type of the receiver Static type checking • • • dynamic binding inheritance An object of type T’ can be assigned to a variable of static type T if T’ is derived from T Assignment compatibility is restricted by type (inheritance) hierarchy Dynamic binding is only possible along the type hierarchy Type inference • • • • Deriving the type of a variable from the context (e.g. Swift, TypeScript, Groovy, Java) Developer saves on typing Enables static type checking Readability? Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 21 Type Checking • Dynamic type checking (dynamic typing) • • • • Allows for dynamic binding outside of the type hierarchy Criterion: does an object understand a message? Smalltalk developers: “True Dynamic Binding” Groovy developers: “Duck Typing” • • Looks like a duck, walks like a duck, quacks like a duck ➜ Duck We duck types, not responsibilities Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 22 Type Checking • Static type checking WinComponent draw WinButton draw • MacComponent draw MacButton draw WinComponent wc; MacComponent mc; WinButton wb = new WinButton(); wc = wb; mc = wb; //OK //Compile time error! Dynamic type checking WinComponent draw WinButton draw Dr. Bruno Schäffer © 2023 Groovy MacComponent draw def wc def mc def wb = new WinButton() MacButton draw wc = wb //OK mc = wb //OK mc.draw() //WinButton.draw() Object-Oriented Software Development – Principles 23 Covariance and Contravariance Is the principle of substitutability applicable to method parameters in overriding methods? Object equals(Object) ComparableObject isGreater(Object) Dr. Bruno Schäffer © 2023 List addElement(Object) SortedList addElement(ComparableObject) ? List list = new SortedList(); list.addElement(new Object()); Object-Oriented Software Development – Principles 24 Covariance and Contravariance • Covariance: • • • • • Type of a method parameter is narrowed in overriding method Principle of substitutability applied to method arguments Useful, but expensive to guarantee type safety at compile time! Java (and most other statically typed oo languages) do not support covariance Exception: Java Arrays Object[] oa = new String[10]; oa[0] = new Object(); • „ArrayStoreException“ at run-time Since Java 5 the return type of an overriding method may be narrowed (covariant return type) public class A { public List getList() { … } } public class B extends A { @Override public ArrayList getList { … } } • Contravariance: • • • Type of a method parameter is widened in overriding method Contravariant method parameter does not override in Java (just overloading) Contravariant return type not allowed in Java Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 25 Types of Inheritance • Specialization ! • Derive concrete subclass from concrete base class • Combination ! • Window Multiple inheritance Teacher Student FloatingWindow • TeachingAssistant Specification ! • Concrete subclass implements abstract base class GraphicalObject Box • • Construction " • Implementation inheritance HashTable Restriction " • Subclass restricts the base class interface SymbolTable Set Dictionary Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 26 Subtyping Pitfalls Figure Figure Rectangle Square setSize(int x, int y) getX() getY() Square setSize(int x, int y) Dr. Bruno Schäffer © 2023 setSize(int x, int y) getX() getY() Rectangle setSize(int x, int y) Object-Oriented Software Development – Principles 27 Subtyping Pitfalls Figure Square setSize(int x, int y) getX() getY() Rectangle setSize(int x, int y) getX() getY() Figure Square quadrilateral setSize(int x, int y) getX() getY() Dr. Bruno Schäffer © 2023 Rectangle quadrilateral setSize(int x, int y) getX() getY() Quadrilateral x y setSize(int x, int y) getX() getY() Object-Oriented Software Development – Principles 28 Multiple Inheritance • Is multiple inheritance advantageous? • • • • • More complex language (syntax and semantics) More complex class hierarchies Often used instead of composition Tends to mess up the class hierarchy (postponing clean redesign) Naming conflicts Collection Hashtable Collection Hashtable ➜ Set • Resolution of naming conflicts • • • Inheritance sequence (A before B) Set contents A B m m Explicit qualification (A::m()) Renaming (rename A::m as Am()) C m Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 29 Multiple Inheritance • Multiple inheritance from the same class? (Fork-Join or Diamond Problem) Box FilledBox ShadowedBox FilledShadowedBox • • C++: FilledShadowedBox has two Box objects Virtual inheritance from Box: • A single Box object will be shared by all derived classes class class class class • Box{}; FilledBox: public virtual Box{}; ShadowedBox: public virtual Box{}; FilledShadowedBox: public FilledBox{}, public ShadowedBox{}; C++ Virtual inheritance is conceptually „expensive“ ➜ Requires assumptions on future derived classes Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 30 Mixin Classes • • • Classes for adding additional behavior • Implementation: • Static type checking • • Do not define any state May contain both abstract and concrete methods 0-1 primary base classes and 0-n mixin classes • Mixin classes for defining protocols independent of the inheritance ➜ Adding protocols ➜ Implementation is factorized in mixin class • Mixin methods can be overridden Java 8 provides default methods in interfaces Groovy (since 2.4.4) provides traits for behavior composition Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 31 Design for Inheritance • • • • • Inheritance violates encapsulation • • • Subclass needs to know implementation details Members (fields) should be private by default Judiciously grant access to subclasses by using protected access Classes have to rely on the sanity of base classes and subclasses Constructors must not invoke overridable methods Test a class' suitability for inheritance by writing subclasses! Prohibit subclassing if class cannot be safely subclassed Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 32 Restricting the Inheritance Interface • Prevent method overriding • Java: keyword “final” • Excludes alternative method implementations • • Turns off dynamic binding Example: export restrictions in cryptographic libraries • • Enables optimizations by the compiler or run-time system Prevent derived classes • • • • Java: keyword “final” All methods are final in a final class Excludes alternative class implementations Prohibit mutable derivations of immutable classes Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 33 Restricting the Inheritance Interface • • Prior to Java 15 inheritance was either all or nothing Sealed interfaces / classes control inheritance in a more fine granular way • • Define permitted subtypes in interface / class Permitted subtypes become part of the client contract! public sealed interface IShape permits Circle, Rectangle { float area(); } public final class Rectangle implements IShape { private Point origin; private Point corner; public Point getOrigin() { … } public Point getCorner() { … } public float area() { … } } • public final class Circle implements IShape { private Point center; private int radius; public Point getCenter() { … } public int getRadius() { … } public float area() { … } } Clients of a sealed interface / class may: • • Use the abstraction Deal with derived implementations safely (e.g. in a switch statement) Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 34 Subtypes and Subclasses – Takeaways Use subtyping and minimize implementation inheritance Design a class for inheritance or disable it Mind covariance when designing a subtype Dr. Bruno Schäffer © 2023 Object-Oriented Software Development – Principles 35

Use Quizgecko on...
Browser
Browser