0% found this document useful (0 votes)
36 views

Solid Priciples in Computer Programming

1. The document describes the five SOLID design principles: single responsibility, open/closed, Liskov substitution, interface segregation, and dependency inversion. 2. The single responsibility principle states that a class should have one job or responsibility. 3. The open/closed principle states that code should be open for extension but closed for modification. 3. The document provides examples to illustrate how to apply each of the five SOLID design principles in code.

Uploaded by

riversoto1
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
36 views

Solid Priciples in Computer Programming

1. The document describes the five SOLID design principles: single responsibility, open/closed, Liskov substitution, interface segregation, and dependency inversion. 2. The single responsibility principle states that a class should have one job or responsibility. 3. The open/closed principle states that code should be open for extension but closed for modification. 3. The document provides examples to illustrate how to apply each of the five SOLID design principles in code.

Uploaded by

riversoto1
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

SOLID

Design Principles introduced by Robert C. Martin (uncle Bob)

Nota inclusion de boost using CLion

Esto funciona ojo con <nombre del proyecto> debe aparecer en dos partes


en este caso liskov_substitution

cmake_minimum_required(VERSION 3.9)
project(liskov_substitution)

find_package(Boost 1.66.0 COMPONENTS system filesystem REQUIRED)


include_directories(${Boost_INCLUDE_DIRS})

set(CMAKE_CXX_STANDARD 11)

add_executable(liskov_substitution main.cpp)

target_link_libraries(liskov_substitution ${Boost_LIBRARIES})

Single Responsibility Principle

Class should have just one Responsibility.


Pastelero a tus pasteles.

boost::lexical_cast

En el ejemplo este weón usa boost::lexical_cast


CLion dice: Use std::to_string() instead of
boost::lexical_cast<std::string> .
https://theboostcpplibraries.com/boost.lexical_cast
Boost.LexicalCast provides a cast operator, boost::lexical_cast , that can
convert numbers from strings to numeric types like int or double and vice versa.
boost::lexical_cast is an alternative to functions like std::stoi() ,
std::stod() , and std::to_string() , which were added to the standard library
in C++11.
Journal es una clase en si, no tiene que preocuparse de guardar archivos y cosas relativas, eso lo hace
PersistenceManager

int main()
{
Journal journal{"Dear Diary"};
journal.print();

journal.add("I ate a bug");


journal.add("I cried today");

//journal.save("diary.txt"); NO!

PersistenceManager pm;
pm.save(journal, "diary.txt");

return 0;
}

Open-Closed Principle

Open for extensions but closed for modifications.

struct ProductFilter {
// filtering by color
vector<Product *> by_color(vector<Product *> items, Color color) {
...
}

// filtering by size
vector<Product *> by_size(vector<Product *> items, Size size) {
...
}

// filtering by size and color


vector<Product *> by_size_and_color(vector<Product *> items, Size size,
Color color) {
...
}
};

El weón usa el Specification Patterns que es un Enterprise pattern.

Liskov substitution principle


Subtypes should be immediately substitutable for their base types.

https://www.tomdalling.com/blog/software-design/solid-class-design-the-liskov-substitution-principle/
Ejemplo esto asume que todas las aves vuelan

class Bird {
public:
virtual void setLocation(double longitude, double latitude) = 0;
virtual void setAltitude(double altitude) = 0;
virtual void draw() = 0;
};

No onstante los pinguinos no vuelan

void Penguin::setAltitude(double altitude)


{
//altitude can't be set because penguins can't fly
//this function does nothing
}

If an override method does nothing or just throws an exception, then you’re probably violating the LSP.

El drama es que hay que andar buscando que clases violan esta especificacion y hacer arreglos parches.

La forma correcta es:

//Solution 3: Proper inheritance


class Bird {
public:
virtual void draw() = 0;
virtual void setLocation(double longitude, double latitude) = 0;
};
class FlightfulBird : public Bird {
public:
virtual void setAltitude(double altitude) = 0;
};

Interface Segregation Principle


Not create interfaces that are too large.

Example a Scanner does not FAX.

/* Too general if given as an API for example*/


struct IMachine {
virtual void print(Document &doc) = 0;
virtual void scan(Document &doc) = 0;
virtual void fax(Document &doc) = 0;
};

struct MFP: IMachine {


void print(Document &doc) override {}
void scan(Document &doc) override {}
void fax(Document &doc) override {}
};

struct Scanner:IMachine {
void print(Document &doc) override {}
void scan(Document &doc) override {}
void fax(Document &doc) override {}
};

Instead smaller interfaces

struct IPrinter {
virtual void print(Document &doc) = 0;
};

struct IScanner {
virtual void scan(Document &doc) = 0;
};

struct IFax {
virtual void fax(Document &doc) = 0;
};

// Si quiero algo mas general simplemente


struct IMachine: IPrinter, IScanner {};

struct Machine: IMachine {


void print(Document &doc) override {}
void scan(Document &doc) override {}
};

Dependency Inversion
It’s not about INJECTION, it’s about forming dependencies between objects.

1. High-level modules should not depend on low-level modules.

Both should depend on abstractions.

2. Abstractions should not depend on details.

Details should depend on abstractions.

*Abstractions are Interfaces or Base Classes.

struct RelationShip { // low-level module (or low-level construct)


vector<tuple<Person, Relationship, Person>> relations;

void add_parent_and_child(const Person &parent,const Person &child) {


relations.push_back({parent, Relationship ::parent, child});
relations.push_back({child, Relationship ::child, parent});
}
};
...
...
struct Research { // high-level
// aca esta el problema
// here a high-level is depending on a low-level
Research(RelationShipS &relationships) {
auto &relations = relationships.relations;
// C++17
for (auto &&[first, rel, second] : relations) {
if (first.name == "John" && rel == Relationship::parent) {
cout << "John has a child called " << second.name << endl;
}
}
}
*/
};

Aca arriba Research (which is high-level) depends on RelationShipS (which is low-level). Cambios
en RelationShipS pueden estopearlo todo.

Solucion, incorporar esta abstraccion:

struct RelationshipBrowser {
virtual vector<Person> find_all_children_of(const string &name) = 0;
};

y ahora

struct RelationShipS: RelationshipBrowser {


vector<Person> find_all_children_of(const string &name) {
vector<Person> result;

for(auto &&[first, rel, second]: relations) {


if (first.name == "John" && rel == Relationship::parent) {
result.push_back(second);
}
}
return result;
}
}

y asi Research (que es high-level) deja de depender de RelationShip

struct Research { // high-level

// arreglo, ahora solo depende de RelationshipBrowser


Research(RelationshipBrowser &browser) {
for (auto &child: browser.find_all_children_of("John")) {
cout << "John has a child called " << child.name << endl;
}
}
};

You might also like