Presentation is loading. Please wait.

Presentation is loading. Please wait.

Object Calisthenics Gabriel Heming.

Similar presentations


Presentation on theme: "Object Calisthenics Gabriel Heming."— Presentation transcript:

1 Object Calisthenics Gabriel Heming

2 Gabriel Heming

3 ORIGEM Cal • is • then • ics - /ˌkaləsˈTHeniks/ Origem grega;
Exercícios no contexto de ginástica.

4 ORIGEM The ThoughtWorks Anthology - Jeff Bay; Conjunto de exercícios;
Nove regras (não universais);

5 MOTIVAÇÃO Manutenibilidade; Legibilidade; Testabilidade; Compreensão.

6 RESUMINDO

7 Only one level of indentation per method;
RULE #1: Only one level of indentation per method;

8 1 2 3 public String Board() { StringBuilder buf = new StringBuilder();
if (this.Data.Length >= 3) for (int i = 0; i < this.Data.Length; i++) for (int j = 0; j < this.Data[i].Length; j++) buf.Append(this.Data[i][j]); } buf.Append("\n"); return buf.ToString(); Validação 1 2 3 8

9 StringBuilder buf = new StringBuilder(); if (this.Data.Length < 3)
public String Board() { StringBuilder buf = new StringBuilder(); if (this.Data.Length < 3) return buf.ToString(); } for (int i = 0; i < this.Data.Length; i++) for (int j = 0; j < this.Data[i].Length; j++) buf.Append(this.Data[i][j]); buf.Append("\n"); Early return 9

10 EXTRACT METHOD Martin Fowler

11 StringBuilder buf = new StringBuilder(); if (this.Data.Length < 3)
public String Board() { StringBuilder buf = new StringBuilder(); if (this.Data.Length < 3) return buf.ToString(); } for (int i = 0; i < this.Data.Length; i++) buf.Append(this.CollectColumns(this.Data[i])); buf.Append("\n"); public String CollectColumns(string[] data) foreach (string row in data) buf.Append(row); 11

12 if (this.Data.Length < 3) return buf.ToString();
public String Board() { if (this.Data.Length < 3) return buf.ToString(); return this.CollectRows(this.Data); } public String CollectRows(string[][] data) StringBuilder buf = new StringBuilder(); foreach (string[] row in data) buf.Append(this.CollectColumns(row)); buf.Append("\n"); return buf.ToString(); public String CollectColumns(string[] data) foreach (string row in data) buf.Append(row); 12

13 Muito simples?

14 public static void SitefPaymentsAbort(Sales sales) {
foreach (Payment payment in sales.Payments) if (payment.objSitefProvider != null && !string.IsNullOrEmpty(payment.objSitefProvider.receiptNumber)) payment.objSitefProvider.Abort(payment.objSitefProvider.receiptNumber, payment.objSitefProvider.DateTime); } foreach (TenderLineItem tenderlineitem in ((RetailTransaction)sales.transaction).TenderLines) if (tenderlineitem.LineId == payment.tenderLineItem.LineId) if (tenderlineitem is GiftCertificateTenderLineItem) if (sales.application.TransactionServices.CheckConnection()) bool released = true; string comment = ""; sales.application.TransactionServices.GiftCardRelease(ref released, ref comment, ((GiftCertificateTenderLineItem)tenderlineitem).SerialNumber); 14

15 public static void SitefPaymentsAbort(Sales sales) {
foreach (Payment payment in sales.Payments) SalesOrder.SitefPaymentAbort(sales , payment); } private static void SitefPaymentAbort(Sales sales, Payment payment) if (payment.objSitefProvider != null && !string.IsNullOrEmpty(payment.objSitefProvider.receiptNumber)) payment.objSitefProvider.Abort(payment.objSitefProvider.receiptNumber, payment.objSitefProvider.DateTime); foreach (TenderLineItem tenderlineitem in ((RetailTransaction)sales.transaction).TenderLines) if (tenderlineitem.LineId == payment.tenderLineItem.LineId) if (tenderlineitem is GiftCertificateTenderLineItem) if (sales.application.TransactionServices.CheckConnection()) bool released = true; string comment = ""; sales.application.TransactionServices.GiftCardRelease(ref released, ref comment, ((GiftCertificateTenderLineItem)tenderlineitem).SerialNumber); 15

16 private static void SitefPaymentAbort(Sales sales, Payment payment) {
/** código omitido **/ foreach (TenderLineItem tenderlineitem in ((RetailTransaction)sales.transaction).TenderLines) if (tenderlineitem.LineId == payment.tenderLineItem.LineId) if (tenderlineitem is GiftCertificateTenderLineItem) if (sales.application.TransactionServices.CheckConnection()) bool released = true; string comment = ""; sales.application.TransactionServices.GiftCardRelease(ref released, ref comment, ((GiftCertificateTenderLineItem)tenderlineitem).SerialNumber); } Validações 16

