Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Czysty Kod Wprowadzenie Przygotował Adam Zawadzki.

Podobne prezentacje


Prezentacja na temat: "Czysty Kod Wprowadzenie Przygotował Adam Zawadzki."— Zapis prezentacji:

1 Czysty Kod Wprowadzenie Przygotował Adam Zawadzki

2 Dlaczego warto dbać o na jakość kodu? Dług techniczny Nazewnictwo Metody Komentarze Formatowanie Obsługa wyjątków Klasy Zewnętrzne biblioteki Agenda

3 Jakosć kodu ma wpływ na prodkuktywność Jakość kodu wpływa na nasze nastawienie do pracy Dlaczego warto dbać o na jakość kodu?

4 Dług techniczny

5 Czysty Kod Nazewnictwo

6 Używanie innego języka niż angielski w nazewnictwie

7 public List getThem() { List list1 = new ArrayList (); for (int[] x : theList) { if (x[0] == 4) list1.add(x); } return list1; } Używaj nazw odzwierciedlających Twoje intencje

8 public List getFlaggedCells() { List flaggedCells = new ArrayList (); for (int[] cell : gameBoard) if (cell[STATUS_VALUE] == FLAGGED) flaggedCells.add(cell); return flaggedCells; } public List getFlaggedCells() { List flaggedCells = new ArrayList (); for (Cell cell : gameBoard) if (cell.isFlagged()) flaggedCells.add(cell); return flaggedCells; } Używaj nazw odzwierciedlających Twoje intencje

9 String hp; Integer aix; accountList; XYZControllerForEfficientHandlingOfStrings XYZControllerForEfficientStorageOfStrings Unikaj dezinformacji w nazewnictwie

