{ clean code }
twitter.com/jirkapenzes
Co je to čistý kód?
• Definic je tolik, kolik je vývojářů.
• Čistý kód píše pečlivý člověk.
• „Čistý kód je jednoduchý a přímočarý. Čistý kód
  se čte jako dobře napsaná próza. Čistý kód
  nikdy nezatemňuje záměr návrháře, ale je plný
  břitkých abstrakcí a přímých toků řízení„
  (Grady Booch).
Proč čistý kód?
Proč psát čistý kód?
•   Chceme na svůj kód být hrdí.
•   Přehlednost, znovu použitelnost.
•   Kód se lépe udržuje.
•   Produktivita, méně stresu.
•   Zbavit se „wtf“ momentů.
•   Budete mít ze své práce radost a lepší pocit.
•   Dokumentace.

• Neděláme to jen pro sebe,
    – občas po nás kód někdo čte.
Jak na čistý kód?
Volit správné názvy
Volit správné názvy
•   Správná jména metod.
•   Správná jména tříd.
•   Správná jména proměnných.
•   Správná jména výčtových typů.

• SPRÁVNÁ JMÉNA.

• Největší problém v dějinách programování!
public List<int[]> GetThem()
    {
            List<int[]> list1 = new List<int[]>();
            foreach(int[] x in theList)
                if (x[0] == 4)
                    list1.Add(x)

             return list1;
    }



•       Jaký druh položek obsahuje theList?
•       Jaký je význam nultého indexu položky v theList?
•       Jaký je význam hodnoty 4?
•       Jak bych mohl využít vráceného seznamu?
•       Co ta metoda vůbec dělá??
public List<int[]> GetFlaggedCells()
{
        List<int[]> list1 = new List<int[]>();
        foreach(int[] x in theList)
            if (x[0] == 4)
                list1.Add(x)

        return list1;
}
public List<int[]> GetFlaggedCells()
{
        List<int[]> flaggedCells = new List<int[]>();
        foreach(int[] x in theList)
            if (x[0] == 4)
               flaggedCells.Add(x)

        return flaggedCells;
}
public List<int[]> GetFlaggedCells()
{
        List<int[]> flaggedCells = new List<int[]>();
        foreach(int[] cell in gameBoard)
            if (cell[0] == 4)
               flaggedCells.Add(cell)

        return flaggedCells;
}
public List<int[]> GetFlaggedCells()
{
        List<int[]> flaggedCells = new List<int[]>();
        foreach(int[] cell in gameBoard)
            if (cell[STATUS_VALUE] == FLAGGED)
               flaggedCells.Add(cell)

        return flaggedCells;
}
public List<int[]> GetFlaggedCells()
{
        List<int[]> flaggedCells = new List<int[]>();
        foreach(int[] cell in gameBoard)
            if (cell[STATUS_VALUE] == FLAGGED)
               flaggedCells.Add(cell)

        return flaggedCells;
}
public List<Cell> getFlaggedCells()
{
        List<Cell> flaggedCells = new List<Cell>();
        foreach(Cell cell in gameBoard)
            if (cell.IsFlagged)
               flaggedCells.Add(cell)

        return flaggedCells;
}
Nezkracujte názvy
int d = 2; // total days
int d = 2; // diameter
int d = 2; // distance

int s = 0;
for (int i = 0; i < 10; i++)
    s += i;

String m = "message";
Nezkracujte názvy
int totalDays = 2;
int diamater = 2;
int distance = 2;

int suma = 0;
for (int index = 0; index < 10; index++)
    suma += index;

String message = "message";



if (a >   b && a > c && a > d && a > e)
    max   = a ;
else if   (b > a && b > c && b > d && b > e)
    max   = b ;
Neprotahovat názvy
UniqueNamesTableUtils.putPortletRequestIntoResourceRecordLazyLoad
AdminTableModelInSession(portletrequest);
Smysluplně se vyjadřovat
int days;



int daysSinceCreation;

int daysSinceLastModification;

int daysSinceLastLogin;

int daysSinceLastPasswordChange;

int durationInDays;
Zřetelnost a výslovnost
List<Car> carsList;