17 private static void SitefPaymentAbort(Sales sales, Payment payment) {
/** código omitido **/ IEnumerable<TenderLineItem> tenderLineItemList = ((RetailTransaction)sales.transaction).TenderLines.Where( tenderLineItem => tenderLineItem.LineId == payment.tenderLineItem.LineId && tenderLineItem is GiftCertificateTenderLineItem ); foreach (TenderLineItem tenderlineitem in tenderLineItemList) if (sales.application.TransactionServices.CheckConnection()) bool released = true; string comment = ""; sales.application.TransactionServices.GiftCardRelease(ref released, ref comment, ((GiftCertificateTenderLineItem)tenderlineitem).SerialNumber); } 17

18 private static void SitefPaymentAbort(Sales sales, Payment payment) {
/** código omitido **/ IEnumerable<TenderLineItem> tenderLineItemList = ((RetailTransaction)sales.transaction).TenderLines.Where( tenderLineItem => tenderLineItem.LineId == payment.tenderLineItem.LineId && tenderLineItem is GiftCertificateTenderLineItem ); foreach (TenderLineItem tenderlineitem in tenderLineItemList) SalesOrder.GiftCardRelease(sales, tenderLineItem); } private static void GiftCardRelease(SalesOrder sales, TenderLineItem tenderlineitem) if (sales.application.TransactionServices.CheckConnection()) bool released = true; string comment = ""; sales.application.TransactionServices.GiftCardRelease(ref released, ref comment, ((GiftCertificateTenderLineItem)tenderlineitem).SerialNumber); 18

19 public static void SitefPaymentsAbort(Sales sales)
{ foreach (Payment payment in sales.Payments) SalesOrder.SitefPaymentAbort(sales , payment); } private static void SitefPaymentAbort(Sales sales, Payment payment) if (payment.objSitefProvider != null && !string.IsNullOrEmpty(payment.objSitefProvider.receiptNumber)) payment.objSitefProvider.Abort(payment.objSitefProvider.receiptNumber, payment.objSitefProvider.DataHoraTransacao); IEnumerable<TenderLineItem> tenderLineItemList = ((RetailTransaction)sales.transaction).TenderLines.Where( tenderLineItem => tenderLineItem.LineId == payment.tenderLineItem.LineId && tenderLineItem is GiftCertificateTenderLineItem ); foreach (TenderLineItem tenderlineitem in tenderLineItemList) SalesOrder.GiftCardRelease(sales, tenderLineItem); private static void GiftCardRelease(SalesOrder sales, TenderLineItem tenderlineitem) if (sales.application.TransactionServices.CheckConnection()) bool released = true; string comment = ""; sales.application.TransactionServices.GiftCardRelease(ref released, ref comment, ((GiftCertificateTenderLineItem)tenderlineitem).SerialNumber); 19

20 BENEFÍCIOS S.R.P. (Single Responsibility Principle);
Redução lógica por métodos; Legibilidade; Reusabilidade.

21 RULE #2: Don’t use the else keyword

22 Por que?

23 COMPLEXIDADE CICLOMÁTICA

24 Defensive Programming

25 public Entity Create(Entity entity) { if (entity.IsValid())
Repository repository = this.GetRepository(entity); if (!repository.Exists(entity)) return repository.Save(entity); } else throw new ArgumentException("The entity already exists"); throw new ArgumentException("Invalid entity"); 25

26 public Entity Create(Entity entity) { if (!entity.IsValid())
throw new ArgumentException("Invalid entity"); } Repository repository = this.GetRepository(entity); if (!repository.Exists(entity)) return repository.Save(entity); else throw new ArgumentException("The entity already exists"); 26

27 public Entity Create(Entity entity) { if (!entity.IsValid())
throw new ArgumentException("Invalid entity"); } Repository repository = this.GetRepository(entity); if (repository.Exists(entity)) throw new ArgumentException("The entity already exists"); return repository.Save(entity); 27

28 OUTRAS ABORDAGENS Chain of Responsibility Pattern; State Pattern.

29 BENEFÍCIOS Evita duplicidade; Aumenta a legibilidade;
Reduz a complexidade ciclomática.

30 RULE #3: Wrap all primitives  and STRINGS

31  Primitive Obsession  anti-pattern

32 SOMENTE TIPOS COM COMPORTAMENTO

33 87,43 Sub 0?? 77,43 ????????? Add -10?? class BankAccount
{ private double amount; public void Add(double money) this.amount += money; } public void Sub(double money) this.amount -= money; public double Total() return this.amount; BankAccount account = new BankAccount(); account->Add(10); account->Add(12.25); account->Add(27.50); account->Add(55); account->Sub(17.32); account->Total(); 87,43 account->Add(-10); account->Sub(0); account->Total(); Sub 0?? 77,43 ????????? Add -10?? 33

34 Lógica duplicada class BankAccount { private double amount;
public void Add(double money) if (money <= 0) throw new ArgumentException("money não pode ser igual ou menor que zero"); } this.amount += money; public void Sub(double money) this.amount -= money; public double Total() return this.amount; Lógica duplicada 34

