• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
[JAM 1.1] Clean Code (Paul Malikov)
 

[JAM 1.1] Clean Code (Paul Malikov)

on

  • 1,026 views

Clean Code

Clean Code

Statistics

Views

Total Views
1,026
Views on SlideShare
1,010
Embed Views
16

Actions

Likes
0
Downloads
6
Comments
0

1 Embed 16

http://jamevent.blogspot.com 16

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    [JAM 1.1] Clean Code (Paul Malikov) [JAM 1.1] Clean Code (Paul Malikov) Presentation Transcript

    • Понятный код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) - следует избегать
    • аргументы функции• с точки зрения тестирования малое количество аргументов упрощает перебор комбинаций• использование выходных аргументов нарушает общую идею подачи исходных данных в качестве аргументов и получение результата через возвращаемое значение функции
    • niladicvoid saveTheMankind()
    • типичные случаи monadic• проверка условия, связанного с аргументом boolean contains(“MyValue”)• обработка аргумента, его преобразование и возвращение InputStream fileOpen(“MyFile”)• сообщение о событии void passwordAttemptFailedNtimes(int attempts)
    • типичные случаи monadic• старайтесь избегать выходных аргументов void transform(StringBuffer out)• используйте возвращаемое значение StringBuffer transform(StringBuffer in)
    • monadicMrs marry(Miss girl)
    • типичные случаи diadic• более сложны для понимания writeField(outputStream, name) -> outputStream.writeField(name)• подходят для агрументов с естественным порядком Point p = new Point(x,y);
    • типичные случаи diadic• если порядок не известен, можно преобразовать в monadiccompare(expected, actual) -> object.compare(expected)
    • diadiccompare(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 benefitsif ((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