SlideShare a Scribd company logo
1 of 55
Download to read offline
Понятный код




Paul Malikov
содержание
• в чем проблема?
• названия
• функции
• комментарии
• форматирование
• классы
в чем проблема?
в чем проблема?
в чем проблема?
в чем проблема?
содержательные имена
имя должно передавать намерение программиста


  // elapsed time in days   int   elapsedTimeInDays;
  int d;                    int   daysSinceCreation;
  int dd;                   int   daysSinceModification;
  int d2;                   int   fileAgeInDays;
Явный код
       Неявный код
                                         лучше неявного
public List<int[]> getThem() {
    List<int[]> list1 =           public List<int[]> getFlaggedCells() {
        new ArrayList<int[]>();       List<int[]> flaggedCells =
                                          new ArrayList<int[]>();
    for (int[] x : theList)
                                      for (int[] cell : gameBoard)
        if (x[0] == 4)                    if (cell[STATUS_VALUE] == FLAGGED)
            list1.add(x);                     flaggedCells.add(cell);
                                      return flaggedCells;
    return list1;
                                  }
}


1. Что хранится в theList?        public List<Cell> getFlaggedCells() {
2. Почему так важен нулевой           List<Cell> flaggedCells =
                                          new ArrayList<Cell>();
элемент x[0]?                         for (Cell cell : gameBoard)
3. Что означает 4?                        if (cell.isFlagged())
                                              flaggedCells.add(cell);
4. Как использовать                   return flaggedCells;

возвращаемое значение?            }
Явный код
       Неявный код
                                         лучше неявного
public List<int[]> getThem() {
    List<int[]> list1 =           public List<int[]> getFlaggedCells() {
        new ArrayList<int[]>();       List<int[]> flaggedCells =
                                          new ArrayList<int[]>();
    for (int[] x : theList)
                                      for (int[] cell : gameBoard)
        if (x[0] == 4)                    if (cell[STATUS_VALUE] == FLAGGED)
            list1.add(x);                     flaggedCells.add(cell);
                                      return flaggedCells;
    return list1;
                                  }
}


1. Что хранится в theList?        public List<Cell> getFlaggedCells() {
2. Почему так важен нулевой           List<Cell> flaggedCells =
                                          new ArrayList<Cell>();
элемент x[0]?                         for (Cell cell : gameBoard)
3. Что означает 4?                        if (cell.isFlagged())
                                              flaggedCells.add(cell);
4. Как использовать                   return flaggedCells;

возвращаемое значение?            }
избегайте дезинформации

• избегайте названий, значение которых
  зависит от контекста

           hp - hipotenuse
      aix - augmentationIndex
      sco - spaceControlOficer


• hp, aix, sco - названия Unix платформ
избегайте дезинформации

• аккуратно используйте специфические
  программерские названия
   accountList - type of List<T>?

• используйте альтернативные названия
            accountGroup
           bunchOfAccounts
              accounts
избегайте дезинформации

• избегайте слабо отличающихся имен
  XYZControllerForHandlingOfStrings
  XYZControllerForStorageOfStrings
избегайте дезинформации

 • не используйте последовательную
    нумерацию
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];
    }
}
избегайте дезинформации

• не используйте лишние слова (noise
  words)
        ProductInfo - Product
        theMessage - message
         moneyAmount - money
        accountData - account
используйте произносимые
          имена
• 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";
    };
используйте имена, удобные
        для поиска
• используйте имена переменных из одной
  буквы только в локальной области
  видимости в маленьких методах
e - самая встречаемая буква алфавита

• не используйте численные константы
  MAX_CLASSES_PER_STUDENT вместо 7
используйте имена, удобные
         для поиска
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;
}
названия методов

• должны выражать действие
• с перегруженными конструкторами
  можно использовать static factory
  методы с названиями, описывающими
  агрументы
Complex fulcrumPoint = new Complex(23.0);

Complex fulcrumPoint = Complex.FromRealNumber(23.0);
размер методов

• методы должны быть маленкими
• еще меньше!
• это подразумевает однострочные if, esle,
  while (названия методов отлично
  документируют ветвление)