35 private double amount; public Money(double amount) if (money <= 0)
class Money { private double amount; public Money(double amount) if (money <= 0) throw new ArgumentException("money não pode ser igual ou menor que zero"); } this.amount = amount; public double GetAmount() return this.amount; class BankAccount { private double amount; public void Add(Money money) this.amount += money->GetAmount(); } public void Sub(Money money) this.amount -= money->GetAmount(); public double Total() return this.amount; BankAccount account = new BanckAccount(); account->Add(new Money(10));  account->Add(new Money(-10)); // throw ArgumentException 35

36 BENEFÍCIOS Evita duplicidade; Encapsulamento; Domain Driven Design.

37 First class collections
RULE #4: First class collections

38 public List<Address> AddressList { get; internal set; } }
public class Person { public List<Address> AddressList { get; internal set; } } public class Address public Type Type { get ; set; } public enum Type Residential, Commercial List<Address> residentialAddressList = person.AddressList.Where( address => address.Type == Type.Residential ).ToList() List<Address> residentialAddressList = person.AddressList.Where( address => address.Type == Type.Commercial ).ToList() 38

39 E SE PRECISAR FILTRAR EM DIFERENTES LUGARES?

40 Responsabilidades demais
class Person { public List<Address> AddressList { get; internal set; } public List<Address> GetResidentialAddressList() return this.AddressList.Where( address => address.Type == Type.Residential).ToList(); } public List<Address> GetCommercialAddressList() address => address.Type == Type.Commercial).ToList(); Responsabilidades demais List<Address> residentialAddressList = person.GetResidentialAddressList(); List<Address> commercialAddressList = person.GetCommercialAddressList(); 40

41 CADA UM COM SUA RESPONSABILIDADE

42 public class AddressCollection {
public List<Address> GetResidentialAddressList() return this.AddressList.Where( address => address.Type == Type.Residential).ToList(); } public List<Address> GetCommercialAddressList() address => address.Type == Type.Commercial).ToList(); public class Person public AddressCollection AddressCollection { get; internal set; } List<Address> residentialAddressList = person.AddressCollection.GetResidentialAddressList(); List<Address> commercialAddressList = person.AddressCollection.GetCommercialAddressList(); 42

43 BENEFÍCIOS S.R.P. (Single Responsibility Principle); Evita duplicação;
Manutenibilidade.

44 RULE #5: One dot per line

45 TRAIN WRECKS Robert UncleBob Martin

46 this.Repository.Database.Config.SetAttribute("attribute" , "value");
E se houver um null? 46

47 Null object?

48 POR QUE NÃO? Esconde um problema de encapsulamento;
Difícil de debugar e tratar exceções; O código deve ser reestruturado e tomar consciência da existência dele; Prejudica a leitura e o entendimento.

49 LAW OF DEMETER

50 this.Repository.SetDatabaseConfig("attribute", "value");
Nem sempre é aplicável 50

51 EXCEÇÕES Fluent Interface;
Builders (ex.: Query Builder, Link Builder, etc...);

52 BENEFÍCIOS Lei de Demeter; O.C.P (Open/Closed Principle);
Legibilidade; Testabilidade; Debug.

53 RULE #6: Don’t abbreviate

54 POR QUE ABREVIAR? Escrita repetitiva? Nomes muito longos?
“There are 2 hard problems in computer science: cache invalidation, naming things, and off-by-1 errors.”

55 BENEFÍCIOS S.R.P. (Single Responsibility Principle); Comunicação;
Legibilidade; Manutenibilidade.

56 Keep all entities small
RULE #7: Keep all entities small

57 DIRETRIZES Classes com 50 linhas; Leitura com pouco uso de scroll;
Apenas desenvolva o que for utilizar.

58 BENEFÍCIOS S.R.P. (Single Responsibility Principle); Legibilidade;
Encapsulamento; Segregação; Coesão e Coerência.

59 No classes with more than two instance variables
RULE #8: No classes with more than two instance variables

60 ESSA É DIFÍCIL

61 List<String> names;
class Name { String first; String middle; String last; } class Name { Surname family; GivenNames given; } class Surname String family; class GivenNames List<String> names; 61

62 Por que somente duas?

63 COMPLEMENTAR A REGRA #2

64 BENEFÍCIOS S.R.P. (Single Responsability Principle);
Baixo acoplamento; Encapsulamento; Coesão e Coerência; Testabilidade.

65 No getters / setters / properties
RULE #9: No getters / setters / properties

66 POR QUE? Simplesmente uma questão comportamental.

67 public int X { get; set; } public int Y { get; set; } }
class Rectangle { public int X { get; set; } public int Y { get; set; } } Rectangle rectangle = new Rectangle() { X = 10, Y = 5 }; int area = rectangle.X * rectangle.Y; 67

68 TELL, DON’T ASK!

69 public Rectangle(int x , int y) this.X = x; this.Y = y; }
class Rectangle { private int X; private int Y; public Rectangle(int x , int y) this.X = x; this.Y = y; } public int TotalArea() return this.X * this.Y; Rectangle rectangle = new Rectangle(10, 5); int area = rectangle.TotalArea(); 69

70 BENEFÍCIOS O.C.P (Open/Closed Principle); Encapsulamento.

71 CONSIDERAÇÕES

72 QUESTIONS? Thanks!


Download ppt "Object Calisthenics Gabriel Heming."

Similar presentations


Ads by Google