List<Car> cars;
List<Car> newCars;


public class DtaRcrd
{
    private DateTime _geneDtDDMMYYYYhhss;
    private DateTime _modiDtDDMMYYYYhhss;
}

public class DataRecord
{
    private DateTime _generationDate;
    private DateTime _modificationDate;
}
Jak volit správné názvy
•   Jména musí vysvětlovat význam.
•   Srozumitelné.
•   Vyhnout se dezinformacím.
•   Názvy by neměli být redundantní.
    – Nezahrnovat do názvu datový typ.
•   Vyslovitelná jména (DtaRcr).
•   Dodržování konvencí (?)
•   Nenutit nikoho přemýšlet.
•   Názvy z reálného světa.
Jak volit správné názvy
• Jména tříd:
  – Podstatná jména.


• Jména metod:
  – Přístupové metody dle své hodnoty (get, set, is).
  – Slovesa.


• Jedno slovo = jeden pojem.
Datetime tomorrow = GetTomorrow();



public DateTime GetTomorrow() {
   Thread.Sleep(1000*60*60*24);
   return DateTime.Now;
}
OOP
Třídy
Single responsibility principle
public class Employee
{
    public int Id { get; set; }
    public String FirstName { get; set; }
    public String LastName { get; set; }

    public Money CalculatePay() { ... }
    public String ReportHours() { ... } ;
    public Report Save() { ... }
}
public class Employee
{
    public int Id { get; set; }
    public String FirstName { get; set; }
    public String LastName { get; set; }
}


public class PayCalculator
{
    public Money CalculatePay(Employee employee) { … }
}

public class EmployeeReporter
{
    public Report ReportHours(Employee employee) { … }
}

public class EmployeeRepository
{
    public void Save() { … }
}
100 řádků v jedné třídě
 15 – 30 řádků metody
  15 tříd v namespace
Datové třídy
 Dědictví
Dědictví a datové třídy
• Dědíme jen to, co potřebujeme.

• Datová třída je pouze nositelem dat.
   – Entity, kontejnery*
• Slouží pro přenos dat (DTO).
• Aktivní záznam – save, find, ... (?!)
public void EmailDemo()
{
    var email = new Email();
    email.From = "jirkapenzes@hotmail.com";
    email.To = "jirkapenzes@gmail.com";
    email.Subject = "Spam";
    email.Body = "Posílám tu URL - tinyurl.com/6s6s63p ";

    email.Send();
}




var email = new Email();
email.From = "jirkapenzes@hotmail.com";
email.To = "jirkapenzes@gmail.com";
email.Subject = "Spam";
email.Body = "Posílám tu URL - tinyurl.com/6s6s63p";

var emailSender = new EmailSender();
emailSender.Send(email);
Jak na metody a funkce
Pravidla
•   1. Metoda musí být malá.
•   2. Metoda musí být ještě menší.
•   3. Metoda by měla dělat pouze jednu věc.
•   4. Volit správný název!
•   5. Minimum zanoření (jedno).
Argumenty funkce
Pravidla
•   Žádný == super.
•   Jeden == ok.
•   Dva == dejme tomu.
•   Tři == raději se tomu vyhnout.
•   Více == důkladně zdůvodnit, zda je to nutné.

• Předávejte objekty.
Vyhnout se příkazu switch
  Nepoužívat blok ‚else‘
public Record ExecuteCommand(Command command)
{
       switch(command.Type)
       {
           case Standard:
               return ExecuteStandardCommand(command);
           case Complex:
               return ExecuteComplexCommand(command);
           default:
               throw new InvalidExecuteType();
       }
   }
public abstract class Command {
    public abstract Record Execute();
}
public abstract class Command {
    public abstract Record Execute();
}

public interface ICommandFactory {
    public Command MakeCommand(CommandRecord commandRecord);
}
public abstract class Command {
    public abstract Record Execute();
}

public interface ICommandFactory {
     Command MakeCommand(CommandRecord commandRecord);
}

public class CommandFactory : ICommandFactory {

