Build Google Docs | A Real-World LLD Project | Document Editor LLD |

Build Google Docs | A Real-World LLD Project | Document Editor LLD |

Introduction to Low-Level Design (LLD)

Overview of the Session

  • The session welcomes viewers back to a series on low-level design, emphasizing practical application of previously learned theories such as SOLID principles and object-oriented design.
  • The focus will be on approaching a problem in an LLD interview context, demonstrating how to create a low-level design through example.

Problem Statement: Document Editor

  • The primary task is to develop a document editor, outlining its features and implementation strategies.
  • Users can input text and images into the document editor, which should support scalability for future features like tables or videos.

Approaching the Design Problem

Design Methodologies

  • Two main approaches exist for designing applications: top-down and bottom-up.
  • Top-down focuses on creating high-level objects first before detailing smaller components.
  • Bottom-up starts with small components and builds up to larger objects.
  • Preference is given to the bottom-up approach in most LLD interviews due to its effectiveness in handling complex designs.

Initial Class Structure

Creating the Document Editor Class

  • A basic class structure for the document editor is proposed, where all functionalities are initially housed within one class.
  • The class will maintain lists for both text and images, allowing users to add elements sequentially while determining their order.

Methods Within the Class

  • Key methods include:
  • addText: Adds text strings to the document.
  • addImage: Accepts image paths as strings for inclusion in the document.
  • renderDocument: Loops through elements and generates output based on user inputs.

Identifying Bad Design

Issues with Current Architecture

  • The current design violates several principles:
  • Single Responsibility Principle: One class handles multiple responsibilities (adding content, rendering, saving).
  • Open/Closed Principle: Adding new features requires modifying existing code rather than extending it.

Improving Design Principles

Refactoring Strategy

  • To adhere better to design principles:
  • Separate concerns by extracting element management from the main editor class into distinct classes (e.g., DocumentElement).
  • Implement polymorphism by creating subclasses for different types of elements (text, image).

New Class Structures

  • An abstract base class (DocumentElement) will define common behavior while allowing specific implementations in derived classes like TextElement and ImageElement.

Finalizing Document Management

Document Class Responsibilities

  • A new Document class will manage collections of document elements. It will handle adding/removing elements and delegating rendering tasks back to individual element classes.

Persistence Layer Implementation

  • Introduce a persistence layer via an abstract class that defines save operations. This allows flexibility in saving documents either locally or remotely without altering core functionality.

This structured approach ensures clarity in understanding how low-level designs evolve from initial concepts through iterative improvements while adhering closely to established software engineering principles.

Rendering Documents: Methodology and Architecture

Overview of Document Rendering

  • The discussion begins with the creation of a renderDocument method, which will handle the rendering process for documents.
  • This method will loop through elements in the document, calling their respective render functions whether they are text or image elements.

Saving Mechanism

  • A new method called save is introduced to replace saveToFile, which will invoke the database's save method.
  • The saving mechanism depends on the reference to the database variable within the document editor, ensuring that it knows how to save files correctly.

Document Editor Responsibilities

  • The document editor retains methods like addText, addImage, renderDocument, and save, but delegates all requests to appropriate handlers instead of managing them directly.
  • It acts as an intermediary between clients and document handling processes, simplifying client interactions by abstracting complexity.

Code Structure and Class Design

Abstract Class Implementation

  • An abstract class named DocumentElement is created with a single render method that is extended by specific element types like TextElement.
  • Each element type overrides its render function; for instance, text returns plain text while images return HTML tags with paths.

Extensibility of Elements

  • New elements can be added easily due to adherence to open/closed principles; examples include newline and tab space elements that inherit from the base class.
  • Future extensions could include formatting options such as bold or italicized text by creating new classes that implement their own rendering logic.

Document Class Functionality

Collection Management

  • The Document class manages a collection of document elements using a vector structure for storage.
  • It includes methods for adding elements and rendering them without handling specifics itself; it loops through stored elements calling their individual render methods.

Persistence Layer Integration

  • A separate Persistence class handles data storage operations, supporting both file-based and database storage mechanisms.
  • Database storage involves overriding save methods to accommodate SQL queries for data persistence.

Client Interaction with Document Editor

Constructor Logic

  • The DocumentEditor class constructor initializes references to documents and persistence layers, allowing polymorphic behavior based on provided storage types (file or DB).

Method Delegation

  • Methods like addText delegate requests back to the document object, maintaining simplicity in client interactions while ensuring functionality remains intact.

Finalizing Architecture: SOLID Principles

Adherence to SOLID Principles

  • The architecture follows Single Responsibility Principle (SRP), where each class has distinct responsibilities—document management, rendering, persistence—without overlap.

Open/Closed Principle Compliance

  • New element types can be added without modifying existing code structures.
  • This allows flexibility in extending functionalities while keeping core implementations stable.

Liskov Substitution Principle

  • Any subclass can replace its parent type without affecting program correctness.
  • For example, both TextElement and ImageElement can be used interchangeably within collections managed by Document.

Interface Segregation Principle

  • Interfaces are kept minimalistic so that implementing classes only need relevant methods.

Dependency Inversion Principle

  • High-level modules do not depend on low-level modules directly but interact through abstractions (interfaces).

Addressing Potential Issues

Counter Questions in Design Review

  • Concerns arise regarding whether having multiple responsibilities within classes violates SRP despite delegation practices being employed.

Knowledge Coupling Concerns

  • Classes may still possess knowledge about other components' functionalities leading to potential coupling issues.

Proposed Solutions for Improvement

  • Suggestions include separating rendering logic into a dedicated renderer class while keeping core operations focused solely on data manipulation tasks within documents.
Video description

Welcome to Lecture 7 of the Ultimate Low-Level Design (LLD) Series by Coder Army! Second week for #lowleveldesign #systemdesign #8weeksLLdchallenge. We are doing 8 weeks challenge and going to complete the whole course within the duration with quality content on Youtube. Let’s learn LLD like never before and attain advance level mastery on this subject. In this video, we apply *LLD principles* using *OOPS* and *SOLID* design concepts to build a *Document Editor* — think Google Docs, but designed from scratch by you! 💻 After teaching the core concepts of Object-Oriented Programming and SOLID principles in previous videos, this session is where it all comes together. You’ll learn how to approach a real-world design problem step-by-step, breaking it down into: ✅ Classes & Relationships ✅ SOLID-compliant structure ✅ Extensibility and Modularity Whether you’re preparing for tech interviews, working on software architecture, or building your own projects — understanding UML is a must for clear, maintainable, and scalable code design. Join Coder Army Whatsapp Group: https://whatsapp.com/channel/0029Va6H0tbHVvTbcuT99Y1f Code and Notes: Github : https://github.com/adityatandon15/LLD Connect with Aditya Tandon Instagram : https://www.instagram.com/adityatandon2 LinkedIn : https://www.linkedin.com/in/adityatandon2 Twitter : https://x.com/adityatandon02 Timestamps: 00:00 Introduction 00.35 Problem Statement 04:21 Bad Design 08:00 Code for Bad Design 11:54 Problems of bad design 13:28 Moving to Better Design 25:24 Code for Better Design 31:07 Revisiting our UML 34:39 Enhancements in our design 42:22 Principle of Least Knowledge #LLD #LowLevelDesign #SOLIDPrinciples #SoftwareDesign #SRP #OCP #LSP #ISP #DIP #CodingInterview #SystemDesign #SoftwareEngineering #TechEducation #OOPS #SOLID #GoogleDocsLLD