제이온

[Object] Chapter 2. Object-Oriented Programming

Created: 2024-04-28

Created: 2024-04-28 13:46

Movie Reservation System


Reviewing Requirements

  • We aim to implement an online movie reservation system.
  • A movie represents the basic information about a film.
    • Such as title, screening time, and price information.
  • A screening represents the actual event where viewers watch a movie.
    • Including screening date, time, and sequence number.
  • People say they reserve a movie, but technically, they reserve a specific screeningof a movie.
  • Discount Conditions
    • Whether or not the price is discounted.
    • Sequence Condition: Determine discount eligibility based on the screening sequence number.
    • Period Condition: Determine discount eligibility based on the movie's screening start time.
  • Discount Policy
    • Determine the discounted fare.
    • Fixed Amount Discount Policy: Discount a certain amount from the reservation fee.
    • Percentage Discount Policy: Discount a certain percentage from the regular price.
  • Each movie can have one discount policy assigned or none at all, and multiple discount conditions can be combined.
  • If a discount policy is applied but the discount conditions are not met, or if no discount policy is applied, the fare is not discounted.


Towards Object-Oriented Programming

Collaboration, Objects, and Classes

  • Object-oriented programming is about focusing on objects.
    • Don't think about what attributes and methods a class needs after deciding on the class.
    • You need to determine what objects have what states and behaviors.
    • Objects should be viewed not as independent entities, but as members of a collaborative community.


Program Structure Following the Domain's Structure

  • The domain refers to the area where users utilize the program to solve a problem.

<span class="image-inline ck-widget" contenteditable="false"><img src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fe7d22a03-4a24-40e9-8068-bd03b9fd816b%2FUntitled.png?table=block&id=3f1931fc-8ef9-470a-8189-3727146638f6&spaceId=b453bd85-cb15-44b5-bf2e-580aeda8074e&width=2000&userId=80352c12-65a4-4562-9a36-2179ed0dfffb&cache=v2" alt="Untitled" style="aspect-ratio:2000/438;" width="2000" height="438"></span>

  • Generally, the names of classes should be the same as or at least similar to the names of the corresponding domain concepts.
  • The relationships between classes should also be as similar as possible to the relationships between domain concepts, making the program structure easier to understand and predict.


Implementing Classes

  • A class is divided into internal and external parts, and to design a good class, you need to decide which parts to expose externally and which parts to hide.
    • Object attributes are made private, and the necessary methods to modify the internal state are kept public.
  • Distinguishing between the inside and outside of a class ensures the autonomy of the object, thereby providing programmers with freedom of implementation.


Autonomous Objects

  • Objects should be autonomous entities with states and behaviors.
  • Bundling data and functionality within an object is called encapsulation.
  • Access control helps reduce external interference, allowing objects to determine their own actions.
  • The principle of separating interface from implementation is a key principle to follow in object-oriented programming.
    • Public Interface: The part accessible from the outside.
    • Implementation: The part accessible only from within.


Programmer's Freedom

  • The role of a programmer is divided into class writer and client programmer.
    • Class writer: Adds new data types.
    • Client programmer: Uses the data types added by the class writer.
  • Implementation Hiding
    • Class writers can hide internal implementations by providing only the necessary parts to client programmers.
    • Client programmers only need to know the interface, reducing the amount of knowledge they need.


A Community of Collaborating Objects

  • When representing money, it's better to wrap it in an object like Money instead of simply declaring a Long-type variable. Using objects improves meaning and allows for centralized handling of repetitive operations.
  • The interaction between objects to implement a specific system function is called collaboration.


A Brief Story about Collaboration

  • The only way for an object to interact with another object is by sending or receiving messages.
  • The object's own method for handling a received message is called a method.
  • Distinguishing between messages and methods is important, and this is where the concept of polymorphism originates.


Calculating Discounted Fare

Starting Collaboration for Discount Fare Calculation

  • The Movie class does not contain detailed logic related to discount policies and delegates it to the DiscountPolicy interface. Using inheritance, polymorphism, and abstraction is crucial.


Discount Policy and Discount Condition

<span class="image-inline ck-widget" contenteditable="false"><img src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F7b9b27a5-0dac-4ba7-9552-05b7f8fbdecd%2FUntitled.png?table=block&id=3264f189-6e12-4a55-94d2-75b851320c7a&spaceId=b453bd85-cb15-44b5-bf2e-580aeda8074e&width=2000&userId=80352c12-65a4-4562-9a36-2179ed0dfffb&cache=v2" alt="Untitled" style="aspect-ratio:2000/535;" width="2000" height="535"></span>


