Summary

This document is a presentation on object-oriented software development, specifically focusing on class libraries. It covers topics like traditional procedural libraries, class libraries, design patterns, testing, refactoring, and frameworks in Java, explaining their roles and functionality.

Full Transcript

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

Object-Oriented Software Development Class Libraries Overview Chapter 1: Introduction Chapter 2: Principles Chapter 3: Class Libraries Chapter 4: Design Patterns Chapter 5: Testing Chapter 6: Refactoring Chapter 7: Frameworks ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 2 Contents • • • • Class libraries Java class library Case study: Java collection classes Structuring of class libraries ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 3 Traditional (Procedural) Libraries • • • Programming languages provide only limited functionality Additional functionality: libraries rather than language extensions • • • Math functions, input/output, etc. Language and library are tightly coupled From subroutine collections to modules Challenges • • • Abstractions Factorization Reusability and adaptability ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 4 Class Libraries • • • Objects and classes • • Synthesis of state and behavior Abstractions and information hiding enable loose coupling Inheritance and dynamic binding • • • • • Adaptation to new requirements Abstract classes ➜ factorization, generalization, and speci cation Interfaces ➜ factorization, type speci cation Relocating control ow from application into library Enables exible design of complex problems Class hierarchies and object structures • Modeling of problem domains Object-Oriented Software Development – Class Libraries fi fi fl ff fl Dr. Bruno Schä er © 2023 5 Open-Closed Principle • Open-closed principle (B. Meyer) Class is open for extension Class is closed for modi cation • • • SOLID Principles Changing requirements do not necessitate code changes, rather Add new code in a derived class Contribute a new implementation of an interface • • Open-Closed has to be chosen strategically Designer has to decide which aspects are open to changes Abstraction is the key to adaptability • • Object-Oriented Software Development – Class Libraries fi ff Dr. Bruno Schä er © 2023 6 Open-Closed Principle • Example • • ShapePainter is open to any kind of Shape ShapePainter is closed to paint strategy (cannot be adapted by client or derived class) interface IShape { void draw(Graphics gc); } public class ShapePainter { private List<IShape> shapeList = new ArrayList<>(); public void addShape(IShape shape) { shapeList.add(shape); } public void paintAll(Graphics gc) { shapeList.forEach( (IShape shape) -> shape.draw(gc) ); } } ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 7 Impact of Class Libraries • • • Starting point for software development • • Comprehensiveness and quality de ne development advantage Reuse by instantiation Advantages of using class libraries • • • • Less in-house development and leveraging expert know-how Less testing e ort and broader test coverage Less maintenance and improvements for free Own code becomes mainstream Frameworks go beyond class libraries • • • Domain speci c, but more abstract Embody control ow (application ➜ framework) Reuse by inheritance / composition Object-Oriented Software Development – Class Libraries fi fl ff fi ff Dr. Bruno Schä er © 2023 8 Java Class Library – Evolution Packages Classes 7000 6005 6002 5250 3793 3500 2991 4024 4240 4410 4433 4545 4569 3279 1842 1520 1750 212 8 504 23 59 76 135 165 0 Java 1.0 Java 1.1 Java 1.2 Java 1.3 Java 1.4 Java 5.0 (1995) (1997) (1999) (2000) (2002) (2004) ff Dr. Bruno Schä er © 2023 203 209 217 315 314 223 225 223 224 Java 6 (2006) Java 7 (2011) Java 8 (2014) Java 9 (2017) Java 10 (2018) Java 11 (2018) Java 12 (2019) Java 13 (2019) Java 14 (2020) Object-Oriented Software Development – Class Libraries 9 The Class „Object“ • • • • „Pivotal“ class in the Java class library All classes are derived from Object No abstract methods ➜ easy to reuse Important methods • • • • • • clone Byte-wise copy of objects (shallow copy) equals Byte-wise comparison of objects hashCode Compute hash value of an object ( nalize) Invoked prior to releasing an object getClass Returns class of an object toString Converts an object to its string representation ff fi Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 10 Comparing Objects • • The equals contract: • • • • • Re exive: x.equals(x) == true Symmetric: x.equals(y) == y.equals(x) Transitive: x.equals(y) == y.equals(z) == x.equals(z) Consistent: x.equals(y) == true, even repeatedly without changing x, y Null-Reference: x.equals(null) == false Equals contract cannot be ful lled if: • • Base class overrides equals and Derived class adds state which must be used for comparing! Object-Oriented Software Development – Class Libraries fi ff fl Dr. Bruno Schä er © 2023 11 Comparing Objects – Example public class Box { private Point origin; private Point corner; public Box(Point origin, Point corner) { //… } public boolean equals(Object o) { if (!(o instanceof Box)) return false; Box b = (Box)o; return origin.equals(b.origin) && corner.equals(b.corner); } //… } public class FilledBox extends Box { private Color color; public FilledBox(Point origin, Point corner, Color color) { super(origin, corner); //… } //… } ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 12 Comparing Objects – Example • How to override equals? //Violates symmetry public boolean equals(Object o) { if (!(o instanceof FilledBox)) return false; FilledBox fb = (FilledBox) o; return super.equals(o) && color == fb.color; } //Violates transitivity public boolean equals(Object o) { if (!(o instanceof FilledBox)) return o.equals(this); FilledBox fb = (FilledBox) o; return super.equals(o) && color == fb.color; } ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 13 Comparing Objects • Recipe for overriding equals in Java • Identity check (optimization) • Check for type equality (using instanceof) • Cast to expected type • Compare attributes (== for base types, equals for references) • • • Deal with null pointers Override hashCode! • hashCode contract speci es that equal objects must have equal hash codes Using getClass instead of instanceof? • Ignores principle of substitutability! Object-Oriented Software Development – Class Libraries fi ff Dr. Bruno Schä er © 2023 14 Collection Classes • • Maintaining collections of objects Java 1.0 implementation (Vector, Hashtable, ...) • • • • Simple but in exible design • • Hardly any abstractions Di cult to provide alternative implementations Limited functionality Moderate performance (e.g. thread-safe by default) Java 1.2 implementation • Simple and exible design • • Elaborate abstractions Easy to provide alternative implementations • Comprehensive (optional) functionality • Thread-safe, immutable, sortable, views, iterators • Pay as you go: only pay for what you really need • Nice example of object-oriented design for class libraries (and frameworks) fl fl ff ffi Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 15 Collection Classes – Overview • Interfaces • De ne minimal functionality • Some methods are optional • De ne type hierarchy and compatibility • • • • • • Not always a subtype relation! Alternative: smaller and more interfaces Functional interfaces Operations on collections/streams (de ned in java.util.function) Abstract classes • • • Foundation for implementation Only a few abstract methods have to be implemented by subclass Concrete methods may be replaced by more e cient implementations Concrete classes • • One or more implementations per interface Implementations di er by performance Object-Oriented Software Development – Class Libraries ffi fi ff ff fi fi Dr. Bruno Schä er © 2023 16 Collections – Interfaces • Collection • Most common set of objects • Does not specify: • Duplicity, sequence, contained objects • No (directly) implementing classes • No subtypes • Collection Reason: optional methods • No duplicates allowed • • ListSequence de ned • Map • Contains key-value tuples • • SortedSet • Set with sort order • SortedMap Set fi ff Dr. Bruno Schä er © 2023 Set SortedSet List Map SortedMap Object-Oriented Software Development – Class Libraries 17 Collections – Interfaces public interface Collection<E> { // Basic Operations int size(); boolean isEmpty(); boolean contains(Object element); boolean add(E element); // Optional boolean remove(Object element); // Optional Iterator<E> iterator(); // Bulk operations boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); boolean removeAll(Collection<?> c); boolean retainAll(Collection<?> c); void clear(); // // // // Optional Optional Optional Optional // Array operations Object[] toArray(); <T> T[] toArray(T a[]); // Stream operations Stream<E> stream; Stream<E> parallelStream; } ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 18 Collections – Interfaces & Abstract Classes Collection AbstractCollection Set AbstractSet List SortedSet ff Dr. Bruno Schä er © 2023 AbstractList AbstractSequentialList Object-Oriented Software Development – Class Libraries 19 Collections – Concrete Classes Collection AbstractCollection Set AbstractSet List AbstractList Map SortedSet AbstractMap TreeSet HashSet AbstractSequentialList SortedMap ArrayList TreeMap HashMap LinkedList ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 20 Collections – Separation of Concerns • • Iterate • • • Iterator may (optionally) remove elements, but not add any elements Fail-fast: iterator aborts immediately on illegal operations Sorting • • • Iterating on elements of a collection is the responsibility of an iterator (and not of a collection) Interface Comparable • • • • Natural order is de ned by the interface Comparable All “base type classes” implement Comparable Interface Comparator Alternative if Comparable does not de ne the required order Delegating comparison to a separate class (strategy design pattern) Creating views on collections • • Views: e.g. unmodi able, synchronized, subset, … see class Collections Object-Oriented Software Development – Class Libraries fi fi fi ff Dr. Bruno Schä er © 2023 21 Class Library Design – Takeaways Interfaces specify types, abstract classes help implementations Subtyping contract cannot always be kept Pay as you go ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 22 Separation of Concerns – External vs. Internal Iteration • • • Separation of concerns • • • Break up implementation into distinct sections with minimal overlap Each section focuses on a single concern Concerns are orthogonal Iteration: separation of concerns is limited with Java 7 (or earlier) Collections prior to Java 8 provide only external iteration • • • Elements of a collection are sequentially accessed through an iterator Iteration and operation on elements are intermingled (how and what) Threaded (parallel) operations are expensive to implement List<Integer> intList = Arrays.asList(0, 1, 1, 2, 3, 5, 8, 13, 21); Iterator<Integer> iter = intList.iterator(); while (iter.hasNext()) { int n = iter.next(); if (n % 2 == 0) { System.out.println(n); } } ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 23 Separation of Concerns – External vs. Internal Iteration • • Internal iteration makes a clean separation of concerns • • How: collection is responsible for sequential access to its elements What: client just provides the operation to be performed Java 8 adds forEach method • Default implementation in interface: • Allowed for extending the Iterable interface without breaking the API • Operation is speci ed as a lambda expression public void forEach(Consumer<? super E> consumer); @FunctionalInterface public interface Consumer<T> { public void accept(T t); } List<Integer> intList = Arrays.asList(0, 1, 1, 2, 3, 5, 8, 13, 21); intList.forEach(n -> { if (n % 2 == 0) System.out.println(n); } ); fi ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 24 Separation of Concerns – External vs. Internal Iteration External Iteration hasNe ff t n e lem Iterator lse true/fa next() Collection Iteration Application Dr. Bruno Schä er © 2023 xt() e Object-Oriented Software Development – Class Libraries 25 Separation of Concerns – External vs. Internal Iteration External Iteration Internal Iteration operat hasNe ff Iterator Collection e t n e lem Application lse true/fa next() Collection Iteration Application Dr. Bruno Schä er © 2023 xt() Iteration ion result Object-Oriented Software Development – Class Libraries 25 Internal Iteration with Streams • • Streams are the Java 8 style to operate on the elements of a collection Principles: • • • • Stream operations work on elements of a collection Lambdas make it easy to de ne functionality and pass it to a stream operation Most stream operations return a stream ➜ method chaining Leads to a declarative (functional) rather than procedural approach public class Person { public enum Gender {FEMALE, …}; private Gender gender; private String firstName; private String lastName; private LocalDate birthDay; List<Person> personList = … personList.stream() .filter( person -> person.getGender == Person.Gender.FEMALE) .mapToInt(Person::getAge) .average() .getAsDouble(); public Gender getGender() … public int getAge() … } Object-Oriented Software Development – Class Libraries fi ff Dr. Bruno Schä er © 2023 26 Separation of Concerns – Class Design Focus and limit object responsibilities Controller Domain Persistence HTTP/REST conventions Conversion from/to JSON Basic validations Application logic Domain logic Object-relational mapping  ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 27 Separation of Concerns – Class Design Class trying to meet requirements of all layers ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 28 Separation of Concerns – Class Design Class trying to meet requirements of all layers public class Person private int id; private String firstName; private String lastName; private LocalDate dateOfBirth; private Gender gender; } ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 28 Separation of Concerns – Class Design Class trying to meet requirements of all layers public class Person @JsonProperty("id") private int id; @JsonProperty("firstName") private String firstName; @JsonProperty("lastName") @NotNull private String lastName; @JsonProperty("dateOfBirth") private LocalDate dateOfBirth; @JsonProperty("gender") private Gender gender; } ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 28 Separation of Concerns – Class Design Class trying to meet requirements of all layers public class Person @JsonProperty("id") private int id; @JsonProperty("firstName") private String firstName; @JsonProperty("lastName") @NotNull private String lastName; @JsonProperty("dateOfBirth") private LocalDate dateOfBirth; @JsonProperty("gender") private Gender gender; @JsonIgnore int getAge() { return dateOfBirth.until(LocalDate.now(), ChronoUnits.YEARS); } } ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 28 Separation of Concerns – Class Design Class trying to meet requirements of all layers @Entity @Table(name="Person") public class Person @JsonProperty("id") @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @JsonProperty("firstName") private String firstName; @JsonProperty("lastName") @NotNull private String lastName; @JsonProperty("dateOfBirth") private LocalDate dateOfBirth; @JsonProperty("gender") @Enumerated(EnumType.STRING) private Gender gender; @JsonIgnore int getAge() { return dateOfBirth.until(LocalDate.now(), ChronoUnits.YEARS); } } ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 28 Separation of Concerns – Class Design Class trying to meet requirements of all layers @Entity @Table(name="Person") public class Person @JsonProperty("id") @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @JsonProperty("firstName") private String firstName; @JsonProperty("lastName") @NotNull private String lastName; @JsonProperty("dateOfBirth") private LocalDate dateOfBirth; @JsonProperty("gender") @Enumerated(EnumType.STRING) private Gender gender; @JsonIgnore int getAge() { return dateOfBirth.until(LocalDate.now(), ChronoUnits.YEARS); } } ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 28 Separation of Concerns – Class Design • • • • • Implement classes according to: • • Functional requirements (business domain) Technical requirements (technology stack) Data Transfer Object (DTO) • Responsible for serializing/deserializing Domain Object • Provides business logic (in cooperation with domain services) Entity Object • Persistence Object mapping for converting objects between di erent representations • • Mapping implementation should not be part of the object Libraries can make this pretty easy Object-Oriented Software Development – Class Libraries ff ff Dr. Bruno Schä er © 2023 29 Separation of Concerns – Class Design ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 30 Separation of Concerns – Class Design public class Person private int id; private String firstName; private String lastName; private LocalDate dateOfBirth; private Gender gender; int getAge() { return dateOfBirth.until(LocalDate.now(), ChronoUnits.YEARS); } } ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 30 Separation of Concerns – Class Design public class PersonDTO @JsonProperty("id") private int id; @JsonProperty("firstName") private String firstName; @JsonProperty("lastName") @NotNull private String lastName; @JsonProperty("dateOfBirth") private LocalDate dateOfBirth; @JsonProperty("gender") private Gender gender; } ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 30 Separation of Concerns – Class Design @Entity @Table(name="Person") public class PersonEntity @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String firstName; private String lastName; private LocalDate dateOfBirth; @Enumerated(EnumType.STRING) private Gender gender; } ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 30 API Design • • How to make an API exible and readable? Example: Splitter for breaking up a string into substrings • First take: constructor combinations public class Splitter public Splitter(String source, char separator, boolean trimResults, int limit, boolean omitEmptyString); //what about fixedLength, patternSeparator, //regularExpressionSeparator, key/value splitter etc. ? public Iterable<String> split(); } • Second take: constructor(s) and setters public class Splitter public Splitter(String source); public void setSeparator(char separator); public void setTrimResults(boolean trim); public void setLimit(int limit); public Iterable<String> split(); } Object-Oriented Software Development – Class Libraries fl ff Dr. Bruno Schä er © 2023 31 API Design • Fluent API • Uses method chaining extensively public class Splitter public static Splitter on(char separator); public Splitter omitEmptyStrings(); public Splitter trimResults(); //... public Iterable<String> split(final CharSequence sequence); } • Usage: Splitter.on(‘,’).trimResults().omitEmptyStrings().split(“x, y, z,, v”); Try to tell a story with a Fluent API ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 32 API Design • The Fest library (fest-re ect) comprises a uent re ection API public class Person private final String firstName; private final String lastName; Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } String getName(char separator) { //… } } Person person = constructor() .withParameterTypes(String.class, String.class) .in(Person.class) .newInstance(“John”, “Doe”); String firstName = field(“firstName”).ofType(String.class).in(person).get(); String name = method(“getName”).withParameterTypes(char.class).in(person).invoke(‘ ‘); Object-Oriented Software Development – Class Libraries fl fl fl ff Dr. Bruno Schä er © 2023 33 Separation of Concerns – Takeaways Breaking up monolithic design Orthogonal reuse of building blocks Flexibility and readability with uent APIs Object-Oriented Software Development – Class Libraries fl ff Dr. Bruno Schä er © 2023 34 Structuring of Class Libraries • • • • Dividing a system into subsystems improves: • • Comprehensibility Reusability • Using/adapting parts, without knowing or forced to bundle the rest Layering principle • • Horizontal layering of a system (technical slicing) Higher layers depend on lower layers (but not vice versa!) Subsystem can be built by one or more packages • • Packages (like classes) should have strong cohesion and loose coupling Prefer abstract over concrete coupling Packages are too ne-grained for large software systems! Object-Oriented Software Development – Class Libraries fi ff Dr. Bruno Schä er © 2023 35 Structuring of Class Libraries • No dedicated entry points ➜ tight coupling Application Client Library Package A Package B A1 A2 A3 ff Dr. Bruno Schä er © 2023 B1 Package C B2 C1 C2 C3 C4 Object-Oriented Software Development – Class Libraries 36 Structuring of Class Libraries • Dedicated entry points ➜ loose coupling Application Client Library Package A A1 A2 A3 Package B B1 ff Dr. Bruno Schä er © 2023 Package C B2 C1 C2 C3 C4 Object-Oriented Software Development – Class Libraries 37 JDK Modules Picture Reference ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 38 Minimizing Dependencies • • • Dependency management • Minimizing dependencies is crucial, but can be a tough job! • Manage dependencies on component level (rather than among classes) • Component may be a package or a module (with Java 9) • Tool support is indispensable (preferably as part of the automatic build ➜ architecture tness functions) Cyclic dependencies are treacherous • • • • • • • Components cannot be viewed in isolation anymore Changes trigger unforeseen side e ects Cyclic dependencies across domains or layers are malicious All components in a cycle have to be bundled for delivery Classes in a cycle may have several roles and therefore tend to be bigger Testing of components with cycles is challenging Cycles tend to be "black holes" - they keep attracting ever more classes Interfaces may help to break cycles Object-Oriented Software Development – Class Libraries fi ff ff Dr. Bruno Schä er © 2023 39 Minimizing Dependencies ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 40 Minimizing Dependencies Accounting Account ff Dr. Bruno Schä er © 2023 Partner Holder Object-Oriented Software Development – Class Libraries 40 Minimizing Dependencies Accounting Partner Account Holder Accounting Partner Account Holder Interfaces «interface» IAccount «interface» IHolder ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 40 Class Libraries – Limitations • • Complexity • • • Class libraries tend to be large Relationships among classes & inheritance (type hierarchy) How to (re-)use it by instance creation & subtyping? Control ow challenge • Applications using class libraries are still responsible for the control • Implementing the control ow can be tough • Applications may implement similar control ow in a di erent way • • ow Duplication of e ort makes application maintenance expensive Approaches for mastering the control ow • Lambdas (micro level) • Move local control ow from a client to a class (e.g. internal iteration) • Frameworks (macro level) • Move global control ow from applications to an application framework Object-Oriented Software Development – Class Libraries fl ff fl fl fl fl fl ff ff fl Dr. Bruno Schä er © 2023 41 Development of Class Libraries • • Good design evolves iteratively • • Starting over is sometimes required too (explorative programming) Example: AWT 1.0 ➜ AWT 1.1 ➜ Swing ➜ JavaFX Challenges • • • When to release the rst version? • Public APIs are a serious commitment! Class libraries mature through widespread usage • • Class libraries and applications a ect one another Changes may have a major impact on clients! How to absorb the impact of changes? • • • Small interfaces (see also: Interface Segregation Principle [SOLID]) Non-breaking API changes (e.g. optional parameters, method overloading, default methods) Anti-corruption layer on client side Object-Oriented Software Development – Class Libraries ff fi ff Dr. Bruno Schä er © 2023 42 Summary • • • • Class libraries leverage software development • • Programming languages can stay focused on core features Loose collection of classes is not su cient Object structures are important • • A single object does not realize an application Design patterns are guidelines for object structures Interaction among classes / objects is crucial • • Delegation of tasks Abstract interaction ➜ framework Components + con guration enable reuse • Inheritance is static and expensive (heavyweight) Object-Oriented Software Development – Class Libraries ffi fi ff Dr. Bruno Schä er © 2023 43 Literature • • • • • • Java: https://www.oracle.com/java/index.html D. Flanagan: Java in a Nutshell J. Bloch: E ective Java Java Tutorial: http://docs.oracle.com/javase/tutorial/ Lambda Tutorial: http://www.angelikalanger.com/Lambdas/Lambdas.pdf Java Modules: https://www.oracle.com/corporate/features/understanding-java-9-modules.html ff ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 44 E ective Java ff ff Dr. Bruno Schä er © 2023 Object-Oriented Software Development – Class Libraries 45

Use Quizgecko on...
Browser
Browser