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).
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.
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á??
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 ;
23. Smysluplně se vyjadřovat
int days;
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;
}
25.
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.
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ů v jedné třídě
15 – 30 řádků metody
15 tříd v namespace
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);
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).
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.
47. public Record ExecuteCommand(Command command)
{
switch(command.Type)
{
case Standard:
return ExecuteStandardCommand(command);
case Complex:
return ExecuteComplexCommand(command);
default:
throw new InvalidExecuteType();
}
}
49. public abstract class Command {
public abstract Record Execute();
}
public interface ICommandFactory {
public Command MakeCommand(CommandRecord commandRecord);
}
50. 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();
}
}
}
51. Command command = commandFactory.MakeCommand(record);
Result result = command.Execute();
52. Command command = commandFactory.MakeCommand(record);
Result result = command.Execute();
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(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);
}
58. List<Car> cars = GetCars();
if (cars != null)
for(Car car : cars) {
Repair(car);
}
List<Car> cars = GetCars();
for(Car car : cars) {
Repair(car);
}
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);