Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
September 17, 2019 11:17 am GMT

SOLID PRINCIPLES: To start with Object-oriented programming

Hi everyone, today I would like to discuss about something solid.
solid? Of course, no! Not that solid.
wait... ah maybe exactly that solid!

I went to an interview today and was asked this question about "Solid principles". And I was like "um... not really sure" which means "I don't know what you are talking about".
On my way out of the room, I felt like I was definitely in a need of researching about solid principles to properly start off going further to object-oriented programming world in the right direction.

So today, I would like to cover this topic with a few basic definitions and easy examples to help ourselves out to understand the concept in general.

1) What and why : SOLID PRINCIPLES

Alt Text

SOLID stands for..

S.O.L.I.D is an acronym for the first five object-oriented design(OOD)** principles** by Robert C. Martin.

Alt Text

It is just really about a set of principles that we can keep in mind in terms of coding, refining and structuring code.

SOLID does..

By reading it, I had no idea what it is supposed to mean,by all mean. As far as understand, These principles are all about making it easier and cleaner for developers to develop software which are easy to maintain and modify when the scale of it is going bigger and get more complicated. So we can really understand this concept as a way of approaching object-oriented programming by cutting down the unnecessary part and organize the code in a way of refining and re-structuring.

2) Dive into : SOLID PRINCIPLES

First Principle: Single-responsibility Principle

"A class should have one and only one reason to change, meaning that a class should have only one job."

It is as simple as it sounds which means that a class should only perform a single job not the multiple jobs in a same class.
Let's have a look at the example down.

class Book {  protected $Author;  public getAuthor($Author) {    return $this->Author;  }  public function formatJson() {    return json_encode($this->getAuthor());  }}

What do you think, do you think you are getting a hang of it?
We can clearly see that Class named 'Book' is performing more than one job which are getting the author of a book and also it is encoding the output to Json format. But what if we want to have an output in a different format not only Json? In that case, we probably have to write few more lines to add more method for that or modifying the existing code. It could look like a minor work at the moment because this example we have right here is extremely simple but imagine there are hundreds or even thousands of classes, it would be better off preventing confusions in advance by implementing these principles.

So, the approach that we can take would be something like

class Book {  protected $Author;  public getAuthor($Author){    return $this->Author;  }}class JsonBookForm {    public function format(Book $Author) {        return json_encode($Author->getAuthor());    }}

By doing that, If we want to get a different type of output then we don't need to make a change in the Book class directly.

Second Principle: Open-closed Principle

"Objects or entities should be open for extension, but closed for modification."

I know it is getting boring, but this is actually meaning that classes should be extended to change functionality, rather than being modified. It should be a way of extending its functionality when they want to add more options and it should not be the case just changing the existing code directly.

There is a common example which is like down below.

class Triangle{  public $width;  public $height;}class Board {  public $triangles= [];  public function calculateArea() {    $area = 0;    foreach ($this->triangles as $triangle) {      $area += $triangle->width * $triangle->height* 1/2;    }  }}

We have a Triangle class that contains the data for a Triangle which are width and height, and a Board class that is used as a array of Triangle objects.
This code at the moment looks absolute fine but when you think about shape and calculating area function, maybe you might want to use this function later for other shapes as well not only just triangle to increase the efficiency. At the moment, these lines of codes are not allowing this by limiting the Board class only working with the Triangle class.

The approach we can try here is

interface Shape {   public function area();}class Triangle implements Shape {  public function area() {    return $this->width * $this->height *1/2;  }}class Circle implements Shape {  public function area() {    return $this->radius * $this->radius * pi();  }}
class Board {  public $shapes;  public function calculateArea() {    $area = 0;    foreach ($this->shapes as $shape) {      $area+= $shape->area();    }    return $area;  }}

In this way, we don't need to specify the name of the class in the class name Board, so whenever we want to add more properties something like Rectangle we can easily add a class named itself and implements Shape interface so that we can use area() in a Board class.

Third Principle: Liskov substitution principle

"Let q(x) be a property provable about objects of x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T."

Okay, I know it does sound like my math teach back in high school. can't really follow.
But look at this picture here
Alt Text
Does this look familiar? We have probably seen this picture in school and I am sure your math teach must have mentioned it. Where this graph can be implied in our world is something related to the previous example. Shapes.

Speaking of shapes, there are a lot of shapes, right? There are circles, and triangles and rectangles and square.. wait, we all know that rectangle and square are similar but not same right?
Rectangle includes square in terms of the fact that rectangle needs more conditions to be square. So it would be like this.

Alt Text
***oops I put the name the other way around here!!!
The common code we can do here would be

class Rectangle {  public function setW($w) {       $this->width = $w;  }  public function setH($h) {      $this->height = $h;  }  public function Area() {      return $this->height * $this->width;  }}
class Square extends Rectangle {  public function set($w) {    $this->width = $w;    $this->height = $w;  }  public function setH=($h) {    $this->height = $h;    $this->width = $h;  }}

But did you realize that there are multiple lines looking exactly same? and considering the fact that in this tutorial, we are doing our best to make the code maintainable and efficient, this way should be avoided and rather trying this way.

interface Setshape {  public function setH($h);  public function setW($w);  public function Area();}class Rectangle implements Setshape ;class Square implements Setshape ;

By doing this way, we don't have to write the same code over and over again, and we can just simple implements the interface to the class.

Forth Principle: Interface segregation principle

"A client should never be forced to implement an interface that it doesn't use or clients shouldn't be forced to depend on methods they do not use."

We are almost there, the forth principle means that classes should not be forced to implement interfaces they do not use. For example, let's say there are some classes looking like

interface Employee {  public function generatereport()  public function clockin()  public function clockout()  public function customerservice()  public function getPaid()}

And let's say there is a duty manager who is doing the most of the functions above but not clockin and clockout because the could possibly get salary not hourly so for them those two functions will be never used. To follow the principle here once again, we should approach it this way.

interface Generalemployee{ public function clockin() public function clockout()}interface Employee{ public function customerservice() public function getPaid()}interface management{  public function generatereport()}class Staff implements Generalemployee, Employee{}class Manager implements Employee, management{}

Last Principle: Dependency Inversion principle

"Entities must depend on abstractions not on concretions. It states that the high level module must not depend on the low level module, but they should depend on abstractions."

I will go straight to the example for this one

class Getuserlists {    private $dbConn;    public function __construct(MySQLConn, $dbConn) {        $this->dbConn= $dbConn;    }}

It is common mistake because according to the hierarchy structure, Getuserlists class is higher module and MySQLConn is a lower module, however, you can easily notice that the class is depending on MySQLConn thoroughly and it would confuse later if we want to use other database not just MySQL.

So the solution on this would be...

interface DbConnectionInterface {    public function connect();} class MySqlConn implements DbConnectionInterface {    public function connect() {}}class Getuserlists {    private $dbConn;    public function __construct(DbConnectionInterface $dbConn) {        $this->dbConn= $dbConn;    }}

According to the little snippet above, you can now see that both the high level and low level modules depend on abstraction.

Congratulations!! We took a step towards Object-oriented programming world!!

Alt Text

Conclusion

SOLID principles seemed to be a very confusing at first, and still will have some more struggles in order to make it to mine and get to the point where I can use comfortably without even realizing but It is always to have some guidelines we can follow, isn't it?


Original Link: https://dev.to/ham8821/solid-principles-to-start-with-object-oriented-programming-1e49

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To