Object-Oriented Programming (OOP) Principles and Design Patterns, Study notes of Advanced Algorithms

A comprehensive overview of object-oriented programming (oop) principles, including encapsulation, inheritance, and polymorphism. It also explores design patterns like abstract factory and strategy, highlighting their role in creating scalable and maintainable software. The document further emphasizes the importance of clean code techniques and solid principles for improving code quality and collaboration within development teams.

Typology: Study notes

2020/2021

Uploaded on 10/10/2024

htet-htet-wint
htet-htet-wint 🇲🇲

1 document

1 / 54

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31
pf32
pf33
pf34
pf35
pf36

Partial preview of the text

Download Object-Oriented Programming (OOP) Principles and Design Patterns and more Study notes Advanced Algorithms in PDF only on Docsity!

Table of Contents

Introduction

I am working as a junior mobile developer in software and mobile app development company Myan Pro Solutions. I was assigned to help in improving the documentation of the company’s in-houses libraries. As a part of my role, I was assigned to develop an app for the Prestige Automobile Company Limited (PAC) which is an official importer and distributer of BMW vehicles and Genuine BMW parts to provide services. The company wants an application that can allow them to add new cars, display car list, searching and updating of the car model and delete unnecessary ones. In here, I will discuss about the OOP paradigm, design principles and relationship between them, and example with the UML diagrams and application’s UML diagrams along with the explanation of them.

Object Oriented Programming (OOP)

OOP is a class-based programming that contains a group of attributes and methods to create an object. A class may represent multiple objects that interact with each other and in complex ways. In OOP structure it contains a class that provide a framework for creating objects, objects that represents a creation of class which defines specific data like properties and behaviors to implement a code, method which is a function that can perform a task and attribute which stores information about an object. For example, that a Human class defines a template for a human. Attributes of this class that define a person include name, email, and address. It can also include procedures, or functions that characterize the behaviors or acts that a human can carry out. Methods like verify and send email to for emailing and checking that if it is valid or not.

Principles of OOP

In OOP they contain data, that refers to the attributes, and methods by allowing them to interact with each other with these principles.

Encapsulation – is a principle that keeps all critical information inside the object and restricts assess to public functions or methods from hiding detail information from the outside world. This provides security control over state changes, reduces errors and improve program understanding. For example, if there is a class that encapsulate variables and methods in a single unit which protect the internal state of the object and improve modularity by limiting direct access to some of its components. Inheritance – inheritance allows the developers to create new classes based on the parent class enabling them to override their properties and methods. This principle is useful in programs with thousands of like of code by simplifying the maintenance and can reduce code duplication. This inheritance relationship enables the extension of class A's functionality and the reuse of code by allowing class B to inherit attributes and methods from class A. Single inheritance supports a hierarchical classification and assists in maintaining of a logical and clear structure within the codebase. Polymorphism – this principle complete inheritance by enabling the objects of different classes to perform tasks with the same name with different code. It can simplify the development process by developing common functions and methods for many types of projects. It contains method overriding, where subclasses provide specialized implementations of superclass methods, and method overloading, when many methods with the same name but different parameters exist in the same class. Abstraction – this principle simplifies the complexity of the program on essential elements and hiding unnecessary features making the code more understandable. This allows developers to manage complexity by focusing on high-level concepts rather than detailed implementations. Abstraction highlights important aspects of

