[JAM 1.1] Clean Code (Paul Malikov)
-
Upload
evgeny-kaziak -
Category
Technology
-
view
916 -
download
3
description
Transcript of [JAM 1.1] Clean Code (Paul Malikov)
![Page 1: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/1.jpg)
Понятный код
Paul Malikov
![Page 2: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/2.jpg)
содержание
• в чем проблема?
• названия• функции• комментарии• форматирование• классы
![Page 3: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/3.jpg)
![Page 4: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/4.jpg)
![Page 5: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/5.jpg)
![Page 6: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/6.jpg)
![Page 7: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/7.jpg)
![Page 8: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/8.jpg)
![Page 9: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/9.jpg)
![Page 10: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/10.jpg)
![Page 11: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/11.jpg)
в чем проблема?
![Page 12: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/12.jpg)
в чем проблема?
![Page 13: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/13.jpg)
в чем проблема?
![Page 14: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/14.jpg)
в чем проблема?
![Page 15: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/15.jpg)
содержательные имена
// elapsed time in daysint d;int dd;int d2;
int elapsedTimeInDays; int daysSinceCreation;int daysSinceModification; int fileAgeInDays;
имя должно передавать намерение программиста
![Page 16: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/16.jpg)
public List<int[]> getThem() { List<int[]> list1 = new ArrayList<int[]>(); for (int[] x : theList) if (x[0] == 4) list1.add(x); return list1;}
Неявный код
1. Что хранится в theList?2. Почему так важен нулевой элемент x[0]?3. Что означает 4?4. Как использовать возвращаемое значение?
public List<int[]> getFlaggedCells() { List<int[]> flaggedCells = new ArrayList<int[]>(); for (int[] cell : gameBoard) if (cell[STATUS_VALUE] == FLAGGED) flaggedCells.add(cell); return flaggedCells;}
public List<Cell> getFlaggedCells() { List<Cell> flaggedCells = new ArrayList<Cell>(); for (Cell cell : gameBoard) if (cell.isFlagged()) flaggedCells.add(cell); return flaggedCells;}
Явный код лучше неявного
![Page 17: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/17.jpg)
public List<int[]> getThem() { List<int[]> list1 = new ArrayList<int[]>(); for (int[] x : theList) if (x[0] == 4) list1.add(x); return list1;}
Неявный код
1. Что хранится в theList?2. Почему так важен нулевой элемент x[0]?3. Что означает 4?4. Как использовать возвращаемое значение?
public List<int[]> getFlaggedCells() { List<int[]> flaggedCells = new ArrayList<int[]>(); for (int[] cell : gameBoard) if (cell[STATUS_VALUE] == FLAGGED) flaggedCells.add(cell); return flaggedCells;}
public List<Cell> getFlaggedCells() { List<Cell> flaggedCells = new ArrayList<Cell>(); for (Cell cell : gameBoard) if (cell.isFlagged()) flaggedCells.add(cell); return flaggedCells;}
Явный код лучше неявного
![Page 18: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/18.jpg)
избегайте дезинформации
• избегайте названий, значение которых зависит от контекста
• hp, aix, sco - названия Unix платформ
hp - hipotenuseaix - augmentationIndexsco - spaceControlOficer
![Page 19: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/19.jpg)
избегайте дезинформации
• аккуратно используйте специфические программерские названия
• используйте альтернативные названияaccountList - type of List<T>?
accountGroupbunchOfAccounts
accounts
![Page 20: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/20.jpg)
избегайте дезинформации
• избегайте слабо отличающихся имен
XYZControllerForHandlingOfStringsXYZControllerForStorageOfStrings
![Page 21: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/21.jpg)
избегайте дезинформации
• не используйте последовательную нумерацию
public static void copyChars(char a1[], char a2[]) { for (int i = 0; i < a1.length; i++) { a2[i] = a1[i]; }}
public static void copyChars( char source[], char destination[]) { for (int i = 0; i < source.length; i++) { destination[i] = source[i]; }}
![Page 22: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/22.jpg)
избегайте дезинформации
• не используйте лишние слова (noise words)
ProductInfo - ProducttheMessage - messagemoneyAmount - money
accountData - account
![Page 23: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/23.jpg)
используйте произносимые имена
• humans are good in words
class DtaRcrd102 { private Date genymdhms; private Date modymdhms; private final String pszqint = "102";};
class Customer { private Date generationTimestamp; private Date modificationTimestamp; private final String recordId = "102";};
![Page 24: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/24.jpg)
используйте имена, удобные для поиска
• используйте имена переменных из одной буквы только в локальной области видимости в маленьких методах
• не используйте численные константыMAX_CLASSES_PER_STUDENT вместо 7
e - самая встречаемая буква алфавита
![Page 25: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/25.jpg)
используйте имена, удобные для поиска
for (int j=0; j<34; j++) { s += (t[j]*4)/5;}
int realDaysPerIdealDay = 4; const int WORK_DAYS_PER_WEEK = 5; int sum = 0; for (int j=0; j < NUMBER_OF_TASKS; j++) { int realTaskDays = taskEstimate[j] * realDaysPerIdealDay; int realTaskWeeks = (realdays / WORK_DAYS_PER_WEEK); sum += realTaskWeeks;}
![Page 26: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/26.jpg)
названия методов
• должны выражать действие
• с перегруженными конструкторами можно использовать static factory методы с названиями, описывающими агрументы
Complex fulcrumPoint = new Complex(23.0);
Complex fulcrumPoint = Complex.FromRealNumber(23.0);
![Page 27: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/27.jpg)
размер методов
• методы должны быть маленкими
• еще меньше!• это подразумевает однострочные if, esle,
while (названия методов отлично документируют ветвление)
• и вложенные структуры не глубже второго уровня
![Page 28: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/28.jpg)
public static String renderPageWithSetupsAndTeardowns( PageData pageData, boolean isSuite) throws Exception { boolean isTestPage = pageData.hasAttribute("Test"); if (isTestPage) { WikiPage testPage = pageData.getWikiPage(); StringBuffer newPageContent = new StringBuffer(); includeSetupPages(testPage, newPageContent, isSuite); newPageContent.append(pageData.getContent()); includeTeardownPages(testPage, newPageContent, isSuite); pageData.setContent(newPageContent.toString()); } return pageData.getHtml();}
public static String renderPageWithSetupsAndTeardowns( PageData pageData, boolean isSuite) throws Exception { if (isTestPage(pageData)) includeSetupAndTeardownPages(pageData, isSuite); return pageData.getHtml();}
![Page 29: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/29.jpg)
правило одной операции
• функция должна выполнять только одну операцию
• она должна выполнять ее хорошо• и ничего другого она делать не должна
• один уровень абстракции на функцию
![Page 30: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/30.jpg)
private void includeSetupAndTeardownPages() { includeSetupPages(); includePageContent(); includeTeardownPages(); updatePageContent();}private void includeSetupPages() { if (isSuite) includeSuiteSetupPage(); includeSetupPage();}private void includeSuiteSetupPage() { include(SuiteResponder.SUITE_SETUP_NAME, "-setup");}private void includeSetupPage() { include("SetUp", "-setup");}private void includePageContent() { newPageContent.append(pageData.getContent());}
![Page 31: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/31.jpg)
аргументы функции
• zero (niladic) - наилучший вариант
• one (monadic)
• two (dyadic)
• three (triadic)
• more (polyadic) - следует избегать
![Page 32: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/32.jpg)
аргументы функции
• с точки зрения тестирования малое количество аргументов упрощает перебор комбинаций
• использование выходных аргументов нарушает общую идею подачи исходных данных в качестве аргументов и получение результата через возвращаемое значение функции
![Page 33: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/33.jpg)
niladic
void saveTheMankind()
![Page 34: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/34.jpg)
типичные случаи monadic
• проверка условия, связанного с аргументом
• обработка аргумента, его преобразование и возвращение
• сообщение о событии
boolean contains(“MyValue”)
InputStream fileOpen(“MyFile”)
void passwordAttemptFailedNtimes(int attempts)
![Page 35: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/35.jpg)
типичные случаи monadic
• старайтесь избегать выходных аргументов
• используйте возвращаемое значениеStringBuffer transform(StringBuffer in)
void transform(StringBuffer out)
![Page 36: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/36.jpg)
monadic
Mrs marry(Miss girl)
![Page 37: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/37.jpg)
типичные случаи diadic
• более сложны для понимания
• подходят для агрументов с естественным порядком
writeField(outputStream, name) -> outputStream.writeField(name)
Point p = new Point(x,y);
![Page 38: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/38.jpg)
типичные случаи diadic
• если порядок не известен, можно преобразовать в monadic
compare(expected, actual) -> object.compare(expected)
![Page 39: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/39.jpg)
diadic
compare(expected, actual)
![Page 40: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/40.jpg)
разделение команд и запросов
• функция должна либо делать что-то, либо отвечать на какой-то вопрос, но не оба действия вместе
• метод устанавливает атрибут?• или метод проверяет значение атрибута?
public boolean set(String attribute, String value);
if (set("username", "unclebob"))...
![Page 41: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/41.jpg)
public boolean setAndCheckIfExists(String attribute, String value);
if (attributeExists("username")) { setAttribute("username", "unclebob"); ...}
разделение команд и запросов
![Page 42: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/42.jpg)
использование исключений
• старайтесь использовать исключения вместо кодов ошибок в качестве возвращаемого значения
![Page 43: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/43.jpg)
if (deletePage(page) == E_OK) { if (registry.deleteReference(page.name) == E_OK) { if (configKeys.deleteKey(page.name.makeKey()) == E_OK) { logger.log("page deleted"); } else { logger.log("configKey not deleted"); } } else { logger.log("deleteReference from registry failed"); } } else { logger.log("delete failed"); return E_ERROR;}
try { deletePage(page); registry.deleteReference(page.name); configKeys.deleteKey(page.name.makeKey());} catch (Exception e) { logger.log(e.getMessage());}
![Page 44: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/44.jpg)
комментарии
• не делают плохой код лучше• объясняйте при помощи кода
// Check to see if the employee is eligible for full benefits if ((employee.flags & HOURLY_FLAG) && (employee.age > 65)) ...
if (employee.isEligibleForFullBenefits()) ...
boolean isEligibleForFullBenefits = (employee.flags & HOURLY_FLAG) && (employee.age > 65);
if (isEligibleForFullBenefits) ...
![Page 45: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/45.jpg)
комментарии
• закомментированный код должен удаляться
• для читателя такой код означает, что есть серьезная причина, по которой этот код не был удален
![Page 46: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/46.jpg)
форматирование
• вертикальное форматирование и метафора газетной статьи
• первый параграф дает вам общее описание статьи
• прочитав его, вы определяете, та ли это статья, которая вам нужна
• чем дальше, тем больше дателей
• газета состоит из статей маленьких и побольше• если бы газета состояла из одной большой статьи, ее невозможно было бы читать
![Page 47: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/47.jpg)
классы
• классы должны быть маленькие
• еще меньше!• единица измерения - количество обязанностей (responsibility count)
![Page 48: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/48.jpg)
название класса
• должно выражать его обязанность• название, по сути, один из первых способов определить размер класса
• слова Processor, Manager, Super указывают на совмещение обязанностей
• опишите класс в 25 словах, не употребляя “если”, “и”, “или”, “но”
![Page 49: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/49.jpg)
Single Responsibility Principle
• утверждает, что класс или модуль должен иметь одну и только одну причину для изменения
• наиболее часто игнорируется программистами, т.к. считают, что их работа закончена после того, как код начал работать
![Page 50: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/50.jpg)
public class SuperDashboard { public Component getLastFocusedComponent(); public void setLastFocused(Component lastFocused); public int getMajorVersionNumber(); public int getMinorVersionNumber(); public int getBuildNumber()}
public class Version { public int getMajorVersionNumber(); public int getMinorVersionNumber(); public int getBuildNumber();}
![Page 51: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/51.jpg)
связность
• классы должны иметь небольшое количество переменных экземпляра
• каждый метод класса должен оперировать с этими переменными
• чем больше переменных, с которыми оперируют методы (для каждого метода), тем выше связность
![Page 52: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/52.jpg)
public class Stack { private int topOfStack = 0; List<Integer> elements = new LinkedList<Integer>(); public int size() { return topOfStack; } public void push(int element) { topOfStack++; elements.add(element); } public int pop() throws PoppedWhenEmpty { if (topOfStack == 0) throw new PoppedWhenEmpty(); int element = elements.get(--topOfStack); elements.remove(topOfStack); return element; }}
![Page 53: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/53.jpg)
связность
• разбиение функций ведет к снижению связности
• если классы утрачивают связность, разбейте их!
![Page 54: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/54.jpg)
что еще в этой книге?
• обработка ошибок• модульные тесты• системы• формирование архитектуры• многопоточность• smells and heruistics
![Page 55: [JAM 1.1] Clean Code (Paul Malikov)](https://reader034.fdocuments.net/reader034/viewer/2022052522/54c2e6414a79598a628b45e3/html5/thumbnails/55.jpg)
литература
• Robert C. Martin, Clean Code. A Handbook of Agile Software Craftsmanship - ISBN-13: 978-0-13-235088-4
• Robert C. Martin, Agile Principles, Patterns, and Practices ISBN-13: 978-0135974445
• Martin Fowler, Refactoring: Improving the Design of Existing Code ISBN-13: 978-0201485677