• и вложенные структуры не глубже
  второго уровня
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();
}
правило одной операции

• функция должна выполнять только одну
  операцию
• она должна выполнять ее хорошо
• и ничего другого она делать не должна

• один уровень абстракции на функцию
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());
}
аргументы функции

• zero (niladic) - наилучший вариант
• one (monadic)
• two (dyadic)
• three (triadic)
• more (polyadic) - следует избегать
аргументы функции

• с точки зрения тестирования малое
  количество аргументов упрощает
  перебор комбинаций
• использование выходных аргументов
  нарушает общую идею подачи исходных
  данных в качестве аргументов и
  получение результата через
  возвращаемое значение функции
niladic




void saveTheMankind()
типичные случаи monadic

• проверка условия, связанного с
  аргументом
           boolean contains(“MyValue”)


• обработка аргумента, его
  преобразование и возвращение
          InputStream fileOpen(“MyFile”)



• сообщение о событии
  void passwordAttemptFailedNtimes(int attempts)
типичные случаи monadic

• старайтесь избегать выходных
  аргументов
        void transform(StringBuffer out)



• используйте возвращаемое значение
     StringBuffer transform(StringBuffer in)
monadic




Mrs marry(Miss girl)
типичные случаи diadic

• более сложны для понимания
      writeField(outputStream, name) ->
        outputStream.writeField(name)


• подходят для агрументов с естественным
  порядком
           Point p = new Point(x,y);
типичные случаи diadic

• если порядок не известен, можно
   преобразовать в monadic
compare(expected, actual) -> object.compare(expected)
diadic




compare(expected, actual)
разделение команд и запросов

 • функция должна либо делать что-то,
   либо отвечать на какой-то вопрос, но не
   оба действия вместе
 public boolean set(String attribute, String value);

 if (set("username", "unclebob"))...



 • метод устанавливает атрибут?
 • или метод проверяет значение атрибута?
разделение команд и запросов
 public boolean setAndCheckIfExists(String attribute,
 String value);



 if (attributeExists("username")) {
     setAttribute("username", "unclebob");
     ...
 }
использование исключений

• старайтесь использовать исключения
  вместо кодов ошибок в качестве
  возвращаемого значения
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());
}
комментарии

    • не делают плохой код лучше
    • объясняйте при помощи кода
// 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) ...
комментарии

• закомментированный код должен
  удаляться
• для читателя такой код означает, что есть
  серьезная причина, по которой этот код
  не был удален
форматирование
•   вертикальное форматирование и метафора
    газетной статьи
•   первый параграф дает вам общее описание
    статьи
•   прочитав его, вы определяете, та ли это статья,
    которая вам нужна
•   чем дальше, тем больше дателей
•   газета состоит из статей маленьких и побольше
•   если бы газета состояла из одной большой
    статьи, ее невозможно было бы читать
классы

• классы должны быть маленькие
• еще меньше!
• единица измерения - количество
  обязанностей (responsibility count)
название класса

• должно выражать его обязанность
• название, по сути, один из первых
  способов определить размер класса
• слова Processor, Manager, Super указывают
  на совмещение обязанностей
• опишите класс в 25 словах, не
  употребляя “если”, “и”, “или”, “но”
Single Responsibility Principle

• утверждает, что класс или модуль должен
  иметь одну и только одну причину для
  изменения
• наиболее часто игнорируется
  программистами, т.к. считают, что их
  работа закончена после того, как код
  начал работать
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();
}
связность

• классы должны иметь небольшое
  количество переменных экземпляра
• каждый метод класса должен
  оперировать с этими переменными
• чем больше переменных, с которыми
  оперируют методы (для каждого
  метода), тем выше связность
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;
    }
}
связность

• разбиение функций ведет к снижению
  связности
• если классы утрачивают связность,
  разбейте их!
что еще в этой книге?

• обработка ошибок
• модульные тесты
• системы
• формирование архитектуры
• многопоточность
• smells and heruistics
литература

• 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

More Related Content

What's hot

8. java lecture threads
8. java lecture threads8. java lecture threads
8. java lecture threads
MERA_school
 

What's hot (17)

8. java lecture threads
8. java lecture threads8. java lecture threads
8. java lecture threads
 
