SlideShare una empresa de Scribd logo
1 de 69
Fernando Escolar
@fernandoescolar
fernando.escolar@tokiota.com
Code Smells
Y
A
X B
public void CalculateTotalPrice()
{
//calculates taxes
var taxes = 0.0m;
foreach (var product in this.productLines)
{
// ...
taxes += product.Price / product.TaxesPercent * 100;
}
//calculates price
var price = 0.0m;
foreach (var product in this.productLines)
{
// ...
price += product.Price * product.Unit;
}
this.TotalPrice = price + taxes;
}
public void CalculateTotalPrice()
{
var taxes = this.CalculateTaxes();
var price = this.CalculatePrice();
this.TotalPrice = price + taxes;
}
public decimal CalculateTaxes()
{
// ...
return taxes;
}
public decimal CalculatePrice()
{
// ...
return price;
}
public class User
{
// ...
}
public class Product
{
// ...
}
public class ProductLine
{
// ...
}
public class Order
{
// ...
}
public class Customer
{
private string name;
private string lastName;
private string streetType;
private string streetName;
private string streetNumber;
private string floorNumber;
private string doorNumber;
private string postalCode;
private string city;
private string state;
private string country;
private string phone;
private string email;
}
public class Customer {
private string name;
private string lastname;
private string phone;
private string email;
private Address address;
}
public class Address {
private string streetType;
private string streetName;
private string streetNumber;
private string floorNumber;
private string doorNumber;
private string postalCode;
private string city;
private string state;
private string country;
}
public void Draw(int x, int y, int width, int heigth,
int borderSize,
Color borderColor, Color backgroundColor)
{
// ...
}
public void Draw(BorderedRectangle rectangle)
{
// ...
}
public class Rectangle
{
public int X { get; set; }
public int Y { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public Color Color { get; set; }
}
public class BorderedRectangle : Rectangle
{
public int BorderSize { get; set; }
public Color BorderColor { get; set; }
}
class Rectangle
{
public void Draw(int x, int y, int width, int height,
int borderSize, Color borderColor, Color backgroundColor)
{
this.DrawRectable(x, y, width, height, backgroundColor);
this.DrawRectangleBorder(x, y, width, height, borderSize,
borderColor);
}
private void DrawRectable(int x, int y, int width, int height,
Color color)
{
// ...
}
private void DrawRectangleBorder(int x, int y, int width,
int height, int borderSize, Color color)
{
// ...
}
public class Rectangle
{
public int X { get; set; }
public int Y { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public Color Color { get; set; }
public void Draw() { /* ... */ }
}
public class BorderedRectangle : Rectangle
{
public int BorderSize { get; set; }
public Color BorderColor { get; set; }
public void Draw() { base.Draw(); /* ... */ }
}
namespace MyTech
{
class MyTechConnection { }
class MyTechConnectionHndl { }
class Order {
public bool Order(OrderRequest request) { /* ... */ }
}
class Inv
{
int Do(int a, string s, double d) { /* ... */ }
}
}
namespace MyTechnology
{
class Connection { }
class ConnectionHandler { }
class OrderManager {
public bool Request(Order order) { /* ... */ }
}
class Invoice
{
bool Pay(int userId, string account, double price) {
/* ... */
}
}
}
private const decimal USDolarChange = 1.13845m;
private const decimal BritishPoundsChange = 0.739373275m;
public enum MoneyTypes { Euro, USDolar, BritishPounds };
public decimal ConvertValue(decimal money, MoneyTypes type)
{
switch (type)
{
case MoneyTypes.Euro:
return money;
case MoneyTypes.USDolar:
return money * USDolarChange;
case MoneyTypes.BritishPounds:
return money * BritishPoundsChange;
default:
return money;
}
}
public class Euro {
public decimal Value { get; set; }
public virtual decimal GetConvertedValue()
{
return this.Value;
}
}
public class USDolar : Euro {
public override decimal GetConvertedValue()
{
return this.Value * USDolarChange;
}
}
public class BritishPounds : Euro {
public override decimal GetConvertedValue()
{
return this.Value * BritishPoundsChange;
}
}
public decimal GetDiscount()
{
var basePrice = quantity * itemPrice;
if (quantity > 1000)
return basePrice * 0.95;
else if (quantity > 500)
return 20.0d;
}
public decimal GetDiscount()
{
if (quantity > 1000)
return CalculateBasePrice() * 0.95;
else if (quantity > 500)
return 20.0d;
}
private decimal CalculateBasePrice()
{
return quantity * itemPrice;
}
abstract class Membership
{
public abstract IEnumerable<User> GetUsers();
public abstract IEnumerable<Profile> GetProfiles();
public abstract User Auth(string user, string password);
public abstract IEnumerable<Profile> GetUserProfile(User user);
}
class MyMembership : Membership
{
public override IEnumerable<User> GetUsers() {
throw new NotImplementedException(); }
public override IEnumerable<Profile> GetProfiles() {
throw new NotImplementedException(); }
public override User Auth(string user, string password) {
// ...
}
public override IEnumerable<Profile> GetUserProfile(User user) {
// ...
}
}
¿Liskov?
abstract class Membership
{
public abstract User Auth(string user, string password);
public abstract IEnumerable<Profile> GetUserProfile(User user);
}
class MyMembership : Membership
{
public override User Auth(string user, string password)
{
// ...
}
public override IEnumerable<Profile> GetUserProfile(User user)
{
// ...
}
}
class TokiotaService
{
// ...
}
class MicrosoftService
{
// ...
}
public IEnumerable<TokiotaItem> GetTokiotaItems()
{
return this.tokiotaService.GetProyects();
}
public IEnumerable<MicrosoftItem> GetMicrosoftItems()
{
return this.microsoftService.GetPartnerCollaborations();
}
class Item { /* ... */ }
class IAdapter
{
IEnumerable<Item> GetItems();
}
class MicrosoftAdapter : IAdapter { /* ... */ }
class TokiotaAdapter : IAdapter { /* ... */ }
public IEnumerable<Item> GetItems(IAdapter adapter)
{
return adapter.GetItems();
}
public decimal CalculateTotalPrice() {
if (this.isChristmas) {
return this.CalculateChristmas();
}
else {
if (this.HasDiscount()) {
return this.CalculateDiscounted(this.GetDiscount());
}
else {
if (this.isTimeOfSale) {
return this.CalculateDiscounted(this.GetSalesDiscount());
}
else
{
return this.CalculateStandard();
}
}
}
}
public decimal CalculateTotalPrice()
{
if (this.isChristmas)
return this.CalculateChristmas();
if (this.HasDiscount())
return this.CalculateDiscounted(this.GetDiscount());
if (this.isTimeOfSale)
return this.CalculateDiscounted(this.GetSalesDiscount());
return this.CalculateStandard();
}
class Customer
{
public string Name { get; set; }
public string LastName { get; set; }
public string toXML()
{
return @"<Customer>" +
"<Name>" +
this.Name +
"</Name>" +
"<LastName>" +
this.LastName +
"</LastName>" +
"</Customer>";
}
}
Open-Close?
class Customer
{
private readonly CustomerXmlSerializer serializer = ...;
public string Name { get; set; }
public string LastName { get; set; }
public string toXML()
{
return this.serializer.Serialize(this);
}
}
class CustomerXmlSerializer : XmlSerializer
{
public string Serialize(Customer c)
{
var sb = new StringBuilder();
sb.Append(this.StartTag("Customer"));
sb.Append(this.WriteTag("Name", c.Name));
sb.Append(this.WriteTag("LastName", c.LastName));
sb.Append(this.EndTag("Customer"));
}
class OrderManager
{
decimal CalculateOrderPrice(Product[] products, int[] units) {
/* ... */
}
}
class OrderViewModel
{
public Product[] Products { get; set; }
public int[] Units { get; set; }
}
class OrderService
{
void SendOrder(Product[] products, int[] units) { /* ... */ }
}
¿Y si queremos
añadir IVA?
class Order
{
public Product[] Products { get; set; }
public int[] Units { get; set; }
public decimal GetPrice() { /* ... */ }
}
class OrderManager
{
decimal CalculateOrderPrice(Order order) {
return order.GetPrice();
}
}
class OrderViewModel
{
public Order Order { get; set; }
}
class OrderService
{
void SendOrder(Order order) { /* ... */ }
}
class Vehicle { }
class Car : Vehicle { }
class Truck : Vehicle { }
class Motorbike : Vehicle { }
class VehicleXmlSerializer { }
class CarXmlSerializer : VehicleXmlSerializer { }
class TruckXmlSerializer : VehicleXmlSerializer { }
class MotorbikeXmlSerializer : VehicleXmlSerializer { }
Vehicle
Class
Car
Truck
Motorbike
Xml
Car
Truck
MotorBike
class VehicleXmlSerializer
{
public VehicleXmlSerializer(IToXmlStrategy[] strategies) { }
}
interface IToXmlStrategy { }
interface IToXmlStrategy<T> where T : Vehicle { }
class CarToXmlStrategy : IToXmlStrategy<Car> { }
class TruckTOXmlStrategy : IToXmlStrategy<Truck> { }
class MotorbikeToXmlStrategy : IToXmlStrategy<Motorbike> { }
class OrderViewModel
{
decimal CalculateTax() { return totalPrice * 0.21; }
}
class Invoice
{
decimal ShowTax() { return order.TotalPrice * 0.21; }
}
class ViewModel
{
public decimal Tax { get { return 21.0; } }
}
static class Globals
{
public const decimal TaxPercent = 21.0m;
public const decimal TaxDelta = TaxPercent / 100;
}
class OrderViewModel
{
decimal CalculateTax() { return totalPrice * Globals.TaxDelta; }
}
class Invoice
{
decimal ShowTax() { return order.TotalPrice * Globals.TaxDelta; }
}
class ViewModel
{
public decimal Tax { get { return Globals.TaxPercent; } }
}
class LazyClass
{
public static string FormatName(string name,
string lastname, string surname)
{
return string.Format("{1}, {0} ({2})",
name, lastname, surname);
}
}
Solo un método
llamada desde
solo un lugar
class CustomerInfo
{
public string Name { get; set; }
public string LastName { get; set; }
public string Surname { get; set; }
public override string ToString()
{
return string.Format("{1}, {0} ({2})",
this.Name,
this.LastName, this.Surname);
}
}
class Settings
{
public string Name { get; set; }
public string Host { get; set; }
public bool UseSsl { get; set; }
public int NumerOfConnections { get; set; }
}
class SettingsManager
{
public void Save(Settings settings) { /* ... */ }
public Settings Load() { /* ... */ }
}
Una clase con las propiedades y
otra con los métodos
class Settings
{
public string Name { get; set; }
public string Host { get; set; }
public bool UseSsl { get; set; }
public int NumerOfConnections { get; set; }
public void Save() { /* ... */ }
public void Load() { /* ... */ }
}
class MyClass
{
public int MyProperty { get; set; }
public string Name { get; set; }
public void Process() { /* ... */ }
public void Send() { /* ... */ }
}
class MyClassOld
{
public string Name { get; set; }
public void Process() { /* ... */ }
}
class MyClass
{
public int MyProperty { get; set; }
public string Name { get; set; }
public void Process() { /* ... */ }
public void Send() { /* ... */ }
}
class CustomerController {
public ActionResult Edit(Customer customer) {
if (Model.IsValid) {
this.customerRepository.InsertOrUpdate(customer);
this.customerRepository.Save();
return RedirectToAction("Index");
}
return View();
}
}
class EmployeeController {
public ActionResult Edit(Employee employee) {
if (Model.IsValid) {
this.employeeRepository.InsertOrUpdate(employee);
this.employeeRepository.Save();
return RedirectToAction("Index");
}
return View();
}
}
class ControllerBase<TEntity> where TEntity : IEntity
{
IRepository<Employee> repository;
public ActionResult Edit(TEntity entity)
{
if (Model.IsValid)
{
this.repository.InsertOrUpdate(entity);
this.repository.Save();
return RedirectToAction("Index");
}
return View();
}
}
class CustomerController : ControllerBase<Customer> { }
class EmployeeController : ControllerBase<Employee> { }
public interface ITextFormatStrategy { string Format(string input); }
public class CommentTextFormatContext {
private ITextFormatStrategy strategy;
public CommentTextFormatContext(ITextFormatStrategy strategy) {
this.strategy = strategy;
}
public int ExecuteStrategy(string input) {
return strategy.Format(input);
}
}
public class RemoveHtmlTagsStrategy : ITextFormatStrategy {
public string Format(string input) {
return Regex.Replace(input, @"<[^>]*>", string.Empty);
}
}
¿Solo una estrategia? YAGNI
public class Comment
{
public void SetMessage(string message)
{
this.Text = Regex.Replace(message, @"<[^>]*>", string.Empty);
}
}
// calculates the total price of the order
public decimal Calculate()
{
// in christmas time
if (DateTime.Now >= new DateTime(DateTime.Now.Year, 12, 25)
&& DateTime.Now <= new DateTime(DateTime.Now.Year + 1, 1, 5))
{
// it has a discount of 10%
return this.TotalPrice * 0.9;
}
else
{
return thisw.TotalPrice;
}
}
public decimal CalculateOrderTotalPrice()
{
if (IsChirstmasTime()) {
return this.ApplyDiscountPercentage(10);
}
else {
return this.TotalPrice;
}
}
private decimal ApplyDiscountPercentage(int percentage)
{
return this.TotalPrice * (100 - percentage) / 100;
}
private static bool IsChirstmasTime()
{
return DateTime.Now >= new DateTime(DateTime.Now.Year, 12, 25)
&& DateTime.Now <= new DateTime(DateTime.Now.Year + 1, 1, 5);
}
public class Product
{
public bool HasBeenOrdered(Order order)
{
return order.Products.Contains(this);
}
}
public class Order
{
public List<Product> Products { get; set; }
}
public class Product { }
public class Order
{
public List<Product> Products { get; set; }
public bool HasBeenOrdered(Product product)
{
return this.Products.Contains(product);
}
}
public class Customer
{
public string Name { get; set; }
public string LastName { get; set; }
public string PhoneNumber { get; set; }
public string Address { get; set; }
}
public class Order
{
private Customer customer;
public string GetSummary()
{
var summary = string.Format("{0} {1}n{2}n{3}",
this.customer.Name,
this.customer.LastName,
this.customer.PhoneNumber,
this.customer.Address);
summary += "n" + this.TotalPrice + " €";
return summary;
}
}
public class Customer
{
public string Name { get; set; }
public string LastName { get; set; }
public string PhoneNumber { get; set; }
public string Address { get; set; }
public override string ToString() {
return string.Format("{0} {1}n{2}n{3}",
this.Name,
this.LastName,
this.PhoneNumber,
this.Address);
}
}
public class Order
{
private Customer customer;
public string GetSummary() {
return this.customer.ToString() + "n" + this.TotalPrice + " €";
}
}
public decimal CalculateTotalPrice()
{
/* ... */
if (this.Customer.Address.Country.IsEuropean)
{
/* ... */
}
/* ... */
}
public decimal CalculateTotalPrice()
{
/* ... */
if (this.Customer.IsEuropean)
{
/* ... */
}
/* ... */
}
public class Customer
{
public bool IsEuropean
{
get
{
return this.Address.IsEuropean;
}
}
}
class MyConnection
{
private SqlConnection connection = new SqlConnection();
public string ConnectionString
{
get { return this.connection.ConnectionString; }
}
public void Open()
{
this.connection.Open();
}
public MyCommand CreateCommand()
{
return new MyCommand(this.connection.CreateCommand());
}
}
SqlConnection connection = new SqlConnection();
class XmlSerializer
{
public string StartTagString { get; set; }
public string EndTagString { get; set; }
public XmlSerializer()
{
StartTagString = "<{0}>";
EndTagString = "</{0}>";
}
protected string WriteTag(string name, string value) {
return StartTag(name) + value + EndTag(name);
}
protected string StartTag(string name) {
return string.Format(StartTagString, name);
}
protected string EndTag(string name) {
return string.Format(EndTagString, name);
}
}
class XmlSerializer
{
private const string StartTagString = "<{0}>";
private const string EndTagString = "</{0}>";
protected string WriteTag(string name, string value)
{
return StartTag(name) + value + EndTag(name);
}
protected string StartTag(string name)
{
return string.Format(StartTagString, name);
}
protected string EndTag(string name)
{
return string.Format(EndTagString, name);
}
}
Fernando Escolar
@fernandoescolar
fernando.escolar@tokiota.com
¡¡¡Si te ha gustado no olvides
rellenar la encuesta!!!
Thanks
Y
A
X B

Más contenido relacionado

La actualidad más candente

Iniciacion en Togaf - Global Knowledge
Iniciacion en Togaf - Global KnowledgeIniciacion en Togaf - Global Knowledge
Iniciacion en Togaf - Global KnowledgeGlobal Knowledge
 
Togaf introduction and core concepts
Togaf introduction and core conceptsTogaf introduction and core concepts
Togaf introduction and core conceptsPaul Sullivan
 
Practical Application of Business Architecture
Practical Application of Business Architecture Practical Application of Business Architecture
Practical Application of Business Architecture Enterprise Architects
 
Introducción a JUnit
Introducción a JUnitIntroducción a JUnit
Introducción a JUnitIker Canarias
 
Arquitectura empresarial - Enfoque sistémico para el desarrollo de sistemas d...
Arquitectura empresarial - Enfoque sistémico para el desarrollo de sistemas d...Arquitectura empresarial - Enfoque sistémico para el desarrollo de sistemas d...
Arquitectura empresarial - Enfoque sistémico para el desarrollo de sistemas d...Julio Vasquez Paragulla
 
Gerencia de procesos- Arquitectura Empresarial
Gerencia de procesos- Arquitectura EmpresarialGerencia de procesos- Arquitectura Empresarial
Gerencia de procesos- Arquitectura EmpresarialMarta Silvia Tabares
 
Business Architecture and Enterprise Planning
Business Architecture and Enterprise PlanningBusiness Architecture and Enterprise Planning
Business Architecture and Enterprise Planningi3 Technologies, Inc
 
Overview of Information Framework
Overview of Information FrameworkOverview of Information Framework
Overview of Information FrameworkAyub Qureshi
 
EA foundations (Views, Repository, Artifacts and Metamodel)
EA foundations (Views, Repository, Artifacts and Metamodel)EA foundations (Views, Repository, Artifacts and Metamodel)
EA foundations (Views, Repository, Artifacts and Metamodel)Mohamed Zakarya Abdelgawad
 
Enterprise Architecture Implementation And The Open Group Architecture Framew...
Enterprise Architecture Implementation And The Open Group Architecture Framew...Enterprise Architecture Implementation And The Open Group Architecture Framew...
Enterprise Architecture Implementation And The Open Group Architecture Framew...Alan McSweeney
 
Enterprise architecture-career-path
Enterprise architecture-career-pathEnterprise architecture-career-path
Enterprise architecture-career-pathSim Kwan Choo
 
Introduction to Business Architecture - Part 2
Introduction to Business Architecture - Part 2Introduction to Business Architecture - Part 2
Introduction to Business Architecture - Part 2Alan McSweeney
 
Successful Digital Transformation starts with a well defined Strategy
Successful Digital Transformation starts with a well defined StrategySuccessful Digital Transformation starts with a well defined Strategy
Successful Digital Transformation starts with a well defined StrategyGlen Alleman
 
IT4IT™ - Managing the Business of IT
IT4IT™ - Managing the Business of ITIT4IT™ - Managing the Business of IT
IT4IT™ - Managing the Business of ITReal IRM
 
Calidad En El Sector Servicios
Calidad En El Sector ServiciosCalidad En El Sector Servicios
Calidad En El Sector Serviciosjenyfer
 
Casos de Uso de Arquitectura Empresarial
Casos de Uso de Arquitectura Empresarial Casos de Uso de Arquitectura Empresarial
Casos de Uso de Arquitectura Empresarial Gabriel Gasparolo
 
1.4. alineación de los servicios de tecnologías de informacion con las politi...
1.4. alineación de los servicios de tecnologías de informacion con las politi...1.4. alineación de los servicios de tecnologías de informacion con las politi...
1.4. alineación de los servicios de tecnologías de informacion con las politi...Alexis Gils
 
Creating Enterprise Value from Business Architecture
Creating Enterprise Value from Business ArchitectureCreating Enterprise Value from Business Architecture
Creating Enterprise Value from Business Architectureiasaglobal
 
Architecting Next Generatio IT Operating Models Using IT4IT and SFIA
Architecting Next Generatio IT Operating Models Using IT4IT and SFIAArchitecting Next Generatio IT Operating Models Using IT4IT and SFIA
Architecting Next Generatio IT Operating Models Using IT4IT and SFIASukumar Daniel
 
Enterprise Architecture .vs. Collection of Architectures in Enterprise
Enterprise Architecture .vs. Collection of Architectures in EnterpriseEnterprise Architecture .vs. Collection of Architectures in Enterprise
Enterprise Architecture .vs. Collection of Architectures in EnterpriseYan Zhao
 

La actualidad más candente (20)

Iniciacion en Togaf - Global Knowledge
Iniciacion en Togaf - Global KnowledgeIniciacion en Togaf - Global Knowledge
Iniciacion en Togaf - Global Knowledge
 
Togaf introduction and core concepts
Togaf introduction and core conceptsTogaf introduction and core concepts
Togaf introduction and core concepts
 
Practical Application of Business Architecture
Practical Application of Business Architecture Practical Application of Business Architecture
Practical Application of Business Architecture
 
Introducción a JUnit
Introducción a JUnitIntroducción a JUnit
Introducción a JUnit
 
Arquitectura empresarial - Enfoque sistémico para el desarrollo de sistemas d...
Arquitectura empresarial - Enfoque sistémico para el desarrollo de sistemas d...Arquitectura empresarial - Enfoque sistémico para el desarrollo de sistemas d...
Arquitectura empresarial - Enfoque sistémico para el desarrollo de sistemas d...
 
Gerencia de procesos- Arquitectura Empresarial
Gerencia de procesos- Arquitectura EmpresarialGerencia de procesos- Arquitectura Empresarial
Gerencia de procesos- Arquitectura Empresarial
 
Business Architecture and Enterprise Planning
Business Architecture and Enterprise PlanningBusiness Architecture and Enterprise Planning
Business Architecture and Enterprise Planning
 
Overview of Information Framework
Overview of Information FrameworkOverview of Information Framework
Overview of Information Framework
 
EA foundations (Views, Repository, Artifacts and Metamodel)
EA foundations (Views, Repository, Artifacts and Metamodel)EA foundations (Views, Repository, Artifacts and Metamodel)
EA foundations (Views, Repository, Artifacts and Metamodel)
 
Enterprise Architecture Implementation And The Open Group Architecture Framew...
Enterprise Architecture Implementation And The Open Group Architecture Framew...Enterprise Architecture Implementation And The Open Group Architecture Framew...
Enterprise Architecture Implementation And The Open Group Architecture Framew...
 
Enterprise architecture-career-path
Enterprise architecture-career-pathEnterprise architecture-career-path
Enterprise architecture-career-path
 
Introduction to Business Architecture - Part 2
Introduction to Business Architecture - Part 2Introduction to Business Architecture - Part 2
Introduction to Business Architecture - Part 2
 
Successful Digital Transformation starts with a well defined Strategy
Successful Digital Transformation starts with a well defined StrategySuccessful Digital Transformation starts with a well defined Strategy
Successful Digital Transformation starts with a well defined Strategy
 
IT4IT™ - Managing the Business of IT
IT4IT™ - Managing the Business of ITIT4IT™ - Managing the Business of IT
IT4IT™ - Managing the Business of IT
 
Calidad En El Sector Servicios
Calidad En El Sector ServiciosCalidad En El Sector Servicios
Calidad En El Sector Servicios
 
Casos de Uso de Arquitectura Empresarial
Casos de Uso de Arquitectura Empresarial Casos de Uso de Arquitectura Empresarial
Casos de Uso de Arquitectura Empresarial
 
1.4. alineación de los servicios de tecnologías de informacion con las politi...
1.4. alineación de los servicios de tecnologías de informacion con las politi...1.4. alineación de los servicios de tecnologías de informacion con las politi...
1.4. alineación de los servicios de tecnologías de informacion con las politi...
 
Creating Enterprise Value from Business Architecture
Creating Enterprise Value from Business ArchitectureCreating Enterprise Value from Business Architecture
Creating Enterprise Value from Business Architecture
 
Architecting Next Generatio IT Operating Models Using IT4IT and SFIA
Architecting Next Generatio IT Operating Models Using IT4IT and SFIAArchitecting Next Generatio IT Operating Models Using IT4IT and SFIA
Architecting Next Generatio IT Operating Models Using IT4IT and SFIA
 
Enterprise Architecture .vs. Collection of Architectures in Enterprise
Enterprise Architecture .vs. Collection of Architectures in EnterpriseEnterprise Architecture .vs. Collection of Architectures in Enterprise
Enterprise Architecture .vs. Collection of Architectures in Enterprise
 

Destacado

Social networking as an esol strategy
Social networking as an esol strategySocial networking as an esol strategy
Social networking as an esol strategyRhonda101
 
Express business health check
Express business health checkExpress business health check
Express business health checkQuek Joo Chay
 
ульяновск саммит
ульяновск саммитульяновск саммит
ульяновск саммитfpolicy_ru
 
Project proposal
Project proposalProject proposal
Project proposalMoeed Awais
 
Деинституционализацията в България!
Деинституционализацията в България!Деинституционализацията в България!
Деинституционализацията в България!CIL - Sofia
 
Presentation1
Presentation1Presentation1
Presentation1kk11711
 
Hjc bb seminar - blackbaud presentation vancouver draft one sept 6 2012
Hjc bb seminar - blackbaud presentation vancouver draft one sept 6 2012Hjc bb seminar - blackbaud presentation vancouver draft one sept 6 2012
Hjc bb seminar - blackbaud presentation vancouver draft one sept 6 2012Ashley Donald
 
Mi carro nuevo - Survey 2012
Mi carro nuevo - Survey 2012Mi carro nuevo - Survey 2012
Mi carro nuevo - Survey 2012RedMasAdv
 
Report of linuxcon japan 2013
Report of linuxcon japan 2013Report of linuxcon japan 2013
Report of linuxcon japan 2013Naruto TAKAHASHI
 
freeCodeCamp Tokyo Meetup #18
freeCodeCamp Tokyo Meetup #18freeCodeCamp Tokyo Meetup #18
freeCodeCamp Tokyo Meetup #18健太 田上
 
Interest only pilot v3 14.12.12
Interest only pilot v3 14.12.12Interest only pilot v3 14.12.12
Interest only pilot v3 14.12.12HML Ltd
 
The "Social" Relationship between Marketing & Recruiting for TMA _ Celinda Ap...
The "Social" Relationship between Marketing & Recruiting for TMA _ Celinda Ap...The "Social" Relationship between Marketing & Recruiting for TMA _ Celinda Ap...
The "Social" Relationship between Marketing & Recruiting for TMA _ Celinda Ap...Celinda Appleby
 
Body paragraph and midtest
Body paragraph and midtestBody paragraph and midtest
Body paragraph and midtestPenyelamatJanda
 
Spring gourmet-dinner
Spring gourmet-dinnerSpring gourmet-dinner
Spring gourmet-dinnerBigAl72
 

Destacado (20)

Social networking as an esol strategy
Social networking as an esol strategySocial networking as an esol strategy
Social networking as an esol strategy
 
Express business health check
Express business health checkExpress business health check
Express business health check
 
ульяновск саммит
ульяновск саммитульяновск саммит
ульяновск саммит
 
Project proposal
Project proposalProject proposal
Project proposal
 
Деинституционализацията в България!
Деинституционализацията в България!Деинституционализацията в България!
Деинституционализацията в България!
 
Presentation1
Presentation1Presentation1
Presentation1
 
Hjc bb seminar - blackbaud presentation vancouver draft one sept 6 2012
Hjc bb seminar - blackbaud presentation vancouver draft one sept 6 2012Hjc bb seminar - blackbaud presentation vancouver draft one sept 6 2012
Hjc bb seminar - blackbaud presentation vancouver draft one sept 6 2012
 
Mi carro nuevo - Survey 2012
Mi carro nuevo - Survey 2012Mi carro nuevo - Survey 2012
Mi carro nuevo - Survey 2012
 
Report of linuxcon japan 2013
Report of linuxcon japan 2013Report of linuxcon japan 2013
Report of linuxcon japan 2013
 
freeCodeCamp Tokyo Meetup #18
freeCodeCamp Tokyo Meetup #18freeCodeCamp Tokyo Meetup #18
freeCodeCamp Tokyo Meetup #18
 
Interest only pilot v3 14.12.12
Interest only pilot v3 14.12.12Interest only pilot v3 14.12.12
Interest only pilot v3 14.12.12
 
The "Social" Relationship between Marketing & Recruiting for TMA _ Celinda Ap...
The "Social" Relationship between Marketing & Recruiting for TMA _ Celinda Ap...The "Social" Relationship between Marketing & Recruiting for TMA _ Celinda Ap...
The "Social" Relationship between Marketing & Recruiting for TMA _ Celinda Ap...
 
Freshwater matters Nov 2015
Freshwater matters Nov 2015 Freshwater matters Nov 2015
Freshwater matters Nov 2015
 
Body paragraph and midtest
Body paragraph and midtestBody paragraph and midtest
Body paragraph and midtest
 
Klíma 7 előnye
Klíma  7 előnyeKlíma  7 előnye
Klíma 7 előnye
 
Public Speaking For Scientists
Public Speaking For ScientistsPublic Speaking For Scientists
Public Speaking For Scientists
 
Spring gourmet-dinner
Spring gourmet-dinnerSpring gourmet-dinner
Spring gourmet-dinner
 
Thackeray ehfi sefs8
Thackeray ehfi sefs8Thackeray ehfi sefs8
Thackeray ehfi sefs8
 
Guns_in_the_Workplace
Guns_in_the_WorkplaceGuns_in_the_Workplace
Guns_in_the_Workplace
 
Examen
ExamenExamen
Examen
 

Similar a DotNet Conference: code smells

Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...
Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...
Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo....NET Conf UY
 
Code generation for alternative languages
Code generation for alternative languagesCode generation for alternative languages
Code generation for alternative languagesRafael Winterhalter
 
Combatendo code smells em Java
Combatendo code smells em Java Combatendo code smells em Java
Combatendo code smells em Java Emmanuel Neri
 
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDBTDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDBtdc-globalcode
 
How to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy CodeHow to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy CodeDaniel Wellman
 
Refactoring - Mejorando el diseño del código existente
Refactoring - Mejorando el diseño del código existenteRefactoring - Mejorando el diseño del código existente
Refactoring - Mejorando el diseño del código existenteMariano Sánchez
 
TDC2016SP - Trilha .NET
TDC2016SP - Trilha .NETTDC2016SP - Trilha .NET
TDC2016SP - Trilha .NETtdc-globalcode
 
14. Java defining classes
14. Java defining classes14. Java defining classes
14. Java defining classesIntro C# Book
 
assignmentTwoCar.javaassignmentTwoCar.javapackage assignmentTw.docx
assignmentTwoCar.javaassignmentTwoCar.javapackage assignmentTw.docxassignmentTwoCar.javaassignmentTwoCar.javapackage assignmentTw.docx
assignmentTwoCar.javaassignmentTwoCar.javapackage assignmentTw.docxssuser562afc1
 
Csharp4 inheritance
Csharp4 inheritanceCsharp4 inheritance
Csharp4 inheritanceAbed Bukhari
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy codeShriKant Vashishtha
 
Dependency Injection and Aspect Oriented Programming presentation
Dependency Injection and Aspect Oriented Programming presentationDependency Injection and Aspect Oriented Programming presentation
Dependency Injection and Aspect Oriented Programming presentationStephen Erdman
 
Java Generics
Java GenericsJava Generics
Java Genericsjeslie
 
Practices For Becoming A Better Programmer
Practices For Becoming A Better ProgrammerPractices For Becoming A Better Programmer
Practices For Becoming A Better ProgrammerSrikanth Shreenivas
 

Similar a DotNet Conference: code smells (20)

Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...
Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...
Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...
 
Solid principles
Solid principlesSolid principles
Solid principles
 
Code generation for alternative languages
Code generation for alternative languagesCode generation for alternative languages
Code generation for alternative languages
 
SOLID Principles
SOLID PrinciplesSOLID Principles
SOLID Principles
 
Combatendo code smells em Java
Combatendo code smells em Java Combatendo code smells em Java
Combatendo code smells em Java
 
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDBTDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
 
How to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy CodeHow to Start Test-Driven Development in Legacy Code
How to Start Test-Driven Development in Legacy Code
 
Functional Programming with C#
Functional Programming with C#Functional Programming with C#
Functional Programming with C#
 
Refactoring - Mejorando el diseño del código existente
Refactoring - Mejorando el diseño del código existenteRefactoring - Mejorando el diseño del código existente
Refactoring - Mejorando el diseño del código existente
 
TDC2016SP - Trilha .NET
TDC2016SP - Trilha .NETTDC2016SP - Trilha .NET
TDC2016SP - Trilha .NET
 
Java doc Pr ITM2
Java doc Pr ITM2Java doc Pr ITM2
Java doc Pr ITM2
 
14. Java defining classes
14. Java defining classes14. Java defining classes
14. Java defining classes
 
assignmentTwoCar.javaassignmentTwoCar.javapackage assignmentTw.docx
assignmentTwoCar.javaassignmentTwoCar.javapackage assignmentTw.docxassignmentTwoCar.javaassignmentTwoCar.javapackage assignmentTw.docx
assignmentTwoCar.javaassignmentTwoCar.javapackage assignmentTw.docx
 
Csharp4 inheritance
Csharp4 inheritanceCsharp4 inheritance
Csharp4 inheritance
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy code
 
Exam2prep
Exam2prepExam2prep
Exam2prep
 
Dependency Injection and Aspect Oriented Programming presentation
Dependency Injection and Aspect Oriented Programming presentationDependency Injection and Aspect Oriented Programming presentation
Dependency Injection and Aspect Oriented Programming presentation
 
OOP Lab Report.docx
OOP Lab Report.docxOOP Lab Report.docx
OOP Lab Report.docx
 
Java Generics
Java GenericsJava Generics
Java Generics
 
Practices For Becoming A Better Programmer
Practices For Becoming A Better ProgrammerPractices For Becoming A Better Programmer
Practices For Becoming A Better Programmer
 

Más de Fernando Escolar Martínez-Berganza

Roslyn: Hello from the other compiler - dotNet Spain Conference 2016
Roslyn: Hello from the other compiler - dotNet Spain Conference 2016Roslyn: Hello from the other compiler - dotNet Spain Conference 2016
Roslyn: Hello from the other compiler - dotNet Spain Conference 2016Fernando Escolar Martínez-Berganza
 

Más de Fernando Escolar Martínez-Berganza (20)

Por qué todo lo que subo a azure esta mal
Por qué todo lo que subo a azure esta malPor qué todo lo que subo a azure esta mal
Por qué todo lo que subo a azure esta mal
 
Deconstrucción de SOLID
Deconstrucción de SOLIDDeconstrucción de SOLID
Deconstrucción de SOLID
 
Gapand - por qué odio git?
Gapand - por qué odio git?Gapand - por qué odio git?
Gapand - por qué odio git?
 
Betabeers - continuous deployment
Betabeers - continuous deploymentBetabeers - continuous deployment
Betabeers - continuous deployment
 
Devops RoadShow: load testing and autoscale
Devops RoadShow: load testing and autoscaleDevops RoadShow: load testing and autoscale
Devops RoadShow: load testing and autoscale
 
Roslyn: Hello from the other compiler - dotNet Spain Conference 2016
Roslyn: Hello from the other compiler - dotNet Spain Conference 2016Roslyn: Hello from the other compiler - dotNet Spain Conference 2016
Roslyn: Hello from the other compiler - dotNet Spain Conference 2016
 
Reconnect 2015 - ALM VSTS
Reconnect 2015 - ALM VSTSReconnect 2015 - ALM VSTS
Reconnect 2015 - ALM VSTS
 
Codemotion 2015 - Unit Testing
Codemotion 2015 - Unit TestingCodemotion 2015 - Unit Testing
Codemotion 2015 - Unit Testing
 
Unit testing en Windows 10
Unit testing en Windows 10Unit testing en Windows 10
Unit testing en Windows 10
 
Las cronicas de redis
Las cronicas de redisLas cronicas de redis
Las cronicas de redis
 
Redis: no solo una caché
Redis: no solo una cachéRedis: no solo una caché
Redis: no solo una caché
 
Foro de Arquitectos: caché en azure a fondo
Foro de Arquitectos: caché en azure a fondoForo de Arquitectos: caché en azure a fondo
Foro de Arquitectos: caché en azure a fondo
 
Codemotion: descubriendo las cachés
Codemotion: descubriendo las cachésCodemotion: descubriendo las cachés
Codemotion: descubriendo las cachés
 
Unit tesing y el mito de los 0 bugs
Unit tesing y el mito de los 0 bugsUnit tesing y el mito de los 0 bugs
Unit tesing y el mito de los 0 bugs
 
We Love Js 6 - Knockout js (with Marc Rubiño)
We Love Js 6 - Knockout js (with Marc Rubiño)We Love Js 6 - Knockout js (with Marc Rubiño)
We Love Js 6 - Knockout js (with Marc Rubiño)
 
Mobile services by @quiqu3
Mobile services by @quiqu3Mobile services by @quiqu3
Mobile services by @quiqu3
 
Javascript no es vietnam
Javascript no es vietnamJavascript no es vietnam
Javascript no es vietnam
 
Where is my beer?
Where is my beer?Where is my beer?
Where is my beer?
 
Coding kihon + Zombie Code Survival Guide
Coding kihon + Zombie Code Survival GuideCoding kihon + Zombie Code Survival Guide
Coding kihon + Zombie Code Survival Guide
 
Level up your skills
Level up your skillsLevel up your skills
Level up your skills
 

Último

Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 

Último (20)

Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 

DotNet Conference: code smells

  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10. public void CalculateTotalPrice() { //calculates taxes var taxes = 0.0m; foreach (var product in this.productLines) { // ... taxes += product.Price / product.TaxesPercent * 100; } //calculates price var price = 0.0m; foreach (var product in this.productLines) { // ... price += product.Price * product.Unit; } this.TotalPrice = price + taxes; }
  • 11. public void CalculateTotalPrice() { var taxes = this.CalculateTaxes(); var price = this.CalculatePrice(); this.TotalPrice = price + taxes; } public decimal CalculateTaxes() { // ... return taxes; } public decimal CalculatePrice() { // ... return price; }
  • 12.
  • 13. public class User { // ... } public class Product { // ... } public class ProductLine { // ... } public class Order { // ... }
  • 14. public class Customer { private string name; private string lastName; private string streetType; private string streetName; private string streetNumber; private string floorNumber; private string doorNumber; private string postalCode; private string city; private string state; private string country; private string phone; private string email; }
  • 15. public class Customer { private string name; private string lastname; private string phone; private string email; private Address address; } public class Address { private string streetType; private string streetName; private string streetNumber; private string floorNumber; private string doorNumber; private string postalCode; private string city; private string state; private string country; }
  • 16. public void Draw(int x, int y, int width, int heigth, int borderSize, Color borderColor, Color backgroundColor) { // ... }
  • 17. public void Draw(BorderedRectangle rectangle) { // ... } public class Rectangle { public int X { get; set; } public int Y { get; set; } public int Width { get; set; } public int Height { get; set; } public Color Color { get; set; } } public class BorderedRectangle : Rectangle { public int BorderSize { get; set; } public Color BorderColor { get; set; } }
  • 18. class Rectangle { public void Draw(int x, int y, int width, int height, int borderSize, Color borderColor, Color backgroundColor) { this.DrawRectable(x, y, width, height, backgroundColor); this.DrawRectangleBorder(x, y, width, height, borderSize, borderColor); } private void DrawRectable(int x, int y, int width, int height, Color color) { // ... } private void DrawRectangleBorder(int x, int y, int width, int height, int borderSize, Color color) { // ... }
  • 19. public class Rectangle { public int X { get; set; } public int Y { get; set; } public int Width { get; set; } public int Height { get; set; } public Color Color { get; set; } public void Draw() { /* ... */ } } public class BorderedRectangle : Rectangle { public int BorderSize { get; set; } public Color BorderColor { get; set; } public void Draw() { base.Draw(); /* ... */ } }
  • 20. namespace MyTech { class MyTechConnection { } class MyTechConnectionHndl { } class Order { public bool Order(OrderRequest request) { /* ... */ } } class Inv { int Do(int a, string s, double d) { /* ... */ } } }
  • 21. namespace MyTechnology { class Connection { } class ConnectionHandler { } class OrderManager { public bool Request(Order order) { /* ... */ } } class Invoice { bool Pay(int userId, string account, double price) { /* ... */ } } }
  • 22.
  • 23. private const decimal USDolarChange = 1.13845m; private const decimal BritishPoundsChange = 0.739373275m; public enum MoneyTypes { Euro, USDolar, BritishPounds }; public decimal ConvertValue(decimal money, MoneyTypes type) { switch (type) { case MoneyTypes.Euro: return money; case MoneyTypes.USDolar: return money * USDolarChange; case MoneyTypes.BritishPounds: return money * BritishPoundsChange; default: return money; } }
  • 24. public class Euro { public decimal Value { get; set; } public virtual decimal GetConvertedValue() { return this.Value; } } public class USDolar : Euro { public override decimal GetConvertedValue() { return this.Value * USDolarChange; } } public class BritishPounds : Euro { public override decimal GetConvertedValue() { return this.Value * BritishPoundsChange; } }
  • 25. public decimal GetDiscount() { var basePrice = quantity * itemPrice; if (quantity > 1000) return basePrice * 0.95; else if (quantity > 500) return 20.0d; }
  • 26. public decimal GetDiscount() { if (quantity > 1000) return CalculateBasePrice() * 0.95; else if (quantity > 500) return 20.0d; } private decimal CalculateBasePrice() { return quantity * itemPrice; }
  • 27. abstract class Membership { public abstract IEnumerable<User> GetUsers(); public abstract IEnumerable<Profile> GetProfiles(); public abstract User Auth(string user, string password); public abstract IEnumerable<Profile> GetUserProfile(User user); } class MyMembership : Membership { public override IEnumerable<User> GetUsers() { throw new NotImplementedException(); } public override IEnumerable<Profile> GetProfiles() { throw new NotImplementedException(); } public override User Auth(string user, string password) { // ... } public override IEnumerable<Profile> GetUserProfile(User user) { // ... } } ¿Liskov?
  • 28. abstract class Membership { public abstract User Auth(string user, string password); public abstract IEnumerable<Profile> GetUserProfile(User user); } class MyMembership : Membership { public override User Auth(string user, string password) { // ... } public override IEnumerable<Profile> GetUserProfile(User user) { // ... } }
  • 29. class TokiotaService { // ... } class MicrosoftService { // ... } public IEnumerable<TokiotaItem> GetTokiotaItems() { return this.tokiotaService.GetProyects(); } public IEnumerable<MicrosoftItem> GetMicrosoftItems() { return this.microsoftService.GetPartnerCollaborations(); }
  • 30. class Item { /* ... */ } class IAdapter { IEnumerable<Item> GetItems(); } class MicrosoftAdapter : IAdapter { /* ... */ } class TokiotaAdapter : IAdapter { /* ... */ } public IEnumerable<Item> GetItems(IAdapter adapter) { return adapter.GetItems(); }
  • 31. public decimal CalculateTotalPrice() { if (this.isChristmas) { return this.CalculateChristmas(); } else { if (this.HasDiscount()) { return this.CalculateDiscounted(this.GetDiscount()); } else { if (this.isTimeOfSale) { return this.CalculateDiscounted(this.GetSalesDiscount()); } else { return this.CalculateStandard(); } } } }
  • 32. public decimal CalculateTotalPrice() { if (this.isChristmas) return this.CalculateChristmas(); if (this.HasDiscount()) return this.CalculateDiscounted(this.GetDiscount()); if (this.isTimeOfSale) return this.CalculateDiscounted(this.GetSalesDiscount()); return this.CalculateStandard(); }
  • 33.
  • 34. class Customer { public string Name { get; set; } public string LastName { get; set; } public string toXML() { return @"<Customer>" + "<Name>" + this.Name + "</Name>" + "<LastName>" + this.LastName + "</LastName>" + "</Customer>"; } } Open-Close?
  • 35. class Customer { private readonly CustomerXmlSerializer serializer = ...; public string Name { get; set; } public string LastName { get; set; } public string toXML() { return this.serializer.Serialize(this); } } class CustomerXmlSerializer : XmlSerializer { public string Serialize(Customer c) { var sb = new StringBuilder(); sb.Append(this.StartTag("Customer")); sb.Append(this.WriteTag("Name", c.Name)); sb.Append(this.WriteTag("LastName", c.LastName)); sb.Append(this.EndTag("Customer")); }
  • 36. class OrderManager { decimal CalculateOrderPrice(Product[] products, int[] units) { /* ... */ } } class OrderViewModel { public Product[] Products { get; set; } public int[] Units { get; set; } } class OrderService { void SendOrder(Product[] products, int[] units) { /* ... */ } } ¿Y si queremos añadir IVA?
  • 37. class Order { public Product[] Products { get; set; } public int[] Units { get; set; } public decimal GetPrice() { /* ... */ } } class OrderManager { decimal CalculateOrderPrice(Order order) { return order.GetPrice(); } } class OrderViewModel { public Order Order { get; set; } } class OrderService { void SendOrder(Order order) { /* ... */ } }
  • 38. class Vehicle { } class Car : Vehicle { } class Truck : Vehicle { } class Motorbike : Vehicle { } class VehicleXmlSerializer { } class CarXmlSerializer : VehicleXmlSerializer { } class TruckXmlSerializer : VehicleXmlSerializer { } class MotorbikeXmlSerializer : VehicleXmlSerializer { } Vehicle Class Car Truck Motorbike Xml Car Truck MotorBike
  • 39. class VehicleXmlSerializer { public VehicleXmlSerializer(IToXmlStrategy[] strategies) { } } interface IToXmlStrategy { } interface IToXmlStrategy<T> where T : Vehicle { } class CarToXmlStrategy : IToXmlStrategy<Car> { } class TruckTOXmlStrategy : IToXmlStrategy<Truck> { } class MotorbikeToXmlStrategy : IToXmlStrategy<Motorbike> { }
  • 40. class OrderViewModel { decimal CalculateTax() { return totalPrice * 0.21; } } class Invoice { decimal ShowTax() { return order.TotalPrice * 0.21; } } class ViewModel { public decimal Tax { get { return 21.0; } } }
  • 41. static class Globals { public const decimal TaxPercent = 21.0m; public const decimal TaxDelta = TaxPercent / 100; } class OrderViewModel { decimal CalculateTax() { return totalPrice * Globals.TaxDelta; } } class Invoice { decimal ShowTax() { return order.TotalPrice * Globals.TaxDelta; } } class ViewModel { public decimal Tax { get { return Globals.TaxPercent; } } }
  • 42.
  • 43. class LazyClass { public static string FormatName(string name, string lastname, string surname) { return string.Format("{1}, {0} ({2})", name, lastname, surname); } } Solo un método llamada desde solo un lugar
  • 44. class CustomerInfo { public string Name { get; set; } public string LastName { get; set; } public string Surname { get; set; } public override string ToString() { return string.Format("{1}, {0} ({2})", this.Name, this.LastName, this.Surname); } }
  • 45. class Settings { public string Name { get; set; } public string Host { get; set; } public bool UseSsl { get; set; } public int NumerOfConnections { get; set; } } class SettingsManager { public void Save(Settings settings) { /* ... */ } public Settings Load() { /* ... */ } } Una clase con las propiedades y otra con los métodos
  • 46. class Settings { public string Name { get; set; } public string Host { get; set; } public bool UseSsl { get; set; } public int NumerOfConnections { get; set; } public void Save() { /* ... */ } public void Load() { /* ... */ } }
  • 47. class MyClass { public int MyProperty { get; set; } public string Name { get; set; } public void Process() { /* ... */ } public void Send() { /* ... */ } } class MyClassOld { public string Name { get; set; } public void Process() { /* ... */ } }
  • 48. class MyClass { public int MyProperty { get; set; } public string Name { get; set; } public void Process() { /* ... */ } public void Send() { /* ... */ } }
  • 49. class CustomerController { public ActionResult Edit(Customer customer) { if (Model.IsValid) { this.customerRepository.InsertOrUpdate(customer); this.customerRepository.Save(); return RedirectToAction("Index"); } return View(); } } class EmployeeController { public ActionResult Edit(Employee employee) { if (Model.IsValid) { this.employeeRepository.InsertOrUpdate(employee); this.employeeRepository.Save(); return RedirectToAction("Index"); } return View(); } }
  • 50. class ControllerBase<TEntity> where TEntity : IEntity { IRepository<Employee> repository; public ActionResult Edit(TEntity entity) { if (Model.IsValid) { this.repository.InsertOrUpdate(entity); this.repository.Save(); return RedirectToAction("Index"); } return View(); } } class CustomerController : ControllerBase<Customer> { } class EmployeeController : ControllerBase<Employee> { }
  • 51. public interface ITextFormatStrategy { string Format(string input); } public class CommentTextFormatContext { private ITextFormatStrategy strategy; public CommentTextFormatContext(ITextFormatStrategy strategy) { this.strategy = strategy; } public int ExecuteStrategy(string input) { return strategy.Format(input); } } public class RemoveHtmlTagsStrategy : ITextFormatStrategy { public string Format(string input) { return Regex.Replace(input, @"<[^>]*>", string.Empty); } } ¿Solo una estrategia? YAGNI
  • 52. public class Comment { public void SetMessage(string message) { this.Text = Regex.Replace(message, @"<[^>]*>", string.Empty); } }
  • 53. // calculates the total price of the order public decimal Calculate() { // in christmas time if (DateTime.Now >= new DateTime(DateTime.Now.Year, 12, 25) && DateTime.Now <= new DateTime(DateTime.Now.Year + 1, 1, 5)) { // it has a discount of 10% return this.TotalPrice * 0.9; } else { return thisw.TotalPrice; } }
  • 54. public decimal CalculateOrderTotalPrice() { if (IsChirstmasTime()) { return this.ApplyDiscountPercentage(10); } else { return this.TotalPrice; } } private decimal ApplyDiscountPercentage(int percentage) { return this.TotalPrice * (100 - percentage) / 100; } private static bool IsChirstmasTime() { return DateTime.Now >= new DateTime(DateTime.Now.Year, 12, 25) && DateTime.Now <= new DateTime(DateTime.Now.Year + 1, 1, 5); }
  • 55.
  • 56. public class Product { public bool HasBeenOrdered(Order order) { return order.Products.Contains(this); } } public class Order { public List<Product> Products { get; set; } }
  • 57. public class Product { } public class Order { public List<Product> Products { get; set; } public bool HasBeenOrdered(Product product) { return this.Products.Contains(product); } }
  • 58. public class Customer { public string Name { get; set; } public string LastName { get; set; } public string PhoneNumber { get; set; } public string Address { get; set; } } public class Order { private Customer customer; public string GetSummary() { var summary = string.Format("{0} {1}n{2}n{3}", this.customer.Name, this.customer.LastName, this.customer.PhoneNumber, this.customer.Address); summary += "n" + this.TotalPrice + " €"; return summary; } }
  • 59. public class Customer { public string Name { get; set; } public string LastName { get; set; } public string PhoneNumber { get; set; } public string Address { get; set; } public override string ToString() { return string.Format("{0} {1}n{2}n{3}", this.Name, this.LastName, this.PhoneNumber, this.Address); } } public class Order { private Customer customer; public string GetSummary() { return this.customer.ToString() + "n" + this.TotalPrice + " €"; } }
  • 60. public decimal CalculateTotalPrice() { /* ... */ if (this.Customer.Address.Country.IsEuropean) { /* ... */ } /* ... */ }
  • 61. public decimal CalculateTotalPrice() { /* ... */ if (this.Customer.IsEuropean) { /* ... */ } /* ... */ } public class Customer { public bool IsEuropean { get { return this.Address.IsEuropean; } } }
  • 62. class MyConnection { private SqlConnection connection = new SqlConnection(); public string ConnectionString { get { return this.connection.ConnectionString; } } public void Open() { this.connection.Open(); } public MyCommand CreateCommand() { return new MyCommand(this.connection.CreateCommand()); } }
  • 63. SqlConnection connection = new SqlConnection();
  • 64. class XmlSerializer { public string StartTagString { get; set; } public string EndTagString { get; set; } public XmlSerializer() { StartTagString = "<{0}>"; EndTagString = "</{0}>"; } protected string WriteTag(string name, string value) { return StartTag(name) + value + EndTag(name); } protected string StartTag(string name) { return string.Format(StartTagString, name); } protected string EndTag(string name) { return string.Format(EndTagString, name); } }
  • 65. class XmlSerializer { private const string StartTagString = "<{0}>"; private const string EndTagString = "</{0}>"; protected string WriteTag(string name, string value) { return StartTag(name) + value + EndTag(name); } protected string StartTag(string name) { return string.Format(StartTagString, name); } protected string EndTag(string name) { return string.Format(EndTagString, name); } }
  • 66.
  • 67.
  • 68.
  • 69. Fernando Escolar @fernandoescolar fernando.escolar@tokiota.com ¡¡¡Si te ha gustado no olvides rellenar la encuesta!!! Thanks Y A X B

Notas del editor

  1. POO/OOP: es un paradigma de programación (como la programación funcional) que propone la creación de diferentes objetos reutilizables, que se popularizó en los años 90 y sus características son: Abstracción: implica la creación de objetos que indican un comportamiento. Por ejemplo una interfaz o una clase base. Encapsulamiento: cuando un objeto contiene todos los métodos y propiedades que comprenden un comportamiento de un tema en concreto, se dice que está encapsulado. Se le pueden añadir niveles de acceso. Herencia: Los objetos no se encuentran aislados, se pueden comunicar entre ellos y pueden formar una estructura jerárquica. Cohesión: significa que cuando encapsulemos el comportamiento, este tenga sentido sobre el mismo tema. Es decir que no mezclemos un objeto que sirva para escribir en consola y para realizar un cálculo complejo matemático. La cohesión añade sentido a la encapsulación. Poliformisfo: son comportamientos diferentes entre objetos distintos que comparten la misma firma: nombre y parámetros. El término “Technical Debt” (Deuda Técnica) fue introducido en 1992 por Ward Cunningham. Es una metáfora que viene a explicar que la falta de calidad en el código fuente de nuestro proyecto, genera una deuda que repercutirá en sobrecostes, tanto en el mantenimiento de un software, como en la propia operativa funcional de la aplicación. Cuando hablamos de un sobrecoste, puede significar desde tener que dedicarle más tiempo o más desarrolladores de los estimados, hasta acumular malestar general y mal ambiente.  SOLID: Que es el acrónimo de 5 principios. Single Responsibility: una clase o función solo debe tener una y solo una razón para existir o ser modificada. Open-Close: el código debe estar abierto a la extensión, pero cerrado a modificaciones. Liskov Substitution: las clases derivadas, deben poder ser sustituidas por su clase base. Interface Segregation: Desgranar las interfaces lo más fino posible, para que sean lo más específicas posible. Dependency Inversion: Hay que depender de las abstracciones no de las concreciones.
  2. En castellano “Code Smells” se traduce como “Olores de código”. Parece ser que fue Kent Beck quien acuñó este concepto a finales de la década de los 90. Pero no se popularizó hasta su aparición en el conocido libro de Martin Fowler: “Refactoring: improving the Design of Existing Code”. ¿Qué son? Los olores del código, son indicadores que señalan, por lo general, un problema más profundo: violaciones de los principios de diseño, con un impacto negativo en la calidad del desarrollo. ¿Qué es calidad? Podríamos decir muchas cosas acerca de la calidad: que tenga un buen diseño, que las métricas de código sean de un valor y otro, que r# no nos llame la atención, que… pero la mejor forma de definir la calidad del código es: “Programa siempre como si el tipo que mantendrá tu código fuera un psicópata violento que sabe donde vives.” - Martin Golding ¿Cómo lo soluciono? Refactoring: Es el proceso de mejorar la calidad del código fuente sin alterar su funcionalidad. Pero… no hay una receta mágica, solo guías. Es fundamental el criterio del desarrollador. Para aplicar los Refactorings se deben crear los Test necesarios para asegurarnos que no vamos a romper nada, y luego realizar los cambios paso a paso..
  3. Rigidez: Cuando algo es rígido significa que no se puede moldear. Un código rígido es aquel que resulta muy difícil de mantener y extender. Fragilidad: Si alguna vez te has encontrado con un programa que al cambiar un detalle, empieza a fallar en muchos puntos donde no has tocado nada, ya te has encontrado con código frágil. Un código que solemos tratar con miedo y bordeamos para modificarlo lo menos posible, generando así más código mal oliente. Inmovilidad: Aunque la solución tiene partes que serían interesantes en otros sistemas, el esfuerzo y riesgo de separarlas del resto del código es tan grande que nunca se reutilizan, se vuelven a escribir. Viscosidad: Podemos definir como viscoso un entorno de desarrollo que es lento e ineficiente. Pero también es viscoso aquel código que es más difícil de usar tal y como está diseñado. Por lo general preferiremos realizar unos “hacks” que programarlo como estaba pensado. Complejidad innecesaria: Contiene elementos muy complejos difíciles de identificar y entender su utilidad, artefactos y funciones que no se usan, y código que no es útil en absoluto. Repeticiones de código: la consecuencia de la maniobra informática más conocida del mundo: copiar y pegar. Crear código repetido a lo largo de toda la aplicación implica que no se ha conseguido identificar esas partes y agruparlas en funciones, clases y contextos comunes. Opacidad: Decimos que un objeto es opaco cuando no se puede ver a través de él. Es decir, un código que es difícil de entender y leer.
  4. The Bloaters: Agrupa smells que indican la existencia de algún aspecto que con el tiempo y el crecimiento pueden volver incontrolable el código. The Object Orientation Abusers: El común denominador de este tipo de smells es que representan casos donde la solución no explota completamente las posibilidades del diseño orientado a objetos. The Change Preventers: Estos smells dificultan la posibilidad de realizar cambios en nuestro software o de simplemente seguir avanzando en el desarrollo. Violan la regla sugerida por Fowler y Beck, que dice que las clases y los posibles cambios deben tener una relación de uno a uno. The Dispensables: Estos Smells tienen en común la existencia de algún elemento innecesario que debería ser eliminado del código fuente. The Couplers: Son smells que alertan sobre problemas en el manejo del acoplamiento entre componentes, pudiendo ser este excesivo y o mal diseñado.
  5. Los métodos largos son mas difíciles de leer, de entender y sobre todo de depurar. Mantener los métodos con pocas líneas ayuda a poder evitar este problema. Si ya tenemos métodos largos podemos considerar separarlos en métodos mas pequeños.
  6. Similar a los métodos largos también son difíciles de leer, entender y depurar. Además las clases grandes muestran otros problemas, como por ejemplo que una única clase contiene demasiadas responsabilidades.
  7. No utilizar una set de variables de tipos primitivos como un sustituto simple para una clase. Si el tipo de datos es lo suficientemente complejo, escribir una clase para que lo represente.
  8. Cuantos mas parámetros reciba un método mas complejo se vuelve de entender y utilizar. Para evitar esto podemos mantener la baja cantidad de parámetros que recibe un método o considerar crear una clase o estructura para pasar estos valores.
  9. Si siempre vemos que la misma información viaja todo el tiempo junta, es muy probable que esos datos sueltos pertenezcan a una misma clase. Considerar integrarlos en la clase que corresponda.
  10. Switchs o cualquier implementación oculta de switch (if, else, if…). Que podrían indicar una falta de utilización de mecanismos de herencia.
  11. El más simple es reemplazar las condiciones usando el polimorfismo. Pero otros refactoring para switch sería los patrones visitor, decorator, strategy, command…
  12. Estar atentos a los objetos que contenga muchos campos opcionales o innecesarios. Si estamos usando un objeto como parámetro de un método asegurarnos que se use todo de él.
  13. Si heredamos de una clase, pero no utilizamos ninguna funcionalidad, ¿para qué vamos a mantener esa herencia? Esto rompe el principio de sustitución de Liskov.
  14. Si dos clases son similares en el interior, pero difieren en el exterior, es probable que se puedan modificar para compartir una interfaz común.
  15. Tener cuidado al detectar o utilizar bloques condicionales muy largos, particularmente los que tienden a crecer con cada cambio que se introduce. Considerar una alternativa orientada a objetos como el uso de un patrón Decorator, Strategy, o State.
  16. Si a través del tiempo, los cambios en una clase necesitan que se toquen muchas partes diferentes de esta, es probable que la clase contenga funcionalidad que no esta relacionada. Considerar aislar las distintas partes en clases diferentes.
  17. Si un cambio en una clase requiere cambios en cascada en muchas otras clases, seguramente nos encontramos en una situación donde una funcionalidad esta mal distribuida.
  18. Cada vez que se realiza una subclase de una clase, se tiene que hacer una sublclase de otra. Considerar unir la jerarquía en una sola clase.
  19. Y también magic strings
  20. Si una clase hace poco y nada, debería eliminarse o combinarse con otra clase.
  21. Evitar clases que solamente almacenen información. Las clases deberían contener información y métodos para operar sobre esta.
  22. Eliminar código que no se utilice. Para eso tenemos sistemas de control de código fuente!
  23. El código duplicado es la peor anti-practica en el desarrollo de software. Eliminar la duplicación siempre que sea posible y estar siempre atento a los casos más sutiles de casi duplicación. DRY!!!
  24. El código que escribimos HOY tiene que ser para resolver los problemas que tenemos HOY. No nos preocupemos por el mañana. YAGNI you aint gonna need it
  25. Hay una línea muy fina entre los comentarios que iluminan y los que oscurecen. Son necesarios? Se puede refactorizar el código para no se necesiten?
  26. Comentar por qué y no el qué
  27. Métodos que realizan un uso extensivo de otra clase, probablemente deberían pertenecer a la otra clase. Deberíamos considerar mover estos métodos a la clase que corresponda.
  28. Estar atentos a las clases que pasan mucho tiempo juntas o que se comunican de modos inapropiados. Las clases deberían conocer lo menos posible unas de otras.
  29. Atentos a las secuencias de llamadas ,posiblemente entre clases, a métodos o variables temporales para obtener datos de rutina. Cualquier intermediario es una dependencia disfrazadas.
  30. Si una clase está delegando todo su trabajo, ¿para qué existe? Elimiar todos los intermediarios. Atencion a las clases que son meramente wrappers sin agregar funcionalidades al framework o contexto.
  31. Cuidado con las clases que exponen innecesariamente su interior. Refactorizar clases para minimizar su interfaz pública. Debe existir una razón de peso para que cada metodo, evento o propiedad que sea pública. Si no existe hay que ocultarlo.