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č 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.
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á??
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 ;
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.
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
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);
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).
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.
public Record ExecuteCommand(Commandcommand)
{
switch(command.Type)
{
case Standard:
return ExecuteStandardCommand(command);
case Complex:
return ExecuteComplexCommand(command);
default:
throw new InvalidExecuteType();
}
}
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();
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);