10 public static void copyChars(char a1[], char a2[]) { for (int i = 0; i < a1.length; i++) { a2[i] = a1[i]; } Znaczące rozróżnienia

11 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"; /*... */ }; Używaj nazw które da się wymówić

12 public class Part { private String m_dsc; // The textual description void setName(String name) { m_dsc = name; } public class Part { String description; void setDescription(String description) { this.description = description; } Unikaj prefixów

13 Nazwa klasy powinna być rzeczownikiem: Customer, WikiPage, Account, AddressParser Unikaj nazw takich jak Manager, Processor, Data, or Info Nie używaj czaswoników w nazwach klas Nazwy klas

14 Nazwy metod wykonujacych operacje powinnt być czasownikami: deletePage, savePersistable, addToList. Metody będąco akcesorami, mutatorami lub predykatami powinny być nazywane zgodnie z konwencją java beans: get, set, is. Nie próbuj demnonstrować swojego poczucia humoru w kodzie. Jest to nieakceptowalne. Nazwy metod

15 Jeżeli w danym projekcie dla akcesorów przyjęto nadawać nazwy z jednym przedrostkiem(get, fetch, retrieve) trzymaj się tej konwencji. Unikajmy mieszania koncepcji: Używając wzorca MVC nie nazywajmy klasy kontrolera: CustomerManager Nie zastępujmy końcówki Manager używając Driver Należy pamiętać że spójny słownik to ważny element czytelnego kodu. Używaj zawsze tego samego słowa dla danej koncepcji

16 Czytającym Twój kod będzie inny programista Rozwiązania techniczne opisuj przy pomocy terminów technicznych: AccountVisitor, CustomerFactory, JobQueue. Używaj nazw w domenie rozwiązania

17 Jeżeli projektujemy system obsługujący lotnisko to zamiast używać słowa: vehicle użyjmy słowa airplane, zamiast zlepku aSubstanceWhichKeepsAirplaneFlying użyjmy fuel Keep it simple. Używaj nazw w domenie problemu

18 Czysty Kod Metody

19 Im dłuższa funkcja tym mniej czytelna public static String renderPageWithSetupsAndTeardowns( PageData pageData, boolean isSuite) throws Exception { if (isTestPage(pageData)) includeSetupAndTeardownPages(pageData, isSuite); return pageData.getHtml(); } Funkcje muszą być małe

20 Jedna funkcja robi wyłącznie jedną rzecz w danym kontekście

21 public void renderAddressDataTableForPerson(Person p) AddressData[] allAddressData = getAllAddressData(); AddressData personAddresData = getPersonAddresData(p, addressData); rednerAddresDataTable(personAddresData); } private AddressData[] getAllAddressData(){ connectDatabase(); AddressData[] addressData = fetchAllAddressData(); disconnectDatabase(); return addressData; } private void connectDatabase(){ /* Connect database. */ } private void fetchAllAddressData(){ /* Fetch all address data from database. */ } private void disconnectDatabase(){ /* Disconnect database. */ } private AddressData getPersonAddresData(Person p, AddressData[] addressData){ /* Iterate over array and return address of selected person. */ } private AddressData rednerAddressDataTable(AddressData addressData){ /* Render address table. */ } Dana funkcja powinna wykonywać operacje na jednym poziomie abstrakcji

22 public void doSomething(String input){ try { doSomethingWell(input); } catch(Exception ex) { LOGGER.error(ex.getMessage(), ex); } private void doSomethingWell(String input){ /* * Do something well. */ doSomethingVeryWell(input); } private void doSomethingVeryWell(String input){ /* * Do something very well. */ } Zasada Stepdown

23 Nazwy muszą być jednoznaczne w danym kontekscie Nazwy muszą być spójne między sobą Używaj opisowych nazw funkcji

24 Funkcje bezargumentowe są świetne: record.remove(); Funkcje z jednym argumentem są bardzo dobre: file.save(„output”); Funkcje z dwoma argumentami są dobre: file.open(„input”, „r”); Funkcje z trzema są akceptowalne: assertEquals(message, expected, actual); Funkcje z więcej niż trzema argumentami są wstrętne i należy ich unikać. Funkje z argumentami flagowymi powinny być unikane. Łamią zasadę SPR. Listy argumentów: void monad(Integer... args); void dyad(String name, Integer... args); void triad(String name, int count, Integer... args); Argumenty funkcji

25 public class UserValidator { private Cryptographer cryptographer; public boolean checkPassword(String userName, String password) { User user = UserGateway.findByName(userName); if (user != User.NULL) { String codedPhrase = user.getPhraseEncodedByPassword(); String phrase = cryptographer.decrypt(codedPhrase, password); if ("Valid Password".equals(phrase)) { Session.initialize(); return true; } return false; } Efekty uboczne

26 appendFooter(s); report.appendFooter(); Argumenty wyjściowe

27 public boolean set(String attribute, String value); if (set("username", "unclebob")){ /*... */ } if (attributeExists("username")) { setAttribute("username", "unclebob"); //... } Separuj komendy od zapytań

28 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; } Używaj wyjątków, nie kodów błędów.

29 try { deletePage(page); registry.deleteReference(page.name); configKeys.deleteKey(page.name.makeKey()); }catch (Exception e) { logger.log(e.getMessage()); } Używaj wyjątków, nie kodów błędów.

30 public void delete(Page page) { try { deletePageAndAllReferences(page); }catch (Exception e) { logError(e); } private void deletePageAndAllReferences(Page page) throws Exception { deletePage(page); registry.deleteReference(page.name); configKeys.deleteKey(page.name.makeKey()); } private void logError(Exception e) { logger.log(e.getMessage()); } Bloki try/catch

31 Wydzielaj obsługę błędów. Nie duplikuj kodu. Jeżeli coś powtarza się dwa razy można z tego zrobić oddzielną funkcję. Refaktoryzuj Dodatkowo

32 Czysty Kod Komentarze. Nie sprawiają, że zły kod staje się lepszy.

33 // Check to see if the employee is eligible for full benefits if ((employee.flags & HOURLY_FLAG) && (employee.age > 65)) if (employee.isEligibleForFullBenefits()) Wyjaśniaj za pomocą kodu

34 Licencje Informacje: // format matched kk:mm:ss EEE, MMM dd, yyyy Pattern timeMatcher = Pattern.compile(„\\d*:\\d*:\\d* \\w*, \\w* \\d*, \\d*"); Wyjaśnienie intencji: public int compareTo(Object o) { if(o instanceof WikiPagePath) { WikiPagePath p = (WikiPagePath) o; String compressedName = StringUtil.join(names, ""); String compressedArgumentName = StringUtil.join(p.names, ""); return compressedName.compareTo(compressedArgumentName); } return 1; // we are greater because we are the right type. } Dobre komentarze

35 Wyjaśnienia public void testCompareTo() throws Exception { WikiPagePath a = PathParser.parse("PageA"); WikiPagePath ab = PathParser.parse("PageA.PageB"); WikiPagePath b = PathParser.parse("PageB"); WikiPagePath aa = PathParser.parse("PageA.PageA"); WikiPagePath bb = PathParser.parse("PageB.PageB"); WikiPagePath ba = PathParser.parse("PageB.PageA"); assertTrue(a.compareTo(a) == 0); // a == a assertTrue(a.compareTo(b) != 0); // a != b assertTrue(ab.compareTo(ab) == 0); // ab == ab assertTrue(a.compareTo(b) == -1); // a < b assertTrue(aa.compareTo(ab) == -1); // aa < ab assertTrue(ba.compareTo(bb) == -1); // ba < bb assertTrue(b.compareTo(a) == 1); // b > a assertTrue(ab.compareTo(aa) == 1); // ab > aa assertTrue(bb.compareTo(ba) == 1); // bb > ba } Dobre komentarze

36 Ostrzeżenia o konsekwencjach Dobre komentarze // Don't run unless you // have some time to kill. public void _testWithReallyBigFile() { writeLinesToFile( ); response.setBody(testFile); response.readyToSend(this); String responseString = output.toString(); assertSubString("Content-Length: ", responseString); assertTrue(bytesSent > ); }

37 TODO’s Dobre komentarze //TODO-MdM these are not needed // We expect this to go away when we do the checkout model protected VersionInfo makeVersion() throws Exception { return null; }

38 Wzmocnienia Java Docs w publicznym API Dobre komentarze String listItemContent = match.group(3).trim(); // the trim is real important. It removes the starting // spaces that could cause the item to be recognized // as another list. new ListItemWidget(this, listItemContent, this.level + 1); return buildList(text.substring(match.end()));

39 Mamrotanie public void loadProperties() { try { String propertiesPath = propertiesLocation + "/" + PROPERTIES_FILE; FileInputStream propertiesStream = new FileInputStream(propertiesPath); loadedProperties.load(propertiesStream); }catch(IOException e){ // No properties files means all defaults are loaded } Złe komentarze

41 Zbędne komentarze public abstract class ContainerBase implements Container, Lifecycle, Pipeline, MBeanRegistration, Serializable { /** * The processor delay for this component. */ protected int backgroundProcessorDelay = -1; /** * The container event listeners for this Container. */ protected ArrayList listeners = new ArrayList(); /** * The Loader implementation with which this Container is * associated. */ protected Loader loader = null; /** * The Logger implementation with which this Container is * associated. */ protected Log logger = null; } Złe komentarze

42 Obowiązkowe komentarze /** * title The title of the CD author The author of the CD tracks The number of tracks on the CD durationInMinutes The duration of the CD in minutes */ public void addCD(String title, String author,int tracks, int durationInMinutes) { CD cd = new CD(); cd.title = title; cd.author = author; cd.tracks = tracks; cd.duration = duration; cdList.add(cd); } Złe komentarze

43 Dzienniki zmian /* * Changes (from 11-Oct-2001) * * 11-Oct-2001 : Re-organised the class and moved it to new package * com.jrefinery.date (DG); * 05-Nov-2001 : Added a getDescription() method, and eliminated NotableDate * class (DG); * 12-Nov-2001 : IBD requires setDescription() method, now that NotableDate * class is gone (DG); Changed getPreviousDayOfWeek(), * getFollowingDayOfWeek() and getNearestDayOfWeek() to correct bugs (DG); * 05-Dec-2001 : Fixed bug in SpreadsheetDate class (DG); * 29-May-2002 : Moved the month constants into a separate interface (MonthConstants) (DG); */ Złe komentarze

44 Komentarze robiące zbędny szum Złe komentarze

45 Przerażający szum JavaDoc /** The name. */ private String name;private String name; /** The version. */ private String version;private String version; /** The licenceName. */ private String licenceName;private String licenceName; /** The version. */ private String info;private String info; Złe komentarze

46 Markery pozycji : /// Actions ////////////////////////////////// Komentarze zamykające: try{ while ((line = in.readLine()) != null) { lineCount++; charCount += line.length(); String words[] = line.split("\\W"); wordCount += words.length; } //while System.out.println("wordCount = " + wordCount); System.out.println("lineCount = " + lineCount); System.out.println("charCount = " + charCount); } // try catch (IOException e) { System.err.println("Error:" + e.getMessage()); } //catch Złe komentarze

47 Komentarze na temat autora: // By Wykomentowany kod: InputStreamResponse response = new InputStreamResponse(); response.setBody(formatter.getResultStream(), formatter.getByteCount()); // InputStream resultsStream = formatter.getResultStream(); // StreamReader reader = new StreamReader(resultsStream); // response.setContent(reader.read(formatter.getByteCount())); Złe komentarze

48 Komentarze HTML: Złe komentarze

49 Informacje nie dotyczące danego fragmentu kodu: /** * Port on which fitnesse would run. Defaults to * fitnessePort */ public void setFitnessePort(int fitnessePort) { this.fitnessePort = fitnessePort; } Nie jasne komentarze: /* * start with an array that is big enough to hold all the pixels * (plus filter bytes), and an extra 200 bytes for header info */ this.pngBytes = new byte[((this.width + 1) * this.height * 3) + 200]; Złe komentarze

50 JavaDoc’s w niepublicznym kodzie: /** * Method foo which is doing something; int */ private int foo(String s); Złe komentarze

51 Czysty Kod Formatowanie

52 Na danym projekcie wszyscy powinni się stosować do tych samych zasad formatowania Zawsze należy usuwać trailing spaces z kodu. Ogólne zasady formatowania

53 Im plik jest krótszy tm bardziej czytelny Kod w pliku powinien być tak ułożony, aby wspierać czytanie go z góry do dołu. Przestrzenie w pionie powinny rozdzielać różne koncepcje: Formatowanie pionowe

54 Zmienne powinny być deklarowane jak najbliżej miejsca w którym będą używane Funkcje zależne powinny być ułożone obok siebie Funkcje obejmujące jedna koncepcję powinny być ułożone blisko siebie Formatowanie pionowe

55 Unikajmy ściskania kodu w poziomie Wstawiajmy spacje żeby zwiększyć czytelność kodu: public class Quadratic { public static double root1(double a, double b, double c) { double determinant = determinant(a, b, c); return (-b + Math.sqrt(determinant)) / (2*a); } public static double root2(int a, int b, int c) { double determinant = determinant(a, b, c); return (-b - Math.sqrt(determinant)) / (2*a); } private static double determinant(double a, double b, double c) { return b*b - 4*a*c; } Formatowanie poziome

56 Unikajmy wyrównywania w poziomie: Formatowanie poziome

57 Wcięcia w kodzie zwiększają jego czytelność: Długość linii nie powinna przekraczać około 120 znaków Formatowanie poziome

58 Czysty Kod Obsługa wyjątków

59 Jedna funkcja = jeden blok try/catch public List retrieveSection(String sectionName) { try { FileInputStream stream = new FileInputStream(sectionName) } catch (Exception e) { throw new StorageException("retrieval error", e); } return new ArrayList (); }

60 Z wyjątkiem dostarczaj kontekst

61 Nie zwracaj NULL public void registerItem(Item item) { if (item != null) { ItemRegistry registry = peristentStore.getItemRegistry(); if (registry != null) { Item existing = registry.getItem(item.getID()); if (existing.getBillingPeriod().hasRetailOwner()) { existing.register(item); }

62 Nie przekazuj NULL public double xProjection(Point p1, Point p2) { if (p1 == null || p2 == null) { throw InvalidArgumentException( "Invalid argument for MetricsCalculator.xProjection"); } return (p2.x – p1.x) * 1.5; }

63 Czysty Kod Praca z zewnętrznymi bibliotekami

64 Opakowuj zewnętrzny kod Napisz testy dla wykorzystywanych zewnętrznych funkcjonalności Zewnętrzne biblioteki

65 Czysty Kod Klasy

66 Zgodnie ze standardami, na samym początku zawsze umieszczamy pola klasy. Klasa powinna udostępniać na zewnątrz tylko funkcje odpowiedzialne za realizację konkretnych zadań. Nie istotnie jest to jak je realizuje. Mechanika powinna być ukryta. Organizacja klasy

67 The Single Responsibility Principle. Nigdy nie powinien istnieć więcej niż jeden powód do zmiany klasy. Spójność. Klasy powinny mieć małą liczbę zmiennych instancyjnych. Każda metoda klasy powinna manipulować przynajmniej jedną zmienną. Klasy powinny być małe

68 Bibliografia Clean Code: A Handbook of Agile Software Craftsmanship By Robert C. Martin


Pobierz ppt "Czysty Kod Wprowadzenie Przygotował Adam Zawadzki."

Podobne prezentacje


Reklamy Google