CalisteNia
de Objetos
con C++
Using STD::CPP 2014
[email protected]
@anibal_caceres
Ericsson R&D
O O
Agenda
› ¿DE DÓNDE SALE ESTO?
› LA PROMESA
› EL DESAFÍO
› LAS REGLAS
› CONCLUSIÓN
› ¿ALGUNA PREGUNTA?
Puedes preguntar lo que
desees durante la
presentación…
Calistenia de Objetos con C++ | 2014-10-28 | Página 2
¿De dónde sale esto?
O O
“Object Calisthenics”,
ensayo de Jeff Bay
Calistenia == Ejercicio
Calistenia de Objetos con C++ | 2014-10-28 | Página 3
La Promesa
O O
La programación orientada a objetos
nos librará de nuestro antiguo código
procedural,
permitiéndonos escribir software de
manera incremental, y reusable.
Pues no sé yo si
lo hemos
conseguido…
Calistenia de Objetos con C++ | 2014-10-28 | Página 4
El Desafío
O O
9 reglas estrictas
(y extremas)
.
Escribe unas 1000 líneas de
código siguiéndolas…
…y saca tus propias
conclusiones
(verdadero valor del ejercicio)
,
después usa estas reglas
como guías
(si te parecen beneficiosas)
.
Calistenia de Objetos con C++ | 2014-10-28 | Página 5
O O
No va en
serio…
Las 9 reglas
1. Un nivel de indentación por función.
2. No uses else.
3. Envuelve todas las primitivas y strings.
4. Colecciones de primera clase.
5. Un punto (o flecha) por línea.
6. No abrevies.
7. Mantén todas las entidades pequeñas.
8. Ninguna clase con más de dos variables.
9. No uses “getters” ni “setters”.
Calistenia de Objetos con C++ | 2014-10-28 | Página 6
Regla 1: Un nivel de
indentación por función
O O
Una función gigante suele
significar falta de cohesión
“Single Responsability”
Ventajas al partir: más
reusabilidad y legibilidad
Calistenia de Objetos con C++ | 2014-10-28 | Página 7
Regla 1: Antes
O O
class Horses {
public:
// ...
void shoe() {
for (auto& x : horsesM) {
std::cout << "Shoes for " << x.name << ": " << std::endl;
for (auto i=0; i < 4; i++) {
std::cout << "Put horseshoe " << (i+1) << std::endl;
}
}
std::cout << "All the horses ready!!" << std::endl;
}
private:
std::vector<Horse> horsesM;
}
Calistenia de Objetos con C++ | 2014-10-28 | Página 8
Regla 1: Después
O O
class Horses {
public:
// ...
void shoe() {
for (auto& x : horsesM) {
shoeHorse(x);
}
std::cout << "All the horses ready!!" << std::endl;
}
void shoeHorse(Horse &horse) {
std::cout << "Shoes for " << horse.name << ": " << std::endl;
for (auto i = 0; i < 4; i++) {
std::cout << "Put horseshoe " << (i+1) << std::endl;
}
}
private:
std::vector<Horse> horsesM;
}
Calistenia de Objetos con C++ | 2014-10-28 | Página 9
Regla 2: No uses else
O O
La lógica condicional está
“en nuestras venas”
Duplicidades, repetición
El Polimorfismo puede
ayudar (patrón estrategia)
Calistenia de Objetos con C++ | 2014-10-28 | Página 10
Regla 2: Antes
O O
class Animal {
public:
// ...
std::string talk() {
std::string voice;
if (kindM == “dog")
voice = “Bark!!";
else if (kindM == “sheep")
voice = “Baa!!";
else if (kindM == "horse")
voice = "Neigh!!";
else
voice = "";
return voice;
}
private:
std::string kindM ;
}
Calistenia de Objetos con C++ | 2014-10-28 | Página 11
Regla 2: después
O O
class Animal {
public:
virtual ~Animal(){};
virtual std::string talk() = 0;
}
class Sheep: public Animal {
public:
Sheep() {}
virtual std::string talk() {
return(“Baa!!");
}
} …
class Dog: public Animal {
public:
Dog(std::string name) :
nameM(name) {}
virtual std::string talk() {
return("Bark!!");
}
private:
std::string nameM;
}
Calistenia de Objetos con C++ | 2014-10-28 | Página 12
Regla 3: Envuelve todas
las primitivas y strings
O O
Un int o un string no tienen
semántica asociada
Clase envoltorio: da semántica
y atrae comportamientos
Esto equivale al anti-patrón
“Primitive Obsession”
Calistenia de Objetos con C++ | 2014-10-28 | Página 13
O O
Regla 3: Antes
class Pig: public Animal {
public:
Pig() {
weightM = 0;
}
virtual std::string talk() {
return("Oink!!");
}
void setWeight(float weight) {
weightM = theWeight;
}
float calculatePrice(float kgPrice) {
return kgPrice * weightM;
}
private:
float weightM;
}
Calistenia de Objetos con C++ | 2014-10-28 | Página 14
O O
Regla 3: Después (i)
class Pig: public Animal {
public:
Pig() {
weightM = Weight();
}
virtual std::string talk() {
return("Oink!!");
}
void setWeight(Weight& weight) {
weightM = theWeight;
}
Weight getWeight() {
return weightM;
}
Money calculatePrice(Money& kgPrice) {
return kgPrice * weightM.valueAs(Weight::KG);
}
private:
Weight weightM;
}
Calistenia de Objetos con C++ | 2014-10-28 | Página 15
Regla 3: Después (iI)
O O
class Weight {
public:
enum Unit { KG, LB };
Weight(float amount, Unit unit = Weight::KG) :
amountM(amount), unitM(unit) {}
virtual ~Weight() {}
float valueAs(Unit theUnit) {
return amountM * conversionM[unitM][theUnit];
}
bool operator>(Weight& weight) {
return amountM > weight.valueAs(unitM);
}
private: // KG LB
static const float conversionM[2][2] = { 1.00, 2.20, // KG
0.45, 1.00 }; // LB
float amountM;
Unit unitM;
}
Calistenia de Objetos con C++ | 2014-10-28 | Página 16
Regla 3: Después (III)
O O
class Money {
public:
enum Currency { EUR, GBP, USD };
Money(float amount, Currency currency = Money::EUR) :
amountM(amount), currencyM(currency) {}
virtual ~Money() {}
float valueAs(Currency currency) {
// …Do something fancy, like contact exchange service…
}
Money operator*(float multiplier) {
return Money(amountM*multiplier, currencyM);
}
private:
float amountM;
Currency currencyM;
}
Calistenia de Objetos con C++ | 2014-10-28 | Página 17
Regla 4: Colecciones
de primera clase
O O
Cada colección en su propia
clase, sin más miembros
Filtros, uniones, ... acabarán
en la clase de la colección
Puede cambiarse la colección
sin afectar a sus usuarios
Calistenia de Objetos con C++ | 2014-10-28 | Página 18
O O
Regla 4: Antes
class Farmer {
public:
// ...
void addPig(Pig& pig) {
pigsM.push_back(pig);
}
std::vector<Pig> findPigsToSell() {
std::vector<Pig> pigsToSell;
Weight min(200);
for (auto& x : pigsM) {
if (x.getWeight() > min)
pigsToSell.push_back(x);
}
return pigsToSell;
}
private:
std::vector<Pig> pigsM;
// ...
}
Calistenia de Objetos con C++ | 2014-10-28 | Página 19
Regla 4: Después
O O
class Farmer {
public:
// ...
void addPig(Pig& pig) {
pigsM.add(pig);
}
Pigs findPigsToSell() {
Weight min(200);
return pigsM.biggerThan(min);
}
private:
Pigs pigsM;
}
class Pigs {
public:
Pigs() {}
virtual ~Pigs() {}
void add(Pig &aPig) {
pigsM.push_back(aPig);
}
Pigs biggerThan(Weight& min) {
Pigs toRet;
for (auto& x : pigsM) {
if (x.getWeight() > min)
toRet.add(x);
}
return toRet;
}
private:
std::vector<Pig> pigsM;
};
Calistenia de Objetos con C++ | 2014-10-28 | Página 20
Regla 5: Un punto (o
flecha) por línea
O O
Muchos puntos por línea ≡
responsabilidad desplazada
Objetos que miran dentro de
otros: saben demasiado
Ley de Deméter: “habla sólo
con tus amigos”
Calistenia de Objetos con C++ | 2014-10-28 | Página 21
O O
Regla 5
› Antes:
Dog dog("Toby");
// Let’s sit down the dog.
dog.getLegs().backLegs().down();
› Después:
Dog dog("Toby");
// Let’s sit down the dog.
dog.sitDown();
Calistenia de Objetos con C++ | 2014-10-28 | Página 22
Regla 6: no abrevies
O O
Abreviar dificulta la legibilidad,
y puede ocultar problemas
Suele indicar duplicidad, o
responsabilidad desplazada
En Order no crees un
shipOrder(): mejor ship()
Calistenia de Objetos con C++ | 2014-10-28 | Página 23
Regla 7: Mantén todas
las entidades pequeñas
O O
No más de 50 líneas por
clase (definición)
Agrupar esas clases
pequeñas en namespaces
No más de 10 clases por
namespace
Calistenia de Objetos con C++ | 2014-10-28 | Página 24
Regla 8: ninguna clase
con más de 2 variables
O O
Clases que encapsulan 1 variable
o clases que coordinan 2 variables
Las clases con más de 2 variables
miembro tienen menos cohesión
Modelo de objetos más eficaz con
varios objetos colaboradores
Calistenia de Objetos con C++ | 2014-10-28 | Página 25
Regla 8
› Antes:
class Name {
// ...
std::string first;
std::string middle;
std::string last;
}
› Después:
class Name {
// ...
FamilyName family;
GivenName given;
}
Calistenia de Objetos con C++ | 2014-10-28 | Página 26
O O
class FamilyName {
// ...
std::string family;
};
class GivenName {
// ...
std::vector<std::string> given;
}
Regla 9: No uses
“Getters” ni “Setters”
O O
Encapsulación extrema
Usando get() alejamos
datos y comportamientos
“Tell, don’t ask”
Calistenia de Objetos con C++ | 2014-10-28 | Página 27
© Martin Fowler
Regla 9: Antes
O O
Cow myCow = Cow();
Volume milkToday = Volume(20);
Volume milkTotal =
myCow.getMilk() + milkToday;
myCow.setMilk(totalMilk);
class Cow: public Animal {
public:
Cow() {
milkM = Volume(0);
}
virtual ~Cow();
std::string talk() {
return “Moo!!";
}
Volume getMilk() {
return milkM;
}
void setMilk(Volume& milk) {
mi
Comentarios de: CalisteNia de Objetos con C++ (0)
No hay comentarios