1 / 77

Object Design Basics

Object Design Basics. Java’s constructs for Objects. Interfaces Abstract classes Classes Subclasses Inner classes Anonymous classes. Nested classes. Static member classes. Non-static member classes. Anonymous classes. Local classes. Inner classes. Which member class to use.

keona
Download Presentation

Object Design Basics

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Object Design Basics Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  2. Java’s constructs for Objects • Interfaces • Abstract classes • Classes • Subclasses • Inner classes • Anonymous classes Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  3. Nested classes • Static member classes. • Non-static member classes. • Anonymous classes. • Local classes. Inner classes Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  4. Which member class to use • If a nested class needs to be visible outside of a single method, or its too long inside of the method, use a private member class. • If each instance of the member class needs a reference to its enclosing instance, make it private non-static class. • Otherwise make it static. • Use anonymous classes for those one-time-use classes. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  5. Exceptions • Built-in • User defined • Use of finally clause Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  6. try { int i = 0; while(true) { a[i++].f(); } } catch(ArrayIndexOutOfBoundsException e){ } Use exceptions only for exceptional conditions!!! Do not use them for control flow of normal situations. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  7. finally try{ … } catch( ….) { … } catch( ….) { … } … finally { …. } Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  8. finally • Code in finally is executes after try terminates either normally, abnormally or via return or break. • Commonly use to release resources held by the object, I.e. to tell the garbage collector about an unused object. • But: there is no guarantee that those statements will get executed promptly. • So: • Nothing time critical should be done in them. • Never depend on a finalizer to update critical persistent state. • Even better: Do not rely on finally clause. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  9. finally • What to do: • Provide an explicit termination method and require clients to invoke it when needed resources are not longer needed. • This method records that object is no longer valid, so if any other method in the instance gets invoked an IllegalStateException should be thrown. • The method will invocation be the only line in the body of finally. • It may be invoke later, rather than never at all. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  10. Exception use • Use checked exceptions for conditions for which the caller can reasonably be expected to recover. • An API with a checked exception is telling the user that user is expected to recover from the condition that throws the exception. User can disregard it, but it is a poor tactic. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  11. Exception use • Use run-time exceptions to indicate programming errors. • User is not expected to recover from these. • The largest percentage of these errors are pre-condition violations. • Runtime exceptions are expected to appear and be resolved during program development. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  12. Exception use • Favor use of standard Java exceptions • IllegalArgumentException • IllegalStateException • NullPointerException • IndexOutOfBoundsException • ConcurrentModificationException • UnsupportedOperationException • ArithmeticException • NumerFormatException Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  13. Exception use • Avoid confusion by allowing an exception to be passed on to higher levels, where the exception might not make reasonable sense • An abstraction should catch a low-level exception and in its place throw an exception that is explainable in terms of the abstraction. • Example: the add method to a bounded queue implemented using an array, can throw an IndexOutOfBoundsException. This does not make much sense for the client of the queue, as he is not expected to know the implementation choice in general. So the add method should catch the exception and throw it as FullQueueException. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  14. Documenting exception • Always declare checked exceptions individually, and document precisely the conditions under which each one is thrown using the Javadoc @throws tag. • Document as well those exceptions which are RunTimeExceptions. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  15. Exceptions are objects! • Any checked exception should contain all the data, along with its queries, that caused the exception. • Since we expect the caller to possibly recover from it, having that information will help the course of action to take. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  16. Exception’s string message • All RuntimeExceptions are expected to produce a system crash which will produce the exception string that caused the crash. • Make sure that strings contains all the information needed to be able to understand what happens of what was possibly expected. • Simple example: an IndexOutOfBoundsException should produce a message that states the lower bound, the upper bound of the array, along with the index value that caused the exception. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  17. Strive for failure atomicity • Generally speaking: a failed method should strive to leave the object in the original state prior to invocation. • From the point of view of the client: a method get all done, or nothing gets done! Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  18. How to accomplish failure atomicity:making the object remain consistent. • Get if for free if your object is immutable. • For mutable objects: • Check conditions (parameters) before making changes. • Order algorithm so that the part that may fail occurs before the part that make changes. • Use temporary objects to perform the algorithm, and replace the object’s state if successfully accomplished. • Write recovery code in the catch clause. • All these solutions work in a singly-threaded method. In a multi-threaded application all bets are off, and need to recourse to other ways to handle object’s consistency. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  19. Beware • Do not ignore exception handling! • Exception handling with blank braces should raise flags. • An ignore exception can later cause another exception in an unrelated piece of code! • There are cases where you may ignore an exception, write a comment for the reason why is safe to ignore it! Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  20. Java support for encapsulation • Field modifiers: • public • private • protected • none Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  21. Static uses in Java • To define constants. • To define methods • These methods are called class methods, because they are independent of any of the instances of a class. • Instance methods rely on the state of the object, while class methods must be independent of them. • Using inheritance, static methods cannot be overwritten, they can only be overloaded. A typical programmer’s error is to overwrite a static method in a subclass, but in reality is only being overloaded. • Thus, polymorphism does not work with static methods. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  22. Static uses in Java • Static method invocation is qualified not with an object reference, but with the actual class name. • The variables manipulated in a static method must be local variables or static variables. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  23. Best programming practices • USE DESIGN BY CONTRACT. • Identify class invariants and make sure all methods maintain them. • Method specification includes require and ensure clauses as doc comments. • Develop a test plan as part of analysis/design phase. • Test each class independently from the system you are developing. • Even better, use JUnit to make testing automated while supporting iterative design. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  24. Best programming practices • When writing code, get used to re-read your code carefully to uncover commonly made design flaws: • Repetitive code • Large methods • Lack of use of polymorphism • Large objects • …. Etc • This activity goes by the name of refactoring • Successful refactoring needs to be supported by automated testing. Changing code without testing it is asking for big trouble down the line. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  25. Fundamental System Decomposition: MVC • Any system written using object must exhibit the following decomposition: • Model: the set of classes which solve problem. These component is independent of the interface being uses by the system. • UI: the set of classes to provide an interface to the model. • Data: the set of classes that provide data to the UI or the Model. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  26. Static diagram for fundamental decomposition Data Model UI presents consumes consumes Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  27. Fundamental Software Development Principles • Cohesion: A module should model one well defined concept; its functionality must only deal with supporting the concept being modeled. • Coupling : a module’s collaborators should be small in number and it should interact through a well defined interface. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  28. Tools for Design: Inheritance and Composition • Inheritance • strong coupling between components • allows modification of components being reused • Making a new class involves programming • static relationship • Composition • powerful reuse technique, difficult to understand by examining static program text. • Composition’s core class can be changed at run-time Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  29. Delegation • Composed object uses its components to implement its interface. Usually a composed object receives a messages which it forwards to one of its components for execution. This is called delegation. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  30. Uses of inheritance • Identifying common functionality among a collection of classes • providing an implementation of a method in an abstract class • providing an alternative implementation • refining the implementation of a method • extending functionality of an existing class Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  31. Concrete classes, abstract classes, interfaces • When should we subclass, when should we compose? • When to use an abstract class, when to use an interface? Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  32. Abstract classes • To model a generalized object • Specification of an abstract class ought to be stable • Should factor out common implementation details of its subclasses • Mechanism used to exploit polymorphism • Abstract classes can be extended without breaking running code. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  33. Interfaces • Model to generalize functionality • they are by definition abstract, no aspects of its implementation is fixed. • A way to multiple inheritance: A class can implement one or more interfaces • Allows for a more generalized used of polymorphism • Interfaces cannot be modified • They are the key to pluggability Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  34. Interfaces and the software life-cycle • Design: serve as a stabilizing element in the specification and implementation of classes • Implementation: compiler checks that class implementing interface fullfills contract • Integration: well-established interfaces are glue for composed classes and subsystems • Testing: logical errors are limited to a subset of methods Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  35. Inheritance and composition • Advantages of inheritance: • code reuse • polymorphism • extension of an existing class • dis-advantages of inheritance • superclass and subclass are strongly coupled; changes to superclass affect suclass, and subclass cannot change specification of superclass methods • It’s a static feature Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  36. Advantages of composition • code reuse as black box reuse • can change composed object’s core class at run-time; ie, it’s a dynamic property of object • Supports stronger encapsulation than inheritance. Changes to core class does not affect specification of composed class. And vice-versa, changes to composed class do not affect core class. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  37. Dis-advantages of composition • lose polymorphism.!!! • Can gain it back: compose with interfaces and have core classes implement those interfaces Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  38. Mis-uses of inheritance • To model roles • To provide implementation alternatives to a given abstraction • To model option features of an object • Consequences: • class explosion Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  39. Favor composition over inheritance • Inheritance should not be used just for code reuse or to take advantage of polymorphism • It is harder to maintain inheritance based code than composition based code. • Use inheritance • when the complete interface of the superclass applies to the subclass candidate • there is a permanent is-a relationship • superclass is stable. • For specialization Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  40. Composition can be used • some features of core class are irrelevant, ie, new class is not a true functional subtype • to provide implementation to some specific functionality. • high proportion of code of base class need to be rewritten • Use composition to extend functionality by delegating to more appropriate objects. • Interfaces can be used • to maintain separation of between specification and implementation • to provide reuse and polymorphism across hierarquies Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  41. Worker SalesW HourlyW FixedW Accommodating update of object’s class • Example: modeling with inheritance • “transmute” problem: via copying & delete • With composition: use “simple” assignment to component being updated. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  42. Student PT FT Example • Need to model student • Later on need to model PT, FT student (beware not to model attributes with classes) Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  43. Student Grad PT FT PTGrad FTGrad • Later own, need to consider graduate student Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  44. Student Grad PT FT PTGrad FTGrad Later on ...Add student worker AGGGGHHHHHHHHHHHHHHHHH!! Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  45. Alternative • Define : Student with subclasses undergrad, GradStudent • Define: Status with subclasses PT, FT • Define: Worker with subclasses FTW, PTW • Now based on student we compose to get • a student who is part-time and ft worker • a grad student full time and part time worker Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  46. Example: Account class • Designed to include • customer information: • name • address • account identification number • Design not cohesive: two abstractions • customer information • account Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  47. Cohesion • Limitations introduced due to the one-to-one correspondence of the two abstractions • one customer with several accounts • join accounts Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  48. Account Cash Acc Porfolio Ac Individual Institution Class specialization Composing on the two dimensions: class explosion. One possible solution: multiple inheritance. More trouble that what solves. Problem: inheritance diamond. Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  49. 1..* Customer Account * owner Cash Acc Individual Porfolio Ac Institutional Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

  50. Inheritance vs composition • Examples: • Sensor, remote Sensor • Subclasses of Thread, not a good choice • Subclasses of Observable Distributed Software Engineering C:\unocourses\4350\slides\DefiningThreads

More Related