SlideShare a Scribd company logo
1 of 69
Download to read offline
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

More Related Content

What's hot

Sql com sql server básico - Bóson treinamentos
Sql com sql server básico - Bóson treinamentosSql com sql server básico - Bóson treinamentos
Sql com sql server básico - Bóson treinamentosFábio dos Reis
 
ALL ABOUT DB2 DSNZPARM
ALL ABOUT DB2 DSNZPARMALL ABOUT DB2 DSNZPARM
ALL ABOUT DB2 DSNZPARMIBM
 
Course 102: Lecture 14: Users and Permissions
Course 102: Lecture 14: Users and PermissionsCourse 102: Lecture 14: Users and Permissions
Course 102: Lecture 14: Users and PermissionsAhmed El-Arabawy
 
Oracle basic queries
Oracle basic queriesOracle basic queries
Oracle basic queriesPRAKHAR JHA
 
SQL Tutorial - Basic Commands
SQL Tutorial - Basic CommandsSQL Tutorial - Basic Commands
SQL Tutorial - Basic Commands1keydata
 
Practical Recipes for Daily DBA Activities using DB2 9 and 10 for z/OS
Practical Recipes for Daily DBA Activities using DB2 9 and 10 for z/OSPractical Recipes for Daily DBA Activities using DB2 9 and 10 for z/OS
Practical Recipes for Daily DBA Activities using DB2 9 and 10 for z/OSCuneyt Goksu
 
Vetores, Matrizes e Strings em C Parte 1
Vetores, Matrizes e Strings em C Parte 1Vetores, Matrizes e Strings em C Parte 1
Vetores, Matrizes e Strings em C Parte 1Elaine Cecília Gatto
 
Oracle Enterprise Manager Cloud Control 13c for DBAs
Oracle Enterprise Manager Cloud Control 13c for DBAsOracle Enterprise Manager Cloud Control 13c for DBAs
Oracle Enterprise Manager Cloud Control 13c for DBAsGokhan Atil
 
Xml transformation-doc
Xml transformation-docXml transformation-doc
Xml transformation-docAmit Sharma
 
DB2 for z/OS Architecture in Nutshell
DB2 for z/OS Architecture in NutshellDB2 for z/OS Architecture in Nutshell
DB2 for z/OS Architecture in NutshellCuneyt Goksu
 
ISPF Recent and Coming Enhancements
ISPF Recent and Coming EnhancementsISPF Recent and Coming Enhancements
ISPF Recent and Coming EnhancementszOSCommserver
 
Uml Diagramas Estruturais
Uml   Diagramas EstruturaisUml   Diagramas Estruturais
Uml Diagramas Estruturaisthaisedd
 
04 Handling Exceptions
04 Handling Exceptions04 Handling Exceptions
04 Handling Exceptionsrehaniltifat
 

What's hot (20)

Sql com sql server básico - Bóson treinamentos
Sql com sql server básico - Bóson treinamentosSql com sql server básico - Bóson treinamentos
Sql com sql server básico - Bóson treinamentos
 
Rhel6 vs rhel7
Rhel6 vs rhel7Rhel6 vs rhel7
Rhel6 vs rhel7
 
Tso and ispf
Tso and ispfTso and ispf
Tso and ispf
 
ALL ABOUT DB2 DSNZPARM
ALL ABOUT DB2 DSNZPARMALL ABOUT DB2 DSNZPARM
ALL ABOUT DB2 DSNZPARM
 
QSpiders - Unix Operating Systems and Commands
QSpiders - Unix Operating Systems  and CommandsQSpiders - Unix Operating Systems  and Commands
QSpiders - Unix Operating Systems and Commands
 
Course 102: Lecture 14: Users and Permissions
Course 102: Lecture 14: Users and PermissionsCourse 102: Lecture 14: Users and Permissions
Course 102: Lecture 14: Users and Permissions
 
Oracle basic queries
Oracle basic queriesOracle basic queries
Oracle basic queries
 
IBM MQ Series For ZOS
IBM MQ Series For ZOSIBM MQ Series For ZOS
IBM MQ Series For ZOS
 
SQL Tutorial - Basic Commands
SQL Tutorial - Basic CommandsSQL Tutorial - Basic Commands
SQL Tutorial - Basic Commands
 
Practical Recipes for Daily DBA Activities using DB2 9 and 10 for z/OS
Practical Recipes for Daily DBA Activities using DB2 9 and 10 for z/OSPractical Recipes for Daily DBA Activities using DB2 9 and 10 for z/OS
Practical Recipes for Daily DBA Activities using DB2 9 and 10 for z/OS
 
Vetores, Matrizes e Strings em C Parte 1
Vetores, Matrizes e Strings em C Parte 1Vetores, Matrizes e Strings em C Parte 1
Vetores, Matrizes e Strings em C Parte 1
 
Oracle Enterprise Manager Cloud Control 13c for DBAs
Oracle Enterprise Manager Cloud Control 13c for DBAsOracle Enterprise Manager Cloud Control 13c for DBAs
Oracle Enterprise Manager Cloud Control 13c for DBAs
 
Xml transformation-doc
Xml transformation-docXml transformation-doc
Xml transformation-doc
 
DB2 for z/OS Architecture in Nutshell
DB2 for z/OS Architecture in NutshellDB2 for z/OS Architecture in Nutshell
DB2 for z/OS Architecture in Nutshell
 
Modulo 15 PSI
Modulo 15 PSIModulo 15 PSI
Modulo 15 PSI
 
Smpe
SmpeSmpe
Smpe
 
ISPF Recent and Coming Enhancements
ISPF Recent and Coming EnhancementsISPF Recent and Coming Enhancements
ISPF Recent and Coming Enhancements
 
Uml Diagramas Estruturais
Uml   Diagramas EstruturaisUml   Diagramas Estruturais
Uml Diagramas Estruturais
 
Ibm db2
Ibm db2Ibm db2
Ibm db2
 
04 Handling Exceptions
04 Handling Exceptions04 Handling Exceptions
04 Handling Exceptions
 

Viewers also liked

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
 

Viewers also liked (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 to 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 to 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
 

More from 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
 

More from 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
 

Recently uploaded

Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical InfrastructureVarsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructureitnewsafrica
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...BookNet Canada
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Karmanjay Verma
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
All These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFAll These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFMichael Gough
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesManik S Magar
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 

Recently uploaded (20)

Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical InfrastructureVarsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
All These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFAll These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDF
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 

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

Editor's Notes

  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.