What is Object Oriented Programming (OOP)?
Object Oriented Programming, is a programming paradigm, where we combine data and actions with this data in a single module called object. We try to model real world objects in programming objects.
AI
Object Oriented programming is na programming paradigm that organizes code into reusable, self-contained units called objects. These objects, represent real=worls entities and encapsulate both data(properties) and functions (methods) that operate on that data. OOP promotes concepts like:
- inherintance
- encapsulation
- polymorphism which make it easier to model complex systems and maintain code. Popular programming languages that follow OOP paradigm are: Java, Python, C++
What are the pillars of OOP?
OOP has four pillars:
- encapsulation: bundling all data and methods into a single unit called an object. This helps controlling access and prevents unintented modifications.
- abstraction: simplifying complex reality by modeling classes based on essential characteristics
- inherintance: promotes reusability. It allows a new class (subclass or derived class) to inherit properties and behaviors
- polymprphism:
Does abstraction apply to Vanilla JS?
(open point -> when you use alert() or create a function and use it, isn't this abstraction?)
First let's explain abstraction: Think about an RC car. You know hoe to make it move forward, backwards, left and right but you do not know how all the gears move in order for these actions to happen. That is abstraction. Using something without knowing all the complicated details.
Encapsulation and abstraction are like opposite things. Think of a coffee machine. It has a cover. This cover is the encapsulation. It has all the gears and protects them form unintended use. On the cover there are some buttons. This is Abstraction. You click a button and it makes coffee. You do not see how this happens under the cover.
so, to answer the question, abstraction most probably does not apply to javascript, because we don't have abstract class and we do not have interfaces. We get those in Typescript
Which programming language tools help us realize encapsulation and which abstraction?
In Javascript encapsulation can be provided by Closures. Closures can be used to create private variables and functions. They encapsulate state within a function's scope making them inaccessible from outside. In Java, we have Access Modifiers, that control which parts of a class are available from outside (private, protected, public)
In Typescript encapsulation is provided by access modifiers In Typescript abstraction can be provided by interfaces. Typescript allows you to define interfaces that define the structure of objects.They help abstract away the details of object and focus on their capabilities.
Can Javascript be considered as an Object Oriented language?
Javascript can be considered as an OP language and FP language. We have Inheritance (Prototypes): prototypes are the mechanism in javascript by which JS objects inherit features one from another. In example when we define an object literal, this object has also access to methods like ".toString()" We have encapsulation: it can be provider by closures We have abstraction (TS): interfaces - does not apply to JS We have polymorphism:
How can we implement encapsulation in pure js?
We should use closures, or module pattern.
What is polymorphism? Simplify and provide examples
It is different implementation of the same method based on the instance it runs. In example we have a button click method. When it run on the tv remote it does one thing. When it runs on the radio it does a different thing.
Or lets imagine in javascript that we have a class called Area and it has a method called getAreaSize Then we can have two other two other classes called Circle and Square that extend Area those two can have a definition of getAreaSize for themselves. So the same method but different implementation. WHat is the benefit? In example when we loop through the array of Areas, we can call the method for each item, which will refer to its own implementation
class Item { getSize() { // to be implemented by subclasses } }
class Circle extends Shape { constructor(radius) { super(); this.radius = radius; }
getSize() { return Math.Pi * this.radius * this.radius } }
class Square extends Shape { constructor(side) { super(); this.side = side; }
getSize() { return this.side * this.side } }
const allItems = [new Circle(4), new Square(5)];
allItems.forEach( item => { console.log('Size: ', item.getSize()) })
Note that there is not need to have inheritance. It can be two different classes, like Dog and Car and the both have a method called move()
How does polymorphism link to SOLID principles?
SOLID principles is a set of five design principles that aim to create maintainable and scalable software. Polymorphism is an important concept that supports those principles.
Interface Aggregation Principle: By defining small interfaces that have only one or two methods, classes can implement only the methods they need and objects can be treated polymorphically through these interfaces without unnecessary dependencies.
In other words: We should have many small interfaces instead of huge ones. In this principle polymorphism plays a big role. So, inside the program we create plenty of small interfaces like: printable, writeable, displayable etc with only one or two methods. And this allows to build flexible and scalable
In OOP, how would you organize the communication between objects?
- Observers
- Events and event handling
- Message Passing
- Encapsulation
In example, React Observable is related to the concept of organizing communication between components in the React framework. While React does not provide this on its core, we can integrate libraries like RxJs that do this. In React these observables can be used to handle updates when new data arrives
In React the communication between components is done through:
- props and state
- callbacks
- context API
- Redux
What are the disadvantages of OOP?
- The main disadvantage of OOP is its main advantage. State management. Each object in a time has some state and this is hard to debug, because different objects stay coupled in the system and may be on different state.
- Complexity: In large projects, the use of classes, inheritance and polymorphism make the code harder to understand and maintain.
- hard architecture - it requires more time to design architecture correctly. inheritance can go wrong
What is Functional Programming
Functional Programming is a programming paradigm where functions are used to create software.
Why is Javascript considered a FP language?
Because functions are first class citizens, which means that javascript allows you to use functions in the same way you can use variables, objects and any other kind of data. We can assign actions to variables, return function from other function (currying), pass functions to other function as arguments. We can consider function as any other data Typescript
What are the principles of functional programming?
- first class citizens
- pure functions: [deterministic and no side effects]. It means that given the same input you always get the same output and it does not change anything outside of it
- immutability: it means that once you create something you cannot change it
Is it possible in JS to create a really immutable object?
Not really. We can do Object.freeze which can do a shallow immutable object, but if there is nesting, then is can be mutated
How can can we have immutable objects?
We can use external libraries like ImmutableJs (open sourced from Facebook). Bonus: You may not need ImmutableJs if you make sure you return a new object or array when you want to modify something. Also we can enforce immutable code in compile time bu using Typescript. We can define an interface with readonly properties or using "as const". However there is still the possibility to mutate if there is nested object.
Why is immutability so important in functional programming?
Because FP paradigm uses pure functions. A pure function works as indepedent function that gives the same output for the same input. Also referential transparency is the same as immutability. It means that the function call can be replaced with its result and this will not change the behavior of your software.
What is considered a side effect?
Pure functions should not be aware of any external environment. Anything that is not injected directly in the function should not be used. A side effect is any action from that function that changes something in the external environment. In example a console.log changes the window state (the console of the window)
Provide some practical examples of function composition
In React whenever we have a component that renders another component, is composition. We also have Higher order components We can also pass components we do not know ahead, by using the special prop children Redux combineReducers function: to combine all reducers
Currying, Memoization and Partial Application
Memoization: Caching the result of a function for a given input. This is why immutable functions are important Currying: A technic where a function that takes multiple arguments is transformed into a series of functions that take one argument each. Each of this new function returns another function that takes the next argument Partial application: In partial application, you get multiple parameters or one parameter and return another function that takes those parameters
Where could partial application be helpful?
When we want to add an event handler and pass an extra argument except for the event
In what cases you choose OOP or FP or Reactive Programming?
When you are limited in memory you should use OP When you have systems that it is critical to debug, when u may need to reboot and have everything working easily (NASA example) When you have event based systems, or systems with a lot of users interactions, then Reactive Programming could be preferred