Формальные методы защиты приложений
Формальные методы защиты приложенийФормальные методы защиты приложений
Формальные методы защиты приложений
 
Agile Instrumentation
Agile InstrumentationAgile Instrumentation
Agile Instrumentation
 
Теоретические основы Application Security
Теоретические основы Application SecurityТеоретические основы Application Security
Теоретические основы Application Security
 
PVS-Studio в 2021 - Примеры ошибок
PVS-Studio в 2021 - Примеры ошибокPVS-Studio в 2021 - Примеры ошибок
PVS-Studio в 2021 - Примеры ошибок
 
Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 12. Быстрее, Python, ещё быстрее.Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 12. Быстрее, Python, ещё быстрее.
 
JRebel
JRebelJRebel
JRebel
 
Лекция 2. Всё, что вы хотели знать о функциях в Python.
Лекция 2. Всё, что вы хотели знать о функциях в Python.Лекция 2. Всё, что вы хотели знать о функциях в Python.
Лекция 2. Всё, что вы хотели знать о функциях в Python.
 
Декораторы в Python и их практическое использование
Декораторы в Python и их практическое использование Декораторы в Python и их практическое использование
Декораторы в Python и их практическое использование
 
Python dict: прошлое, настоящее, будущее
Python dict: прошлое, настоящее, будущееPython dict: прошлое, настоящее, будущее
Python dict: прошлое, настоящее, будущее
 
Programming Java - Lecture 02 - Objects - Lavrentyev Fedor
Programming Java - Lecture 02 - Objects - Lavrentyev FedorProgramming Java - Lecture 02 - Objects - Lavrentyev Fedor
Programming Java - Lecture 02 - Objects - Lavrentyev Fedor
 
Лекция 1. Начало.
Лекция 1. Начало.Лекция 1. Начало.
Лекция 1. Начало.
 
Профилирование и отладка Django
Профилирование и отладка DjangoПрофилирование и отладка Django
Профилирование и отладка Django
 
Оптимизация производительности Python
Оптимизация производительности PythonОптимизация производительности Python
Оптимизация производительности Python
 
Tricky Java Generics
Tricky Java GenericsTricky Java Generics
Tricky Java Generics
 
Bytecode
BytecodeBytecode
Bytecode
 
Лекция 11. Тестирование.
Лекция 11. Тестирование.Лекция 11. Тестирование.
Лекция 11. Тестирование.
 

Viewers also liked

[JAM 1.2] HTML5 (Alexei Yanochkin)
[JAM 1.2] HTML5 (Alexei Yanochkin)[JAM 1.2] HTML5 (Alexei Yanochkin)
[JAM 1.2] HTML5 (Alexei Yanochkin)
Evgeny Kaziak
 
[JAM 1.2] Testing in Android (Dzmitry Ivashnev)
[JAM 1.2] Testing in Android (Dzmitry Ivashnev)[JAM 1.2] Testing in Android (Dzmitry Ivashnev)
[JAM 1.2] Testing in Android (Dzmitry Ivashnev)
Evgeny Kaziak
 
[JAM 1.2] Design & Multitasking (Andrew Solovey)
[JAM 1.2] Design & Multitasking (Andrew Solovey)[JAM 1.2] Design & Multitasking (Andrew Solovey)
[JAM 1.2] Design & Multitasking (Andrew Solovey)
Evgeny Kaziak
 
[JAM 1.2] Intro (Paul Malikov)
[JAM 1.2] Intro (Paul Malikov)[JAM 1.2] Intro (Paul Malikov)
[JAM 1.2] Intro (Paul Malikov)
Evgeny Kaziak
 
[JAM 1.0] CMS. Обзор. (Alexei Yanochkin)
[JAM 1.0] CMS. Обзор. (Alexei Yanochkin)[JAM 1.0] CMS. Обзор. (Alexei Yanochkin)
[JAM 1.0] CMS. Обзор. (Alexei Yanochkin)
Evgeny Kaziak
 
[JAM 1.0] Intro (Paul Malikov)
[JAM 1.0] Intro (Paul Malikov)[JAM 1.0] Intro (Paul Malikov)
[JAM 1.0] Intro (Paul Malikov)
Evgeny Kaziak
 