    public Command MakeCommand(CommandRecord commandRecord) {
       switch (commandRecord.Type) {
            case Standard:
                return new StandardCommand(commandRecord);
            case Complex:
                return new ComplexCommand(commandRecord);
            default:
                throw new InvalidExecuteRecordType();
        }
    }
}
Command command = commandFactory.MakeCommand(record);
Result result = command.Execute();
Command command = commandFactory.MakeCommand(record);
Result result = command.Execute();
Neopakovat se
Zpracování chyb
Zásady dobrého zpracování chyb
•   Používat výjimky!
•   Nepoužívat návratové kódy.
•   Nepředávat a nevracet hodnotu null.
•   Pište defenzivně.
•   Předávat informace o chybě.
•   Kontrolované výjimky (Java).
public void Add(Car car) {
    if (car != null) {
        CarGarage garage = context.FindCarGarage();
        if (garage != null) {
            garage.Add(car);
        }
    }
}




public void Add(Car car) {
    CarGarage garage = context. FindCarGarage();
    garage.Add(car);
}
List<Car> cars = GetCars();
if (cars != null)
   for(Car car : cars) {
       Repair(car);
   }




List<Car> cars = GetCars();
for(Car car : cars) {
    Repair(car);
}
Komentáře
(self documentation)
Práce s daty
Objekty a struktury
Práce s daty
• Při práci s daty se snažit o nezávislost.
• Odstínění datového zdroje.

• Repository pattern, DAO.
const string query
= "select name, isbn from book where year = @year";

using (var connection = new SqlConnection(connectionString))
{
    connection.Open();
    var sqlCommand = new SqlCommand(query, connection);
    sqlCommand.Parameters.AddWithValue("@year", year);
    var reader = sqlCommand.ExecuteReader();

    while (reader.Read())
    {
        var book = new Book
        {
            Name = reader["name"],
            Isbn = reader["isbn"]
        };
        Display(book);
    }
}
const string query
= MakeSqlQuery(BookQuery.FindBooksByYear);

using (var connection = new SqlConnection(connectionString))
{
    connection.Open();
    var sqlCommand = new SqlCommand(query, connection);
    sqlCommand.Parameters.AddWithValue("@year", year);
    var reader = sqlCommand.ExecuteReader();

    while (reader.Read())
    {
        var book = new User
        {
            Name = reader["name"],
            Isbn = reader["isbn"]
        };
        Display(book);
    }
}
var books = bookRepository.FindByYear(2002);

foreach (var book in books)
    Display(book);

public interface IBookRepository
{
    Book FindById(long id);
    IEnumerable<Book> FindAll();
    IEnumerable<Book> FindByCategory(Category category);
    IEnumerable<Book> FindByAuthor(Author author);
    IEnumerable<Book> FindByTag(string tag);
}




var books = bookDao.Fetch(new BookByYearQuery(2002));

foreach (var book in books)
    Display(book);
Refactoring
double CalculatePrice()
{
   // price is base price - quantity discount + shipping
   return _quantity * _itemPrice -
        Math.Max(0, _quantity - 500) * _itemPrice * 0.05 +
        Math.Min(_quantity * _itemPrice * 0.1, 100.0);
}
double CalculatePrice()
{
   // price is base price - quantity discount + shipping
   double basePrice = _quantity * _itemPrice;

    return _quantity * _itemPrice -
         Math.Max(0, _quantity - 500) * _itemPrice * 0.05 +
         Math.Min(_quantity * _itemPrice * 0.1, 100.0);
}
double CalculatePrice()
{
   // price is base price - quantity discount + shipping
   double basePrice = _quantity * _itemPrice;

    return basePrice -
         Math.Max(0, _quantity - 500) * _itemPrice * 0.05 +
         Math.Min(_quantity * _itemPrice * 0.1, 100.0);
}
double CalculatePrice()
{
   // price is base price - quantity discount + shipping
   double basePrice = _quantity * _itemPrice;

    return basePrice -
         Math.Max(0, _quantity - 500) * _itemPrice * 0.05 +
         Math.Min(basePrice * 0.1, 100.0);
}
double CalculatePrice()
{
   // price is base price - quantity discount + shipping
   double basePrice = _quantity * _itemPrice;
   double quantityDiscount =
              Math.Max(0, _quantity - 500) * _itemPrice * 0.05;

    return basePrice - quantityDiscount +
         Math.Min(basePrice * 0.1, 100.0);
}
double CalculatePrice()
{
   // price is base price - quantity discount + shipping
   double basePrice = _quantity * _itemPrice;
   double quantityDiscount =
              Math.Max(0, _quantity - 500) * _itemPrice * 0.05;
   double shipping = Math.Min(basePrice * 0.1, 100.0);

    return basePrice - quantityDiscount + shipping;
}
double CalculatePrice()
{
   // price is base price - quantity discount + shipping
   double basePrice = _quantity * _itemPrice;
   double quantityDiscount =
              Math.Max(0, _quantity - 500) * _itemPrice * 0.05;
   double shipping = Math.Min(basePrice * 0.1, 100.0);

    return basePrice - quantityDiscount + shipping;
}
double CalculatePrice()
{
   return basePrice() - quantityDiscount() + shipping();
}