Inheritance and Polymorphism

Compile-Time Dependency and Runtime Dependency

  • Code dependencies and runtime dependencies can differ.
  • The greater the difference in dependency between the two, the harder the code is to understand, but it results in more flexible and extensible code.


Programming by Difference

  • Inheritance allows for the easy and quick addition of new classes based on existing classes, and it enables the reuse of the parent class's implementation.
  • The method of creating a new class by only adding parts that are different from the parent class is called programming by difference.


Inheritance and Interfaces

  • Inheritance causes child classes to inherit all interfaces provided by the parent class.
  • An interface defines a list of messages that an object can understand.
  • Movie sends the calculateDiscountAmount message to DiscountPolicy. From Movie's perspective, it doesn't matter which class's instance responds, as long as it provides a successful response.
  • Therefore, both AmountDiscountPolicy and PercentDiscountPolicy can collaborate with Movie in place of DiscountPolicy.
  • This process of a child class substituting for a parent class is called upcasting because it appears as if the child class is automatically type-cast to the parent class above it.


Polymorphism

  • Polymorphism refers to the ability of an object to respond differently depending on its type when receiving the same message.
    • Movie sends the same message, but which method actually executes depends on the class of the object receiving the message.
  • Polymorphism is based on the fact that the compile-time dependency and runtime dependency of a program can differ.
  • Since polymorphism determines the method to execute at runtime, it's called late binding or dynamic binding.


Interfaces and Polymorphism

  • If you only want to share the interface and not the implementation, you can use an interface instead of an abstract class.


Abstraction and Flexibility

The Power of Abstraction

  • Advantages of Abstraction
    • By examining only the abstraction layer, you can describe the requirements' policy at a high level.
    • It makes the design more flexible.


Flexible Design

  • Abstraction prevents designs from being coupled to specific situations, allowing for more flexible design.


Abstract Class vs. Interface Trade-off


  • Currently, NoneDiscountPolicy is not actually necessary because the calculateDiscountAmount() method of DiscountPolicy returns 0 if there are no discount conditions, so there's no issue. However, from the user's perspective, they need to provide the None policy, which doesn't have a discount, as an argument to Movie, so it was added.
  • Therefore, the NoneDiscountPolicy class is conceptually confusing, and the following modification makes it easier to understand.



  • As shown above, DiscountPolicy is abstracted as an interface, and it's divided into NoneDiscountPolicy, which implements it, and DefaultDiscountPolicy, which represents general discount policies.

<span class="image-inline ck-widget" contenteditable="false"><img src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F712983a9-3937-4265-82fe-66a144c44a0f%2FUntitled.png?table=block&id=f5ca651c-d03c-4a6c-97e9-7443ee5649a0&spaceId=b453bd85-cb15-44b5-bf2e-580aeda8074e&width=2000&userId=80352c12-65a4-4562-9a36-2179ed0dfffb&cache=v2" alt="Untitled" style="aspect-ratio:2000/886;" width="2000" height="886"></span>

  • One might think that adding an interface solely for NoneDiscountPolicy is inefficient compared to the increased complexity.
  • It's important to recognize that everything related to implementation can be a subject of trade-offs in design. In other words, every piece of code you write should have a valid reason.


Code Reuse

  • Inheritance can be used for code reuse.
  • However, it's better to use composition than inheritance for code reuse.
  • In the current code, the way Movie reuses DiscountPolicy's code is through composition.
  • If Movie were to be the parent class, and it were split into AmountDiscountMovie and PercentDiscountMovie, it would be considered using inheritance.


Inheritance

  • Disadvantages of Inheritance
    • Violates encapsulation.
      • You need to know the internal structure of the parent class.
      • When the parent class changes, the child class is likely to change as well.
    • Makes design inflexible.
      • The relationship between parent and child classes is determined at compile time.
      • It's not possible to change the type of an object at runtime.
      • However, with composition, the using object can replace instances at runtime through methods like changeDiscountPolicy().


Composition

  • The method of reusing code only through messages defined in an interface is called composition.
  • It allows for encapsulation and maintains loose coupling.
  • When reusing an interface for polymorphism, inheritance and composition should be combined.
    • For example, the DiscountPolicy interface must use inheritance to implement its subclasses.


Source

  • Objects

Comments0