Friday, 7 February 2020

OOD - Online Book Reader

Untitled1

OOD for Online book reader

Requirements

  • User should be able to search in a library of books
  • Choose a book
  • Read a book
  • Turn pages of book

The code here will be pythonic version of the solution in CTCI here :

https://github.com/careercup/CtCI-6th-Edition/tree/master/Java/Ch%2007.%20Object-Oriented%20Design/Q7_05_Online_Book_Reader

Actors and use cases

  • User
    • Browses a library of books
    • Chooses a book
    • Book page is displayed to user
    • User turns page
    • User chooses new book to open

Classes and their responsibilities

  • Book
    • Represents a book and its content
  • User
    • Represents the user
  • Library
    • This will hold all the books
  • OnlineReaderSystem
    • This is composed of library, a user manager and a display unit
    • This also sets an active user and an active book
  • Display
    • Responsible for displaying the book
    • When user chooses a page that should be shown, like swipes to next page or back
  • UserManager
    • This takes care of addin and removing users from the system

online_reader_cd.png

In [45]:
class OnlineReaderSystem(object):
    def __init__(self):
        self._library = Library()
        self._user_manager = UserManager()
        self._display = Display()
        
        self._active_book = None
        self._active_user = None
        
    def get_library(self) -> Library:
        return self._library
    
    def get_user_manager(self) -> UserManager:
        return self._user_manager
    
    def get_display(self) -> Display:
        return self._display
    
    @property
    def active_book(self) -> Book:
        return self._active_book
    
    @active_book.setter
    def active_book(self, book: Book):
        self._active_book = book
        self._display.display_book(book)
        
    @property
    def active_user(self) -> User:
        return self._active_user
    
    @active_user.setter
    def active_user(self, user: User):
        self._active_user = user
        self._display.display_user(user)
        

class Library(object):
    def __init__(self):
        self.books = {}
        
    def add_book(self, book: Book):
        self.books[book.id] = book
        
    def remove_book(self, book: Book):
        self.remove_book(book.id)
        
    def remove_book(self, id_: int):
        del self.books[id_]
        
    def find_book(self, id_: int) -> Book:
        if id_ in self.books:
            return self.books[id_]
        else:
            return None
        

class UserManager(object):
    def __init__(self):
        self.users = {}
    
    def add_user(self, user: User):
        self.users[user.id] = user
    
    def remove_user(self, user: User):
        self.remove_user(user.id)
    
    def remove_user(self, id_: int):
        del self.users[id_]
        
    def find_user(self, id_) -> User:
        return self.users[id_]
    

class Display(object):
    def __init__(self):
        self._book = None
        self._user = None
        self._page_number = -1
        
    def display_user(self, user: User):
        self._user = user
        self._refresh_username()
    
    def display_book(self, book: Book):
        self._book = book
        
        self._refresh_title()
        self._refresh_details()
        self._refresh_page()
        
    def turn_page_forward(self):
        self._page_number = self._page_number + 1
        self._refresh_page()
        
    def turn_page_backward(self):
        self._page_number = self._page_number - 1
        self._refresh_page()
        
    # private methods
    def _refresh_username(self):
        print('The username update to : %s' % self._user.name)
        
    def _refresh_title(self):
        print('The title of book updated to : %s' % self._book.title)
        
    def _refresh_details(self):
        print('The details of book updated to : %s' % self._book.details)
        
    def _refresh_page(self):
        print('Refreshed the current page number : %d' % self._page_number)
        

class Book(object):
    def __init__(self, id_: int, title: str , details: str):
        self.id = id_
        self.title = title
        self.details = details
        

class User(object):
    def __init__(self, id_: int, name: str, account_type: int, details: str):
        self.id = id_
        self.name = name
        self.account_type = account_type
        self.details = details
        
    # other user relate methods
    def renew_membership(self):
        pass
    
    
In [46]:
class OnlineReaderSystemTestCLI(object):
    def __init__(self):
        self.reader = OnlineReaderSystem()
        
    def start(self):
        # add some books to library
        library = self.reader.get_library()
        
        rmy = Book(1001, 'Ramayana', 'Story of how Raama came back')
        mbt = Book(2002, 'Mahaabhaarata', 'Story of Pandavas and Kauravas')
        library.add_book(rmy)
        library.add_book(mbt)
        
        # add some users to user manager
        user_manager = self.reader.get_user_manager()
        
        ram = User(1, 'Rameshvara', 0 , 'Premium User')
        lak = User(2, 'Lakshmana', 1, 'Standard User')
        user_manager.add_user(ram)
        user_manager.add_user(lak)
        
        # now lets set a book and user in the system
        self.reader.active_user = ram
        self.reader.active_book = rmy
        
        # now lets flip the pages
        display = self.reader.get_display()
        display.turn_page_forward()
        display.turn_page_forward()
        display.turn_page_backward()
        
In [47]:
cli = OnlineReaderSystemTestCLI()
cli.start()
The username update to : Rameshvara
The title of book updated to : Ramayana
The details of book updated to : Story of how Raama came back
Refreshed the current page number : -1
Refreshed the current page number : 0
Refreshed the current page number : 1
Refreshed the current page number : 0