Skip to content

Commit

Permalink
Update Rule “interfaces-abstract-classes/rule” (#7936)
Browse files Browse the repository at this point in the history
  • Loading branch information
Calinator444 authored Feb 9, 2024
1 parent 1eacb55 commit 482a314
Showing 1 changed file with 5 additions and 49 deletions.
54 changes: 5 additions & 49 deletions rules/interfaces-abstract-classes/rule.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,52 +17,38 @@ guid: dc2f25d6-46b4-4917-8328-70459c7f8165
---
When embarking on understanding a new codebase, it's crucial to identify the components that offer the most insight with the least effort. Interfaces and Abstract Classes stand out as the pillars that uphold the structure and behavior of the code, providing a clear overview without delving into the intricate details of implementation.


<!--endintro-->


`youtube: https://youtu.be/9j-uECGrqSI`


**Video: How to Read Source Code: Interfaces and abstract classes | Luke Mao | SSW Rules (6 min)**


### Why interfaces and abstract classes are important


Interfaces and abstract classes provide 2 main insights by helping you know:


* Data structures and their relationships​
* What functionality a class can provide


### What is an interface?


An interface defines properties and methods that a class must implement. It only provides the method signatures without any implementation details.​


Imagine we have objects of different shapes, such as circles and rectangles. Each shape can have its own color. Also, all shapes have an area that can be calculated. However, the calculation changes depending on the type of shape. For example, a circle calculates area using PI and radius, while a rectangle uses the width and height.​


So, we can define an interface called `Shape`:


```typescript
interface Shape {
color: string;
area(): number;
}
```


It declares a property called color and a method called area. The specific implementation will be inside the `Circle` and `Rectangle` class.​


#### Circle class


```typescript
class Circle implements Shape {
color: string;
Expand All @@ -81,10 +67,8 @@ class Circle implements Shape {
}
```


#### Rectangle class


```typescript
class Rectangle implements Shape {
color: string;
Expand All @@ -105,25 +89,21 @@ class Rectangle implements Shape {
}
```


These implementations can then be instantiated separately depending on the kind of shape that is needed.


```typescript
const circle = new Circle('red', 10);
circle.color; // red
circle.area(); // 314.1592653589793
console.log(circle.color); // outputs "red"
console.log(circle.area()); // outputs "314.1592653589793"


const rectangle = new Rectangle('blue', 5, 10);
rectangle.color; // blue
rectangle.area(); // 50
console.log(rectangle.color); // outputs "blue"
console.log(rectangle.area()); // outputs "50"
```


Its important to note that you can get interfaces wrong. For example you could not use interfaces or you could over use interfaces


```typescript
interface Animal {
eat(): void;
Expand All @@ -145,30 +125,22 @@ interface Bulldog extends Dog {
}
```


::: bad
Figure: Bad Example - When you over abstract, it becomes harder to find the right place to add new methods
:::


The role of the interface is to reduce coupling. For example, if you need to change how the area is calculated for a rectangle but not for a circle, you can do so without affecting how the circle behaves. It also improves scalability. Every time a new shape is added, there is already a set of well-defined methods, making it easier to add the new class.​


Interfaces are contracts that dictate what a class can do without specifying how it does it. They are crucial in defining behavior and ensuring consistency across different implementations.


### What is an abstract class?


An abstract class is a class that cannot be instantiated and serves as a blueprint for creating derived classes. It's similar to an interface but allows you to provide fully implemented methods, not just method declarations.​


Imagine various payment methods, such as bank transfer and credit card payment. ​


We can define an abstract class called Payment:


```typescript
abstract class Payment {
amount: number;
Expand All @@ -188,16 +160,12 @@ abstract class Payment {
}
```


It's similar to an interface. It defines a property called `amount` and a method called `processPayment`. `processPayment` will change depending on the payment method. There is also a `receipt` method, and unlike the `processPayment` method, it should be the same for all kinds of payment methods. This `receipt` method can be directly implemented in an abstract class but not in an interface.​


This abstract class would then be used to define different types of payments, such as Bank Transfer or Credit Card Payment:


#### Bank Transfer class


```typescript
class BankTransfer extends Payment {
processPayment(): void {
Expand All @@ -206,10 +174,8 @@ class BankTransfer extends Payment {
}
```


#### Credit Card Payment class


```typescript
class CreditCardPayment extends Payment {
processPayment(): void {
Expand All @@ -218,10 +184,8 @@ class CreditCardPayment extends Payment {
}
```


These implementations can then be instantiated separately depending on the kind of payment that is needed.


```typescript
const bankTransfer = new BankTransfer(512);
bankTransfer.processPayment(); // Processing a bank transfer of $512
Expand All @@ -233,27 +197,19 @@ creditCardPayment.processPayment(); // Processing a credit card payment of $1024
creditCardPayment.receipt(); // Payment of $1024 has been processed.
```


The primary purpose of abstract classes is to solve code reuse problems. If we don't use a Payment abstract class here, the `BankTransfer` and `CreditCardPayment` classes will have duplicate receipt methods.​


### When to focus on interfaces and abstract classes


The best time to read interfaces and abstract classes is:


* After understanding the business problem
* Before diving into implementation details


### Other Benefits


There more benefits to using interfaces and abstract classes such as in Unit Testing which you can read [here](https://www.mehulkar.com/blog/2015/05/unit-testing-interface-vs-implementation/)


### Conclusion


Knowing when and how to read interfaces and abstract classes streamlines your learning process and equips you with a framework to understand the broader system architecture and its components.
Knowing when and how to read interfaces and abstract classes streamlines your learning process and equips you with a framework to understand the broader system architecture and its components.

0 comments on commit 482a314

Please sign in to comment.