[JAM 1.0] Human Interface Guidelines (Evgeny Kaziak)
[JAM 1.0] Human Interface Guidelines (Evgeny Kaziak)[JAM 1.0] Human Interface Guidelines (Evgeny Kaziak)
[JAM 1.0] Human Interface Guidelines (Evgeny Kaziak)
Evgeny Kaziak
 
Part iii sec.2 ppt.
Part iii sec.2 ppt.Part iii sec.2 ppt.
Part iii sec.2 ppt.
dhtay
 
[JAM 1.0] Android OS, Java (Paul Malikov)
[JAM 1.0] Android OS, Java (Paul Malikov)[JAM 1.0] Android OS, Java (Paul Malikov)
[JAM 1.0] Android OS, Java (Paul Malikov)
Evgeny Kaziak
 
[JAM 1.2] Mobile Gamedesign (Boris Zapolsky)
[JAM 1.2] Mobile Gamedesign (Boris Zapolsky)[JAM 1.2] Mobile Gamedesign (Boris Zapolsky)
[JAM 1.2] Mobile Gamedesign (Boris Zapolsky)
Evgeny Kaziak
 

Viewers also liked (18)

[JAM 1.2] HTML5 (Alexei Yanochkin)
[JAM 1.2] HTML5 (Alexei Yanochkin)[JAM 1.2] HTML5 (Alexei Yanochkin)
[JAM 1.2] HTML5 (Alexei Yanochkin)
 
[JAM 1.2] Testing in Android (Dzmitry Ivashnev)
[JAM 1.2] Testing in Android (Dzmitry Ivashnev)[JAM 1.2] Testing in Android (Dzmitry Ivashnev)
[JAM 1.2] Testing in Android (Dzmitry Ivashnev)
 
[JAM 1.2] Design & Multitasking (Andrew Solovey)
[JAM 1.2] Design & Multitasking (Andrew Solovey)[JAM 1.2] Design & Multitasking (Andrew Solovey)
[JAM 1.2] Design & Multitasking (Andrew Solovey)
 
[JAM 1.1] Geo Champs (Mashpit Team)
[JAM 1.1] Geo Champs (Mashpit Team)[JAM 1.1] Geo Champs (Mashpit Team)
[JAM 1.1] Geo Champs (Mashpit Team)
 
[JAM 1.2] Intro (Paul Malikov)
[JAM 1.2] Intro (Paul Malikov)[JAM 1.2] Intro (Paul Malikov)
[JAM 1.2] Intro (Paul Malikov)
 
[JAM 1.1] Symfony (Alexei Yanochkin)
[JAM 1.1] Symfony (Alexei Yanochkin)[JAM 1.1] Symfony (Alexei Yanochkin)
[JAM 1.1] Symfony (Alexei Yanochkin)
 
[JAM 1.0] CMS. Обзор. (Alexei Yanochkin)
[JAM 1.0] CMS. Обзор. (Alexei Yanochkin)[JAM 1.0] CMS. Обзор. (Alexei Yanochkin)
[JAM 1.0] CMS. Обзор. (Alexei Yanochkin)
 
Clements World Part III, Sec 1
Clements World Part III, Sec 1Clements World Part III, Sec 1
Clements World Part III, Sec 1
 
Secondary education-act-1972
Secondary education-act-1972Secondary education-act-1972
Secondary education-act-1972
 
[JAM 1.1] Intro (Paul Malikov)
[JAM 1.1] Intro (Paul Malikov)[JAM 1.1] Intro (Paul Malikov)
[JAM 1.1] Intro (Paul Malikov)
 
[JAM 1.0] Intro (Paul Malikov)
[JAM 1.0] Intro (Paul Malikov)[JAM 1.0] Intro (Paul Malikov)
[JAM 1.0] Intro (Paul Malikov)
 
[JAM 1.0] Human Interface Guidelines (Evgeny Kaziak)
[JAM 1.0] Human Interface Guidelines (Evgeny Kaziak)[JAM 1.0] Human Interface Guidelines (Evgeny Kaziak)
[JAM 1.0] Human Interface Guidelines (Evgeny Kaziak)
 
