Skip to content

Commit fc3c073

Browse files
committed
Finished SOLID - SMART module
1 parent fe39c24 commit fc3c073

37 files changed

Lines changed: 1090 additions & 12 deletions
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# SOLID - SMART
2+
3+
***
4+
5+
## Single Responsability [S]
6+
7+
This Principle says that each class should have only responsability
8+
9+
In the context of the exercise we are told that a car can do the following actions:
10+
11+
* start(): starts the engine
12+
* stop(): stops the engine and applies the brakes
13+
* accelerate(speed): increases the speed of the car by a specified value
14+
* shift_gears_up(): shifts up to the next gear
15+
* shift_gears_down(): shifts down to the previous gear
16+
* reverse(): puts the transmission in reverse gear
17+
* turn_wheel(angle): turns the wheels by a specified angle
18+
* straighten_wheels(): returns the wheels to a straight-ahead position
19+
* apply_force_on_brakes(force): applies a specified force to the brakes
20+
* apply_emergency_brakes(): applies the brakes with maximum force for an emergency stop
21+
22+
Given this example, I imediately identify that the only responsability of the car was to enforce the car actions.<br>
23+
Nothing more, tha car is only the concept, the car is the enforcer, but he will do nothing more.<br>
24+
The respponsability of the car is only to serve as a concept to execute the actions (link the car components)<br>
25+
26+
***
27+
28+
So I also identify which actions are compatible:
29+
30+
start & stop (both affect the Motor)
31+
accelerate, apply_force_on_brakes & apply_emergency_brakes (both have to do with the speed of the car, although also with the brakes)
32+
shift_gears_up, shift_gears_down, reverse (affect the transmission gear)
33+
turn_wheel & straighten_wheels (affect the wheels)
34+
35+
The only "tricky" case in this example is the accelerate, apply_force_on_brakes & apply_emergency_brakes, because they have two responsabilities<br>
36+
Change the car speed and actionate the brakes (if you concider that applying force on the brakes is an action)<br>
37+
For this you can divide in a third object to handle the speed, and other objects which will use this object to modify the speed<br>
38+
Accelerator will simply increase the speed<br>
39+
While the brakes will decrease the speed according to the force<br>
40+
41+
***
42+
43+
## Open/Closed [O]
44+
45+
This principle basically says that the code should be open for extension and closed for modification.
46+
47+
In other words, if you want to add functionalities you should be able to do it without changing the current code.
48+
49+
In the case of the example, the Command class should be designed so that you can add Command derivates without having to change the original Command.
50+
51+
This is possible by using for example the protected properly and virtual, so that new Classes will automatically have access to the Base class and can implement method calls over the Base.
52+
53+
***
54+
55+
## Liskov substitution [L]
56+
57+
The Liskov Substitution Principle (LSP) is a fundamental concept in object-oriented programming (OOP) that states that objects of a superclass should be replaceable with objects of its subclasses without affecting the correctness of the program. In simpler terms, if S is a subtype of T, then objects of type T may be replaced with objects of type S without altering any of the desirable properties of the program.
58+
59+
Let's consider the example from the subject: a superclass called Shape and subclasses Rectangle, Circle, and Triangle.
60+
61+
62+
Now, let's examine how these classes adhere to the Liskov Substitution Principle:
63+
64+
Substitutability: Any method that expects a Shape should be able to work with any subclass of Shape without knowing the difference.
65+
66+
Preservation of behavior: If we replace an instance of Shape with an instance of its subclass (Rectangle, Circle, or Triangle), the behavior should remain consistent.
67+
68+
***
69+
70+
## Interface segregation [I]
71+
72+
The Interface Segregation Principle (ISP) in object-oriented design states that a class should not be forced to implement interfaces it doesn't use.<br>
73+
Instead of one large interface, clients should be able to depend only on the methods they use.<br>
74+
Essentially, it promotes the idea of smaller, more focused interfaces.
75+
76+
In this case, the interface of Employee is making sure only the essential methods are implemented by the implementing classes.
77+
78+
For example, calculateSalary must be implemented by EVERYONE because it is essencial and each employee has a different salary.
79+
Now executeWorkday might be similar for some users, which I identified.
80+
There is a generic executeWorkday which just counts the day as worked. But if an employee should register the total amount of hours and not the whole day he can implement this method (because it's virtual) and change it's functionality, but only if needed, respecting the Interface segregation.
81+
Others might just count a day as worked not counting hours, like contractEmployees.
82+
83+
***
84+
85+
## Dependency Inversion [D]
86+
87+
Dependency Inversion Principle (DIP) is one of the five SOLID principles of object-oriented programming. It states that high-level modules should not depend on low-level modules; both should depend on abstractions. Additionally, abstractions should not depend on details; rather, details should depend on abstractions.
88+
89+
In simpler terms, DIP encourages decoupling between modules by introducing an abstraction layer. This allows for more flexibility and easier maintenance of the codebase because changes in one module do not necessarily affect other modules directly.
90+
91+
Instead of implementing the date method inside the classes, I decided to implement another interface an IHeader so that the Loggers can choose to have a header, but they don't need to know how to use the header, or what the header should do, they just use the interface, and the .header() to get the header!
92+
93+
***

42/Piscine Object/Module 03 - SMART/ex02/Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ INC_PATH = .
99

1010
SRC_PATH = .
1111

12-
SRC = ./main.cpp
12+
SRC = ./main.cpp \
13+
./triangle.cpp \
14+
./circle.cpp \
15+
./rectangle.cpp \
16+
./point.cpp \
17+
./shape.cpp \
1318

1419
CFLAGS = -Wall -Wextra -Werror -std=c++98 -pedantic -fsanitize=address #-O3 -g -fsanitize=leak
1520

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//***************************//
2+
//*Template by pulgamecanica*//
3+
//***************************//
4+
5+
#include <math.h>
6+
7+
#include "circle.hpp"
8+
#define PI 3.1416
9+
10+
Circle::Circle(Point xx, float rad):
11+
Shape("circle"), xx_(xx), rad_(rad) {
12+
;
13+
}
14+
15+
Circle::~Circle() {
16+
std::cout << "Circle destroyed" << std::endl;
17+
}
18+
19+
float Circle::area() const {
20+
return PI * (pow(rad_, 2));
21+
}
22+
23+
24+
float Circle::perimeter() const {
25+
return 2 * PI * rad_;
26+
}
27+
28+
Point Circle::getCenter() const {
29+
return xx_;
30+
}
31+
32+
float Circle::getRad() const {
33+
return rad_;
34+
}
35+
36+
std::ostream& operator<<(std::ostream& s, const Circle& c) {
37+
s << "Xo: "<< c.getCenter() << " Rad: " << c.getRad();
38+
return (s);
39+
}
40+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//***************************//
2+
//*Template by pulgamecanica*//
3+
//***************************//
4+
5+
#ifndef __CIRCLE_HPP__
6+
# define __CIRCLE_HPP__
7+
8+
#include <iostream>
9+
10+
#include "shape.hpp"
11+
#include "point.hpp"
12+
13+
class Circle: public Shape {
14+
public:
15+
Circle(Point xx, float rad);
16+
~Circle();
17+
float area() const;
18+
float perimeter() const;
19+
Point getCenter() const;
20+
float getRad() const;
21+
private:
22+
Point xx_;
23+
float rad_;
24+
};
25+
std::ostream& operator<<(std::ostream&, const Circle&);
26+
#endif

42/Piscine Object/Module 03 - SMART/ex02/main.cpp

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,54 @@
33
//***************************//
44

55
#include "ex02.inc"
6+
#include "shape.hpp"
7+
#include "rectangle.hpp"
8+
#include "circle.hpp"
9+
#include "triangle.hpp"
10+
11+
void printShapeByRef(const Shape & fig) {
12+
std::cout << fig << std::endl;
13+
}
14+
15+
void printShapeByPointer(const Shape* fig_ptr) {
16+
std::cout << *fig_ptr << std::endl;
17+
}
18+
619

720
int main(void)
821
{
922
if (DEBUG)
1023
std::cout << "Debug ON!" << std::endl;
11-
std::cout << "Hello Friend\nPulgamecanica greets you :D\n";
24+
std::cout << BLUE << "- - - Normal Rectangle - - -" << ENDC << std::endl;
25+
Rectangle rect(Point(42, 42.42), Point(4.2, 0.42));
26+
std::cout << rect << std::endl;
27+
printShapeByRef(rect);
28+
std::cout << BLUE << "- - - Polymorphic Rectangle - - -" << ENDC << std::endl;
29+
{
30+
Shape * fig = &rect;
31+
printShapeByPointer(fig);
32+
}
33+
std::cout << BLUE << "- - - Normal Circle - - -" << ENDC << std::endl;
34+
Circle circ(Point(2.4, 4.2), 42);
35+
std::cout << circ << std::endl;
36+
printShapeByRef(circ);
37+
std::cout << BLUE << "- - - Polymorphic Circle - - -" << ENDC << std::endl;
38+
{
39+
Shape * fig = &circ;
40+
printShapeByPointer(fig);
41+
}
42+
std::cout << BLUE << "- - - Normal Triangle - - -" << ENDC << std::endl;
43+
// https://www.triangle-calculator.com/
44+
Triangle tri(Point(2.4, 4.2), Point(4.5, 8.2), Point(3.0, 0));
45+
std::cout << tri << std::endl;
46+
printShapeByRef(tri);
47+
std::cout << BLUE << "- - - Polymorphic Triangle - - -" << ENDC << std::endl;
48+
{
49+
Shape * fig = &tri;
50+
printShapeByPointer(fig);
51+
}
52+
std::cout << BLUE << "- - - - - - - - - - - - - - - - -" << ENDC << std::endl;
53+
54+
1255
return (0);
1356
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//***************************//
2+
//*Template by pulgamecanica*//
3+
//***************************//
4+
5+
#include "point.hpp"
6+
7+
Point::Point(float x, float y): x(x), y(y) {
8+
;
9+
}
10+
11+
Point::~Point() {
12+
;
13+
}
14+
15+
std::ostream& operator<<(std::ostream& s, const Point& p) {
16+
s << "(" << p.x << ", " << p.y << ")";
17+
return s;
18+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//***************************//
2+
//*Template by pulgamecanica*//
3+
//***************************//
4+
5+
#ifndef __POINT_HPP__
6+
# define __POINT_HPP__
7+
8+
#include <iostream>
9+
10+
struct Point {
11+
Point(float x, float y);
12+
~Point();
13+
float x;
14+
float y;
15+
};
16+
std::ostream& operator<<(std::ostream&, const Point&);
17+
18+
#endif
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//***************************//
2+
//*Template by pulgamecanica*//
3+
//***************************//
4+
5+
#include "rectangle.hpp"
6+
7+
Rectangle::Rectangle(Point trc, Point size):
8+
Shape("rectangle"), trc_(trc), size_(size) {
9+
;
10+
}
11+
12+
Rectangle::~Rectangle() {
13+
std::cout << "Rectangle destroyed" << std::endl;
14+
}
15+
16+
float Rectangle::area() const {
17+
return size_.x * size_.y;
18+
}
19+
20+
float Rectangle::perimeter() const {
21+
return (size_.x * 2) + (size_.y * 2);
22+
}
23+
24+
Point Rectangle::getTopRight() const {
25+
return trc_;
26+
}
27+
28+
Point Rectangle::getSize() const {
29+
return size_;
30+
}
31+
32+
std::ostream& operator<<(std::ostream& s, const Rectangle& rect) {
33+
s << "TRC: " << rect.getTopRight() << " Size: " << rect.getSize();
34+
return (s);
35+
}
36+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//***************************//
2+
//*Template by pulgamecanica*//
3+
//***************************//
4+
5+
#ifndef __RECTANGLE_HPP__
6+
# define __RECTANGLE_HPP__
7+
8+
#include <iostream>
9+
10+
#include "shape.hpp"
11+
#include "point.hpp"
12+
13+
class Rectangle: public Shape {
14+
public:
15+
Rectangle(Point trc, Point size);
16+
~Rectangle();
17+
Point getTopRight() const;
18+
Point getSize() const;
19+
float perimeter() const;
20+
float area() const;
21+
private:
22+
Point trc_;
23+
Point size_;
24+
};
25+
std::ostream& operator<<(std::ostream&, const Rectangle&);
26+
#endif
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//***************************//
2+
//*Template by pulgamecanica*//
3+
//***************************//
4+
5+
#include "shape.hpp"
6+
7+
Shape::Shape(const std::string& type): type_(type) {
8+
;
9+
}
10+
11+
Shape::~Shape() {
12+
std::cout << "Shape " << type_ << " destroyed" << std::endl;
13+
}
14+
15+
const std::string Shape::getType() const {
16+
return type_;
17+
}
18+
19+
std::ostream& operator<<(std::ostream& s, const Shape& fig) {
20+
s << fig.getType() << " area: " << fig.area() << " perimeter: " << fig.perimeter();
21+
return (s);
22+
}
23+

0 commit comments

Comments
 (0)