relationship but a parent can exist without a part of child and vice versa. For Example, an employee may belong to many departments within organization but if the department is deleted the employee object will not be erased. Realization – refers to the relationship between interface and a class that implement the interface. For example, there is a car interface that contains methods like start and stop method and implemented by “Mercedes” and “Tesla” classes. Each class has their own implementation like unfolding roof and charge battery. (Kanjilal,

Design Patterns

Design patterns are reusable solutions to often occurring problems. Design patterns were started as guidelines that were applied again and again to comparable issues found in different context of software design.

Creational Design Patterns

Creational design Pattern provide creation of objects that are trying to build objects in manner correspond to the situation. Design issues or complexity may increase from the basic form of object production. This design pattern can solve this problem by managing the object creation process. Singleton Pattern – it can enables to ensure that a class has only one instance while offering a global access point to this instance. This example shows the creation of a Singleton class named MySingleton, protected from outside creation by a private constructor _internal(). The instance is kept in a static variable _instance; a factory constructor validates whether an instance has been generated.

Abstract Factory Method Pattern – Abstract factory design enables users to create related objects through abstract factory methods which are implemented by specialized factory classes for each product category. For example, in the diagram, the client request animal from the “AnimalFactory” interface which has two concrete classes “WildAnimalFactory” which will produce “WildDog” and “WildTiger” and “PetAnimalFactory” which will produce “PetDog” and “PetTiger” to create associated animals. This pattern can ensure the scalability and loose coupling by enabling the client to obtain specified animal objects without being aware of their concrete classes.

Structural Patterns

Structural design patterns define how to combine things to create new functionality. The additional flexibility of object composition come from the ability to change the composition at runtime, which is not available with static class composition. Adaptor Pattern – This pattern enables different interfaces to function together by creating an extension that transforms one interface into another requested by the client. This is particularly useful when integrating current or third-party code that doesn't match the user's expected interface. For example, the "Rect" class is an adapter with a private instance of "OldRectangle", allowing clients to send arguments and modify input to meet its requirements. When using the render() method, it is

Open-Closed Principle (OCP) – this principle allows software components to be open for extension but closed for modification which means the code should be able to add new functions without changing the existing code. Implementing this principle can improve code extensibility which is new functions can be add without affecting the existing code and can reduce the risk of occurring bugs. Liskov Substitution Principle (LSP) – this principle show that superclass or parent class should only be replaceable with the objects of subclass without affecting the program accuracy. The subclass or child class should function as expected when used in place of their parent class. This principle ensure that subclasses continue to behave as their parent class probably would, resulting in more dependable and predictable code. Interface Segregation Principle (ISP) – this principle shows that many client interfaces are better than one general purpose interface which is clients should never be forced to implement a function they don’t need. Since clients are not forced to depend on large interfaces, changes made to one part of the system are less likely to impact to others. Dependency Inversion Principle (DIP) – this principle shows that the classes should depend on interfaces instead of concrete classes and functions. Following this principle makes the design more modular and flexible by reducing the link between high- and low-level components and makes it easier to test individual components by replacing mocks for the dependencies. As it allows the components to be developed and modify independently, it can increase the scalability of the system. (Y.K, 2020)

Clean Code

In software engineering, it is not just about learning languages and coding. As a software developer, if is important to write the code easy to understand and easy to change. Clean code is a technique that developers should follow which is also important between developers. Naming conventions – when giving the name of classes, methods, and variables, using short form like (int a or void b ()) are not allow to use. Instead, it should be

the meaning name that is understandable once it is read by the developer themselves and others. Example, in the following code, the variable name on the left are not understandable and on the right one, they created the variable name which are easily understandable. Single Responsibility Principle (SRP) – this is one of solid principle mentioned above, which most of the beginners do. They write a function that can handle all the tasks which makes code confusing for developers and may face problems while finding bugs and a part of code. For example, the following code has three methods that return specified components of date, time with clear format of method names and proper formatting. Commenting – all the developers use comments to show the purpose of the specific line in the code. It is helpful and help in explaining and understanding the code. If the duplicate comment exist in the same place can be a big problem. Which developers can confuse and get destructed because of the useless comments.

Impact of clean code on the use of data structure and in operations

Following clean code techniques have a great impact on the use of data structures and operations many ways. Proper use of clean code techniques can help to improve the code readability by giving proper function and variable names, clear and consistent formatting. Properly organized code with clear documentation allows the developers in maintaining the code like code changes with minimal risk of occurring errors. If the code is well organized, it will be easier in debugging and handling errors. Clean code techniques help to improve the efficiency of data structure and processes which in turn allows for modifications that accelerate the execution of the program. If the code is followed clean code techniques, it is more likely to be reusable. Also, if the code is well- documented, modular and written in understandable way allows developers for easy to recuse multiple parts across the software application. With reusability of the code, the development process can become more efficient and less redundant. Thus, clean code has a great impact on the readability, maintainability, debugging, efficiency, reusability while building the robust and high-quality software project.

Relationship Between OOP and Design Patterns

In programming, OOP and design patterns are linked in somehow, with the design pattern build based on the principles of OOP to provide solutions to software design problems.

  • To handle typical design difficulties in software development, design patterns utilize OOP concepts. As an example, the Strategy pattern makes advantage of polymorphism, a key OOP principle, to improve the adaptability of various algorithms. This allows developers to change an object's algorithm during runtime without changing its code.
  • Many design patterns handle complexity and simplify code by using abstraction and encapsulation. Encapsulation is used, for instance, in the Factory Method design to prevent the client code from knowing which concrete class is being produced. In this manner, object creation is not a knowledge required by the client code. In a similar vein, the Template Method

design allows subclasses to offer their own implementations for certain algorithmic components by using abstraction to establish the fundamental structure of an algorithm inside a method.

  • Design patterns give standardized answers to typical design problems, which have been tested and proven throughout time. Standardization makes it easy for developers to communicate to each other because they can detect a pattern and instantly understand the basic method that is used. For example, when a developer presents the Singleton pattern, others understand that the goal is to ensure a class has only one instance and give a global point of access to it.
  • Design patterns follow the OOP concepts and allow to develop flexible and reusable systems. For example, code reuse is promoted and sophisticated structure management is made easier with the Composite pattern, which provides uniform handling of individual items and compositions of things. As requirements change, this flexibility allows the system's expansion, modification, and maintenance.

The affect of SOLID principle on the development process in OOP

Following the solid principle has a several good impact and affect on the development process. For example, following the single responsibility principle (SRP), it can help in easier understanding of code and classes that are implemented in the project and easy to debug because of their specified responsibility. It can also improve reusability of the code by allowing easy integration across various part of the application. If the developers followed SOLID principles, it can help in easier collaboration within development teams because of clear roles and well-defined structures, the team members can easily understand different part of code or classes by making it easier to work for various components without confusing in understanding of code. This can reduce the likelihood of facing bugs and errors when the changes are made and increase the project’s integrity and functionality. Also, the code that is written based on the solid principles are more scalable and expendable as they can be expend and develop new requirements without

Open-Closed Principle (OCP)

The UML diagram shows a design where the Transmission class is an abstract class defining the changeGear(int gear) method, which is implemented by the ManualTransmission and AutomaticTransmission classes. The Vehicle class has a composition relationship with the Transmission class, represented by its transmission attribute, which is initialized through its constructor. The Vehicle class sends the changeGear(int gear) method to the Transmission object, allowing for different transmission methods (manual or automatic) to be used interchangeably, displaying polymorphism and encapsulation in the design. (www.linkedin.com, n.d.)

Liskov Substitution Principle (LSP)

The following example shows an abstract class Bird with an abstract method move(), showing that all bird types must implement their own movement behavior. The FlyingBird class extends Bird and offers a concrete implementation of the move() method to represent flying behavior. Similarly, the Penguin class extends Bird and modifies the move() method to represent walking or swimming behavior. This design shows polymorphism, allowing different types of birds to define their specific movement behaviors while sharing a common interface.

(www.linkedin.com, n.d.)

Interface Segregation Principle (ISP)

In the following example there are two abstract classes, Drivable and Flyable, each having single abstract methods drive() and fly() respectively. The Car class implements Drivable, giving its own implementation of drive() for driving behavior specific to cars. Similarly, the Airplane class implements both Drivable and Flyable, describing its own versions of drive() and fly() for airplane-specific driving and flying functionalities. This structure illustrates how classes can extend abstract behaviors described in abstract classes, displaying the specialization of methods according to the type of vehicle they represent. (www.linkedin.com, n.d.)

Design patterns with UML and examples

Creational Design Patterns - Singleton Pattern

In here the Singleton class uses the Singleton design pattern, ensuring that only one instance of the class can exist. There is a private static variable called _instance that holds the single instance, and a private constructor called _internal() that prevents direct creation. If it is, it uses the private constructor to create a new Singleton object and assigns it to _instance. If it is not null, it returns the current instance. This makes sure that getInstance() always gives the same instance, so there is only one shared object throughout the lifecycle of the app. (www.linkedin.com, n.d.)

Creational Design Patterns - Abstract Factory Method Pattern

In the example UML class diagram, the CarFactory class acts as a car factory's order system, generating certain types of cars depending on the CarType enum, which includes sedan, SUV, and hatchback. The Car abstract class defines a common drive method that is implemented by the Sedan, SUV, and Hatchback classes, each with its own driving behavior. The CarFactory's createCar function accepts a CarType and returns an instance of the appropriate car class. This approach enables for easy

extension with new car types by adding new classes and modifying the CarType enum and createCar function, which promotes code flexibility and maintainability. (www.linkedin.com, n.d.)