[JAM 1.1] Project Managment Tools (Viktor Sidorcov)
[JAM 1.1] Project Managment Tools (Viktor Sidorcov)[JAM 1.1] Project Managment Tools (Viktor Sidorcov)
[JAM 1.1] Project Managment Tools (Viktor Sidorcov)
 
Part iii sec.2 ppt.
Part iii sec.2 ppt.Part iii sec.2 ppt.
Part iii sec.2 ppt.
 
Bombay primary education act
Bombay primary education actBombay primary education act
Bombay primary education act
 
[JAM 1.0] Android OS, Java (Paul Malikov)
[JAM 1.0] Android OS, Java (Paul Malikov)[JAM 1.0] Android OS, Java (Paul Malikov)
[JAM 1.0] Android OS, Java (Paul Malikov)
 
[JAM 1.2] Mobile Gamedesign (Boris Zapolsky)
[JAM 1.2] Mobile Gamedesign (Boris Zapolsky)[JAM 1.2] Mobile Gamedesign (Boris Zapolsky)
[JAM 1.2] Mobile Gamedesign (Boris Zapolsky)
 
[JAM 1.1] Testing not for Fun (Evgeny Kaziak)
[JAM 1.1] Testing not for Fun (Evgeny Kaziak)[JAM 1.1] Testing not for Fun (Evgeny Kaziak)
[JAM 1.1] Testing not for Fun (Evgeny Kaziak)
 

Similar to [JAM 1.1] Clean Code (Paul Malikov)

Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6
Technopark
 
2015-12-06 Максим Юнусов - Проектирование REST приложения, или нужно ли прогр...
2015-12-06 Максим Юнусов - Проектирование REST приложения, или нужно ли прогр...2015-12-06 Максим Юнусов - Проектирование REST приложения, или нужно ли прогр...
2015-12-06 Максим Юнусов - Проектирование REST приложения, или нужно ли прогр...
HappyDev
 

Similar to [JAM 1.1] Clean Code (Paul Malikov) (20)

Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"
 
Разработка крупного Standalone проекта на юнити: улучшаем производительность
Разработка крупного Standalone проекта на юнити: улучшаем производительностьРазработка крупного Standalone проекта на юнити: улучшаем производительность
Разработка крупного Standalone проекта на юнити: улучшаем производительность
 
C#. От основ к эффективному коду
C#. От основ к эффективному кодуC#. От основ к эффективному коду
C#. От основ к эффективному коду
 
course js day 2
course js day 2course js day 2
course js day 2
 
Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6
 
лабраб 7
лабраб 7лабраб 7
лабраб 7
 
Объектно-ориентированное программирование. Лекции 9 и 10
Объектно-ориентированное программирование. Лекции 9 и 10Объектно-ориентированное программирование. Лекции 9 и 10
Объектно-ориентированное программирование. Лекции 9 и 10
 
Database (Lecture 14 – database)
Database (Lecture 14 – database)Database (Lecture 14 – database)
Database (Lecture 14 – database)
 
SQL-ник DevDay. Каменский. Расширенный SQL в MySQL и PostgreSQL. Сравнение во...
SQL-ник DevDay. Каменский. Расширенный SQL в MySQL и PostgreSQL. Сравнение во...SQL-ник DevDay. Каменский. Расширенный SQL в MySQL и PostgreSQL. Сравнение во...
SQL-ник DevDay. Каменский. Расширенный SQL в MySQL и PostgreSQL. Сравнение во...
 
Язык программирования C#
Язык программирования C#Язык программирования C#
Язык программирования C#
 
2015-12-06 Максим Юнусов - Проектирование REST приложения, или нужно ли прогр...
2015-12-06 Максим Юнусов - Проектирование REST приложения, или нужно ли прогр...2015-12-06 Максим Юнусов - Проектирование REST приложения, или нужно ли прогр...
2015-12-06 Максим Юнусов - Проектирование REST приложения, или нужно ли прогр...
 
Java осень 2014 занятие 3
Java осень 2014 занятие 3Java осень 2014 занятие 3
Java осень 2014 занятие 3
 