private double quantityDiscount() {
    return Math.Max(0, _quantity - 500) * _itemPrice * 0.05;
}

private double shipping() {
    return Math.Min(basePrice() * 0.1, 100.0);
}

private double basePrice() {
    return _quantity * _itemPrice;
}
double CalculatePrice()
{
   return basePrice() - quantityDiscount() + shipping();
}



double CalculatePrice()
{
   // price is base price - quantity discount + shipping
   return _quantity * _itemPrice -
        Math.Max(0, _quantity - 500) * _itemPrice * 0.05 +
        Math.Min(_quantity * _itemPrice * 0.1, 100.0);
}
Refactoring
•   Neměnit logiku aplikace.
•   Rozházet kód do tříd a metod.
•   Provádět iterativně.
•   Pozor na názvy.
    – Zloději, loupežníci, banditi, zločinci, rafani, …
Formátování a konvence
Formátování a konvence
• 1. Formátovat.
• 2. Dodržovat jazykové konvence.

• Konvence pro přístupové metody.
• Velikost písmen.
• Týmové konvence.
Další zdroje?
Shrnutí
•   Déle přemýšlet nad názvy.
•   Zkusit kód častěji formátovat.
•   Držet se konvencí.
•   Testování.

• Nestačí, aby to jen fungovalo …
Q&A
jirkapenzes@hotmail.com
  twitter.com/jirkapenzes

