CS3500: Object Oriented Design - assouline.sh

CS3500: Object Oriented Design

Object-Oriented Design (CS3500) has been the most challenging course to date. The demanding assignments with extensive testing, coupled with the doubled pace of the course (since I took it over the summer) was quite stressful. However, all the late nights were well worth it, as I feel my comprehension of coding concepts and Java skills have developed tremendously. At first it was intimidating to have such free-reign about design and approach, but it grew my confidence in my technical abilities, and became my favorite aspect of the course.

We worked on two primary projects throughout the course- a marble solitaire game and an image processor. Both can be found on my github here.


Here are some of the main conceptual takeaways from the class:

Principles

  • Software is “good” if it is correct, efficient, secure, reduces and manages complexity, maintainable, reliable, testable, usable, scaleable, portable, and robust
  • Object-Oriented Design allows us to deal with complexity and design for flexibility
    • Objects encapsulate both data and behaviors associated with that data
    • Information hiding, interfaces, and polymorphism promote loose coupling
    • Data abstraction and encapsulation
    • Client perspective vs. implementor perspective
  • SOLID Principles:
    • Single Responsibility: every object should be responsible for just one focused purpose
    • Open / Closed: everything can be open to extension, but closed to modification
    • Liskov Substitution: if a type S is a subtype of a type T, then objects of type S can be used anywhere objects of type T can
    • Interface Segregation: no client should be forced to depend on methods it doesn’t use
    • Dependency Inversion: abstractions should not depend on details; rather the reverse
  • Class invariants enable rely-guarantee reasoning; if the constructor ensures some property and every method preserves the property, then every public method can rely on the property
  • Reusability is an explicit goal in design: the more generic, the more reusable it is
    • Can be achieved with inheritance or composition
  • Performance, GUIs with Swing, encapsulation, mocks, JUnit testing, UML class diagrams

Design Patterns

  • Factory method pattern
    • Creational design pattern often used to decide which object to instantiate in several ways
  • Model, view, controller (MVC)
    • Allows isolation of behavior and promotes cohesion, as each class is in only one category
    • Also promotes low coupling between groups of classes; for example the controller decides when to provide data to the view, instead of it asking the controller for data
  • Builder pattern
    • The client doesn’t call the class’s constructor directly (it is private) so the client must instantiate model instances via the builder
    • Builder begins with the default parameter values, then provides several methods for changing whichever parameters we choose
  • Command design pattern
    • Unifies different sets of operations under one umbrella so they can be treated uniformly, increasing cohesion
    • Promotes delegation which allows support of new, more complicated commands
  • Adapter pattern
    • Extend the adaptee and then implement the target; the resulting object, by extending the adaptee, inherits its interface
    • Replace inheritance with delegation to wrap an already-existing object or wrap objects of different types than the one for which it was intended
  • Strategy and decorator pattern
    • Strategies are function objects, can be composed, and can be dynamically selected
    • Decorator pattern similarly has objects delegate from one to another; each class is responsible for one fragment of functionality and the complete functionality comes by composing several decorators together around some base object
    • Both are not fixed at compile time so they don’t have to be hard-coded in advance, are tiny, self-contained, easy to read, and have high cohesion