Вещи в Java, о которых вы (возможно) не знали
Вещи в Java, о которых вы (возможно) не зналиВещи в Java, о которых вы (возможно) не знали
Вещи в Java, о которых вы (возможно) не знали
 
Groovy и Grails. Быстро и обо всём
Groovy и Grails. Быстро и обо всёмGroovy и Grails. Быстро и обо всём
Groovy и Grails. Быстро и обо всём
 
Java Generics: What it is and How to Implement it
Java Generics: What it is and How to Implement itJava Generics: What it is and How to Implement it
Java Generics: What it is and How to Implement it
 
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
 
основы Java переменные, циклы
основы Java   переменные, циклыосновы Java   переменные, циклы
основы Java переменные, циклы
 
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
 
Lambdas in java 8
Lambdas in java 8Lambdas in java 8
Lambdas in java 8
 
Unit test быстрый старт
Unit test быстрый стартUnit test быстрый старт
Unit test быстрый старт
 

[JAM 1.1] Clean Code (Paul Malikov)

  • 2. содержание • в чем проблема? • названия • функции • комментарии • форматирование • классы
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 15. содержательные имена имя должно передавать намерение программиста // elapsed time in days int elapsedTimeInDays; int d; int daysSinceCreation; int dd; int daysSinceModification; int d2; int fileAgeInDays;
  • 16. Явный код Неявный код лучше неявного public List<int[]> getThem() { List<int[]> list1 = public List<int[]> getFlaggedCells() { new ArrayList<int[]>(); List<int[]> flaggedCells = new ArrayList<int[]>(); for (int[] x : theList) for (int[] cell : gameBoard) if (x[0] == 4) if (cell[STATUS_VALUE] == FLAGGED) list1.add(x); flaggedCells.add(cell); return flaggedCells; return list1; } } 1. Что хранится в theList? public List<Cell> getFlaggedCells() { 2. Почему так важен нулевой List<Cell> flaggedCells = new ArrayList<Cell>(); элемент x[0]? for (Cell cell : gameBoard) 3. Что означает 4? if (cell.isFlagged()) flaggedCells.add(cell); 4. Как использовать return flaggedCells; возвращаемое значение? }
  • 17. Явный код Неявный код лучше неявного public List<int[]> getThem() { List<int[]> list1 = public List<int[]> getFlaggedCells() { new ArrayList<int[]>(); List<int[]> flaggedCells = new ArrayList<int[]>(); for (int[] x : theList) for (int[] cell : gameBoard) if (x[0] == 4) if (cell[STATUS_VALUE] == FLAGGED) list1.add(x); flaggedCells.add(cell); return flaggedCells; return list1; } } 1. Что хранится в theList? public List<Cell> getFlaggedCells() { 2. Почему так важен нулевой List<Cell> flaggedCells = new ArrayList<Cell>(); элемент x[0]? for (Cell cell : gameBoard) 3. Что означает 4? if (cell.isFlagged()) flaggedCells.add(cell); 4. Как использовать return flaggedCells; возвращаемое значение? }
  • 18. избегайте дезинформации • избегайте названий, значение которых зависит от контекста hp - hipotenuse aix - augmentationIndex sco - spaceControlOficer • hp, aix, sco - названия Unix платформ
  • 19. избегайте дезинформации • аккуратно используйте специфические программерские названия accountList - type of List<T>? • используйте альтернативные названия accountGroup bunchOfAccounts accounts
  • 20. избегайте дезинформации • избегайте слабо отличающихся имен XYZControllerForHandlingOfStrings XYZControllerForStorageOfStrings
  • 21. избегайте дезинформации • не используйте последовательную нумерацию 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]; } }
  • 22. избегайте дезинформации • не используйте лишние слова (noise words) ProductInfo - Product theMessage - message moneyAmount - money accountData - account
  • 23. используйте произносимые имена • 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"; };
  • 24. используйте имена, удобные для поиска • используйте имена переменных из одной буквы только в локальной области видимости в маленьких методах e - самая встречаемая буква алфавита • не используйте численные константы MAX_CLASSES_PER_STUDENT вместо 7
  • 25. используйте имена, удобные для поиска 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; }
  • 26. названия методов • должны выражать действие • с перегруженными конструкторами можно использовать static factory методы с названиями, описывающими агрументы Complex fulcrumPoint = new Complex(23.0); Complex fulcrumPoint = Complex.FromRealNumber(23.0);
  • 27. размер методов • методы должны быть маленкими • еще меньше! • это подразумевает однострочные if, esle, while (названия методов отлично документируют ветвление) • и вложенные структуры не глубже второго уровня
  • 28. 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(); }
  • 29. правило одной операции • функция должна выполнять только одну операцию • она должна выполнять ее хорошо • и ничего другого она делать не должна • один уровень абстракции на функцию
  • 30. 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()); }
  • 31. аргументы функции • zero (niladic) - наилучший вариант • one (monadic) • two (dyadic) • three (triadic) • more (polyadic) - следует избегать
  • 32. аргументы функции • с точки зрения тестирования малое количество аргументов упрощает перебор комбинаций • использование выходных аргументов нарушает общую идею подачи исходных данных в качестве аргументов и получение результата через возвращаемое значение функции
  • 34. типичные случаи monadic • проверка условия, связанного с аргументом boolean contains(“MyValue”) • обработка аргумента, его преобразование и возвращение InputStream fileOpen(“MyFile”) • сообщение о событии void passwordAttemptFailedNtimes(int attempts)
  • 35. типичные случаи monadic • старайтесь избегать выходных аргументов void transform(StringBuffer out) • используйте возвращаемое значение StringBuffer transform(StringBuffer in)
  • 37. типичные случаи diadic • более сложны для понимания writeField(outputStream, name) -> outputStream.writeField(name) • подходят для агрументов с естественным порядком Point p = new Point(x,y);
  • 38. типичные случаи diadic • если порядок не известен, можно преобразовать в monadic compare(expected, actual) -> object.compare(expected)
  • 40. разделение команд и запросов • функция должна либо делать что-то, либо отвечать на какой-то вопрос, но не оба действия вместе public boolean set(String attribute, String value); if (set("username", "unclebob"))... • метод устанавливает атрибут? • или метод проверяет значение атрибута?
  • 41. разделение команд и запросов public boolean setAndCheckIfExists(String attribute, String value); if (attributeExists("username")) { setAttribute("username", "unclebob"); ... }
  • 42. использование исключений • старайтесь использовать исключения вместо кодов ошибок в качестве возвращаемого значения
  • 43. 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()); }
  • 44. комментарии • не делают плохой код лучше • объясняйте при помощи кода // 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) ...
  • 45. комментарии • закомментированный код должен удаляться • для читателя такой код означает, что есть серьезная причина, по которой этот код не был удален
  • 46. форматирование • вертикальное форматирование и метафора газетной статьи • первый параграф дает вам общее описание статьи • прочитав его, вы определяете, та ли это статья, которая вам нужна • чем дальше, тем больше дателей • газета состоит из статей маленьких и побольше • если бы газета состояла из одной большой статьи, ее невозможно было бы читать
  • 47. классы • классы должны быть маленькие • еще меньше! • единица измерения - количество обязанностей (responsibility count)
  • 48. название класса • должно выражать его обязанность • название, по сути, один из первых способов определить размер класса • слова Processor, Manager, Super указывают на совмещение обязанностей • опишите класс в 25 словах, не употребляя “если”, “и”, “или”, “но”
  • 49. Single Responsibility Principle • утверждает, что класс или модуль должен иметь одну и только одну причину для изменения • наиболее часто игнорируется программистами, т.к. считают, что их работа закончена после того, как код начал работать
  • 50. 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(); }
  • 51. связность • классы должны иметь небольшое количество переменных экземпляра • каждый метод класса должен оперировать с этими переменными • чем больше переменных, с которыми оперируют методы (для каждого метода), тем выше связность
  • 52. 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; } }
  • 53. связность • разбиение функций ведет к снижению связности • если классы утрачивают связность, разбейте их!
  • 54. что еще в этой книге? • обработка ошибок • модульные тесты • системы • формирование архитектуры • многопоточность • smells and heruistics
  • 55. литература • 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