Clean code

  • 1.
    { clean code} twitter.com/jirkapenzes
  • 3.
    Co je točistý kód? • Definic je tolik, kolik je vývojářů. • Čistý kód píše pečlivý člověk. • „Čistý kód je jednoduchý a přímočarý. Čistý kód se čte jako dobře napsaná próza. Čistý kód nikdy nezatemňuje záměr návrháře, ale je plný břitkých abstrakcí a přímých toků řízení„ (Grady Booch).
  • 5.
  • 8.
    Proč psát čistýkód? • Chceme na svůj kód být hrdí. • Přehlednost, znovu použitelnost. • Kód se lépe udržuje. • Produktivita, méně stresu. • Zbavit se „wtf“ momentů. • Budete mít ze své práce radost a lepší pocit. • Dokumentace. • Neděláme to jen pro sebe, – občas po nás kód někdo čte.
  • 9.
  • 11.
  • 12.
    Volit správné názvy • Správná jména metod. • Správná jména tříd. • Správná jména proměnných. • Správná jména výčtových typů. • SPRÁVNÁ JMÉNA. • Největší problém v dějinách programování!
  • 13.
    public List<int[]> GetThem() { List<int[]> list1 = new List<int[]>(); foreach(int[] x in theList) if (x[0] == 4) list1.Add(x) return list1; } • Jaký druh položek obsahuje theList? • Jaký je význam nultého indexu položky v theList? • Jaký je význam hodnoty 4? • Jak bych mohl využít vráceného seznamu? • Co ta metoda vůbec dělá??
  • 14.
    public List<int[]> GetFlaggedCells() { List<int[]> list1 = new List<int[]>(); foreach(int[] x in theList) if (x[0] == 4) list1.Add(x) return list1; }
  • 15.
    public List<int[]> GetFlaggedCells() { List<int[]> flaggedCells = new List<int[]>(); foreach(int[] x in theList) if (x[0] == 4) flaggedCells.Add(x) return flaggedCells; }
  • 16.
    public List<int[]> GetFlaggedCells() { List<int[]> flaggedCells = new List<int[]>(); foreach(int[] cell in gameBoard) if (cell[0] == 4) flaggedCells.Add(cell) return flaggedCells; }
  • 17.
    public List<int[]> GetFlaggedCells() { List<int[]> flaggedCells = new List<int[]>(); foreach(int[] cell in gameBoard) if (cell[STATUS_VALUE] == FLAGGED) flaggedCells.Add(cell) return flaggedCells; }
  • 18.
    public List<int[]> GetFlaggedCells() { List<int[]> flaggedCells = new List<int[]>(); foreach(int[] cell in gameBoard) if (cell[STATUS_VALUE] == FLAGGED) flaggedCells.Add(cell) return flaggedCells; }
  • 19.
    public List<Cell> getFlaggedCells() { List<Cell> flaggedCells = new List<Cell>(); foreach(Cell cell in gameBoard) if (cell.IsFlagged) flaggedCells.Add(cell) return flaggedCells; }
  • 20.
    Nezkracujte názvy int d= 2; // total days int d = 2; // diameter int d = 2; // distance int s = 0; for (int i = 0; i < 10; i++) s += i; String m = "message";
  • 21.
    Nezkracujte názvy int totalDays= 2; int diamater = 2; int distance = 2; int suma = 0; for (int index = 0; index < 10; index++) suma += index; String message = "message"; if (a > b && a > c && a > d && a > e) max = a ; else if (b > a && b > c && b > d && b > e) max = b ;
  • 22.
  • 23.
    Smysluplně se vyjadřovat intdays; int daysSinceCreation; int daysSinceLastModification; int daysSinceLastLogin; int daysSinceLastPasswordChange; int durationInDays;
  • 24.
    Zřetelnost a výslovnost List<Car>carsList; List<Car> cars; List<Car> newCars; public class DtaRcrd { private DateTime _geneDtDDMMYYYYhhss; private DateTime _modiDtDDMMYYYYhhss; } public class DataRecord { private DateTime _generationDate; private DateTime _modificationDate; }
  • 26.
    Jak volit správnénázvy • Jména musí vysvětlovat význam. • Srozumitelné. • Vyhnout se dezinformacím. • Názvy by neměli být redundantní. – Nezahrnovat do názvu datový typ. • Vyslovitelná jména (DtaRcr). • Dodržování konvencí (?) • Nenutit nikoho přemýšlet. • Názvy z reálného světa.
  • 27.
    Jak volit správnénázvy • Jména tříd: – Podstatná jména. • Jména metod: – Přístupové metody dle své hodnoty (get, set, is). – Slovesa. • Jedno slovo = jeden pojem.
  • 28.
    Datetime tomorrow =GetTomorrow(); public DateTime GetTomorrow() { Thread.Sleep(1000*60*60*24); return DateTime.Now; }
  • 29.
  • 31.
  • 33.
  • 34.
    public class Employee { public int Id { get; set; } public String FirstName { get; set; } public String LastName { get; set; } public Money CalculatePay() { ... } public String ReportHours() { ... } ; public Report Save() { ... } }
  • 35.
    public class Employee { public int Id { get; set; } public String FirstName { get; set; } public String LastName { get; set; } } public class PayCalculator { public Money CalculatePay(Employee employee) { … } } public class EmployeeReporter { public Report ReportHours(Employee employee) { … } } public class EmployeeRepository { public void Save() { … } }
  • 36.
    100 řádků vjedné třídě 15 – 30 řádků metody 15 tříd v namespace
  • 37.
  • 38.
    Dědictví a datovétřídy • Dědíme jen to, co potřebujeme. • Datová třída je pouze nositelem dat. – Entity, kontejnery* • Slouží pro přenos dat (DTO). • Aktivní záznam – save, find, ... (?!)
  • 39.
    public void EmailDemo() { var email = new Email(); email.From = "jirkapenzes@hotmail.com"; email.To = "jirkapenzes@gmail.com"; email.Subject = "Spam"; email.Body = "Posílám tu URL - tinyurl.com/6s6s63p "; email.Send(); } var email = new Email(); email.From = "jirkapenzes@hotmail.com"; email.To = "jirkapenzes@gmail.com"; email.Subject = "Spam"; email.Body = "Posílám tu URL - tinyurl.com/6s6s63p"; var emailSender = new EmailSender(); emailSender.Send(email);
  • 40.
    Jak na metodya funkce
  • 41.
    Pravidla • 1. Metoda musí být malá. • 2. Metoda musí být ještě menší. • 3. Metoda by měla dělat pouze jednu věc. • 4. Volit správný název! • 5. Minimum zanoření (jedno).
  • 43.
  • 44.
    Pravidla • Žádný == super. • Jeden == ok. • Dva == dejme tomu. • Tři == raději se tomu vyhnout. • Více == důkladně zdůvodnit, zda je to nutné. • Předávejte objekty.
  • 46.
    Vyhnout se příkazuswitch Nepoužívat blok ‚else‘
  • 47.
    public Record ExecuteCommand(Commandcommand) { switch(command.Type) { case Standard: return ExecuteStandardCommand(command); case Complex: return ExecuteComplexCommand(command); default: throw new InvalidExecuteType(); } }
  • 48.
    public abstract classCommand { public abstract Record Execute(); }
  • 49.
    public abstract classCommand { public abstract Record Execute(); } public interface ICommandFactory { public Command MakeCommand(CommandRecord commandRecord); }
  • 50.
    public abstract classCommand { public abstract Record Execute(); } public interface ICommandFactory { Command MakeCommand(CommandRecord commandRecord); } public class CommandFactory : ICommandFactory { public Command MakeCommand(CommandRecord commandRecord) { switch (commandRecord.Type) { case Standard: return new StandardCommand(commandRecord); case Complex: return new ComplexCommand(commandRecord); default: throw new InvalidExecuteRecordType(); } } }
  • 51.
    Command command =commandFactory.MakeCommand(record); Result result = command.Execute();
  • 52.
    Command command =commandFactory.MakeCommand(record); Result result = command.Execute();
  • 53.
  • 55.
  • 56.
    Zásady dobrého zpracováníchyb • Používat výjimky! • Nepoužívat návratové kódy. • Nepředávat a nevracet hodnotu null. • Pište defenzivně. • Předávat informace o chybě. • Kontrolované výjimky (Java).
  • 57.
    public void Add(Carcar) { if (car != null) { CarGarage garage = context.FindCarGarage(); if (garage != null) { garage.Add(car); } } } public void Add(Car car) { CarGarage garage = context. FindCarGarage(); garage.Add(car); }
  • 58.
    List<Car> cars =GetCars(); if (cars != null) for(Car car : cars) { Repair(car); } List<Car> cars = GetCars(); for(Car car : cars) { Repair(car); }
  • 60.
  • 62.
  • 63.
    Práce s daty •Při práci s daty se snažit o nezávislost. • Odstínění datového zdroje. • Repository pattern, DAO.
  • 64.
    const string query ="select name, isbn from book where year = @year"; using (var connection = new SqlConnection(connectionString)) { connection.Open(); var sqlCommand = new SqlCommand(query, connection); sqlCommand.Parameters.AddWithValue("@year", year); var reader = sqlCommand.ExecuteReader(); while (reader.Read()) { var book = new Book { Name = reader["name"], Isbn = reader["isbn"] }; Display(book); } }
  • 65.
    const string query =MakeSqlQuery(BookQuery.FindBooksByYear); using (var connection = new SqlConnection(connectionString)) { connection.Open(); var sqlCommand = new SqlCommand(query, connection); sqlCommand.Parameters.AddWithValue("@year", year); var reader = sqlCommand.ExecuteReader(); while (reader.Read()) { var book = new User { Name = reader["name"], Isbn = reader["isbn"] }; Display(book); } }
  • 66.
    var books =bookRepository.FindByYear(2002); foreach (var book in books) Display(book); public interface IBookRepository { Book FindById(long id); IEnumerable<Book> FindAll(); IEnumerable<Book> FindByCategory(Category category); IEnumerable<Book> FindByAuthor(Author author); IEnumerable<Book> FindByTag(string tag); } var books = bookDao.Fetch(new BookByYearQuery(2002)); foreach (var book in books) Display(book);
  • 67.
  • 69.
    double CalculatePrice() { // price is base price - quantity discount + shipping return _quantity * _itemPrice - Math.Max(0, _quantity - 500) * _itemPrice * 0.05 + Math.Min(_quantity * _itemPrice * 0.1, 100.0); }
  • 70.
    double CalculatePrice() { // price is base price - quantity discount + shipping double basePrice = _quantity * _itemPrice; return _quantity * _itemPrice - Math.Max(0, _quantity - 500) * _itemPrice * 0.05 + Math.Min(_quantity * _itemPrice * 0.1, 100.0); }
  • 71.
    double CalculatePrice() { // price is base price - quantity discount + shipping double basePrice = _quantity * _itemPrice; return basePrice - Math.Max(0, _quantity - 500) * _itemPrice * 0.05 + Math.Min(_quantity * _itemPrice * 0.1, 100.0); }
  • 72.
    double CalculatePrice() { // price is base price - quantity discount + shipping double basePrice = _quantity * _itemPrice; return basePrice - Math.Max(0, _quantity - 500) * _itemPrice * 0.05 + Math.Min(basePrice * 0.1, 100.0); }
  • 73.
    double CalculatePrice() { // price is base price - quantity discount + shipping double basePrice = _quantity * _itemPrice; double quantityDiscount = Math.Max(0, _quantity - 500) * _itemPrice * 0.05; return basePrice - quantityDiscount + Math.Min(basePrice * 0.1, 100.0); }
  • 74.
    double CalculatePrice() { // price is base price - quantity discount + shipping double basePrice = _quantity * _itemPrice; double quantityDiscount = Math.Max(0, _quantity - 500) * _itemPrice * 0.05; double shipping = Math.Min(basePrice * 0.1, 100.0); return basePrice - quantityDiscount + shipping; }
  • 75.
    double CalculatePrice() { // price is base price - quantity discount + shipping double basePrice = _quantity * _itemPrice; double quantityDiscount = Math.Max(0, _quantity - 500) * _itemPrice * 0.05; double shipping = Math.Min(basePrice * 0.1, 100.0); return basePrice - quantityDiscount + shipping; }
  • 76.
    double CalculatePrice() { return basePrice() - quantityDiscount() + shipping(); } private double quantityDiscount() { return Math.Max(0, _quantity - 500) * _itemPrice * 0.05; } private double shipping() { return Math.Min(basePrice() * 0.1, 100.0); } private double basePrice() { return _quantity * _itemPrice; }
  • 77.
    double CalculatePrice() { return basePrice() - quantityDiscount() + shipping(); } double CalculatePrice() { // price is base price - quantity discount + shipping return _quantity * _itemPrice - Math.Max(0, _quantity - 500) * _itemPrice * 0.05 + Math.Min(_quantity * _itemPrice * 0.1, 100.0); }
  • 78.
    Refactoring • Neměnit logiku aplikace. • Rozházet kód do tříd a metod. • Provádět iterativně. • Pozor na názvy. – Zloději, loupežníci, banditi, zločinci, rafani, …
  • 79.
  • 81.
    Formátování a konvence •1. Formátovat. • 2. Dodržovat jazykové konvence. • Konvence pro přístupové metody. • Velikost písmen. • Týmové konvence.
  • 82.
  • 85.
    Shrnutí • Déle přemýšlet nad názvy. • Zkusit kód častěji formátovat. • Držet se konvencí. • Testování. • Nestačí, aby to jen fungovalo …
  • 86.