B4B33RPH: Řešení problémů a hry PEP 8. Čistý kód.

Podobné dokumenty
A4B99RPH: Řešení problémů a hry Čistý kód.

Chyby a výjimky. Chyba. Odkud se chyby berou? Kdo chyby opravuje? Co můžete dělat jako programátor? Dvě hlavní metody práce s chybami.

Automatické testování softwaru. Testujte svůj kód! Předpoklady: Příklad: sum_digits() Možnost 1: Zkusíme funkci použít v konzoli Pythonu.

1, Žáci dostanou 5 klíčových slov a snaží se na jejich základě odhadnout, o čem bude následující cvičení.

WORKSHEET 1: LINEAR EQUATION 1

Čipové karty Lekařská informatika

Dynamic programming. Optimal binary search tree

Tento materiál byl vytvořen v rámci projektu Operačního programu Vzdělávání pro konkurenceschopnost.

Jak postupovat při zpracování jednotlivých částí testu: Flyers

Pascal. Katedra aplikované kybernetiky. Ing. Miroslav Vavroušek. Verze 7

SPJA, cvičení 1. ipython, python, skripty. základy syntaxe: základní datové typy, řetězce. podmínky: if-elif-else, vyhodnocení logických výrazů

VY_32_INOVACE_06_Předpřítomný čas_03. Škola: Základní škola Slušovice, okres Zlín, příspěvková organizace

Kámen-nůžky-papír. Tomáš Svoboda Centrum strojového vnímání, Katedra kybernetiky Fakulta elektrotechnická, České vysoké učení technické

2. Entity, Architecture, Process

Kámen-nůžky-papír. Tomáš Svoboda Centrum strojového vnímání, Katedra kybernetiky Fakulta elektrotechnická, České vysoké učení technické

Jak importovat profily do Cura (Windows a

Evoluční algoritmy. Podmínka zastavení počet iterací kvalita nejlepšího jedince v populaci změna kvality nejlepšího jedince mezi iteracemi

Gymnázium, Brno, Slovanské nám. 7, SCHEME OF WORK Mathematics SCHEME OF WORK. cz

Introduction to MS Dynamics NAV

EU peníze středním školám digitální učební materiál

Python profesionálně: dynamické parametry, generátory, lambda funkce... with. Dynamické parametry

Czech Republic. EDUCAnet. Střední odborná škola Pardubice, s.r.o.

IB111 Úvod do programování skrze Python Přednáška 7

Transportation Problem

Gymnázium, Brno, Slovanské nám. 7 WORKBOOK. Mathematics. Teacher: Student:

Úvod do Operačních Systémů

3. Řízení běhu programu

Doxygen. Jakub Břečka

UPM3 Hybrid Návod na ovládání Čerpadlo UPM3 Hybrid 2-5 Instruction Manual UPM3 Hybrid Circulation Pump 6-9

Compression of a Dictionary

ČTENÍ. M e t o d i c k é p o z n á m k y k z á k l a d o v é m u t e x t u :

Název projektu: Multimédia na Ukrajinské

Konečný automat. Jan Kybic.

Algoritmizace a programování

Střední průmyslová škola strojnická Olomouc, tř.17. listopadu 49

Úvod do programovacích jazyků (Java)

PG 9.5 novinky ve vývoji aplikací

Granit 1280i. Stručný návod k použití. Industrial Full Range Laser Scanner CZ-QS Rev A 1/14

Semestrální práce z předmětu. Jan Bařtipán / A03043 bartipan@studentes.zcu.cz

Vestavěné nástroje Pythonu

VY_22_INOVACE_60 MODAL VERBS CAN, MUST

Caroline Glendinning Jenni Brooks Kate Gridley. Social Policy Research Unit University of York

Číslo materiálu: VY 32 INOVACE 29/18. Číslo projektu: CZ.1.07/1.4.00/

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

EXACT DS OFFICE. The best lens for office work

Next line show use of paragraf symbol. It should be kept with the following number. Jak může státní zástupce věc odložit zmiňuje 159a.

Tematický celek Proměnné. Proměnné slouží k dočasnému uchovávání hodnot během provádění aplikace Deklarace proměnných

ITICA. SAP Školení přehled Seznam kurzů

LOGOMANUÁL / LOGOMANUAL

PL/SQL. Jazyk SQL je jazykem deklarativním, který neobsahuje procedurální příkazy jako jsou cykly, podmínky, procedury, funkce, atd.

Algoritmus. Algoritmus je posloupnost kroků, které jsou potřeba k vyřešení problému.

Programování v Pythonu

POSLECH. Anglický jazyk 9. třída Mgr. Martin Zicháček. Jazyk Úroveň Autor Kód materiálu. Z á k l a d o v ý t e x t :

JAVA. Další jazyky kompilovatelné do Java byte-code

Automatika na dávkování chemie automatic dosing

Arduino Ethernet Shield W5100 R3

Litosil - application

Využití OOP v praxi -- Knihovna PHP -- Interval.cz

Statické proměnné a metody. Tomáš Pitner, upravil Marek Šabo

Obsah přednášky. programovacího jazyka. Motivace. Princip denotační sémantiky Sémantické funkce Výrazy Příkazy Vstup a výstup Kontinuace Program

Vánoční sety Christmas sets

Výjimky. Tomáš Pitner, upravil Marek Šabo

CODE BOOK NEISS 8. A code book is an identification tool that allows the customer to perform a test result evaluation using a numeric code.

Přechod webových aplikací na Python 3 Tomáš Pazderka 6. listopadu 2018

Výukový materiál zpracovaný v rámci operačního programu Vzdělávání pro konkurenceschopnost

Škola: Střední škola obchodní, České Budějovice, Husova 9. Inovace a zkvalitnění výuky prostřednictvím ICT

Problém identity instancí asociačních tříd

Vytvoření pokročilé Fotogalerie v Drupalu - Views

Agilní metodiky vývoje softwaru

Střední odborná škola stavební a Střední odborné učiliště stavební Rybitví

Housework, professions, jobs, services, tradition/culture.

PSANÍ. (1) My address is Dlouhá 34, Liberec. Thank you and!

Website review vaznikystrechy.eu

ALGORITMIZACE A PROGRAMOVÁNÍ

VYUŽITÍ DATA DRIVEN PAGES

Jméno autora: Mgr. Alena Chrastinová Datum vytvoření: Číslo DUMu: VY_32_INOVACE_O7_AJ

Funkce, podmíněný příkaz if-else, příkaz cyklu for

PRIMÁRNÍ MODÁLNÍ SLOVESA CAN

Funkce - opakování. Funkce může přijímat parametry na vstupu a může vracet parametry na výstupu.

Název společnosti: VPK, s.r.o. Vypracováno kým: Ing. Michal Troščak Telefon: Datum:

Postřehová hra. Zadání projektu. 1 Moje cíle

Výukový materiál zpracován v rámci projektu EU peníze školám

Projekt: ŠKOLA RADOSTI, ŠKOLA KVALITY Registrační číslo projektu: CZ.1.07/1.4.00/ EU PENÍZE ŠKOLÁM

Chapter 7: Process Synchronization

POSLECH. M e t o d i c k é p o z n á m k y k z á k l a d o v é m u t e x t u :

Tento materiál byl vytvořen v rámci projektu Operačního programu Vzdělávání pro konkurenceschopnost.

User manual SŘHV Online WEB interface for CUSTOMERS June 2017 version 14 VÍTKOVICE STEEL, a.s. vitkovicesteel.com

Cvičení 9 - Monitory. monitor m; var proměnné... procedure p; begin... end; begin inicializace; end;

LOGBOOK. Blahopřejeme, našli jste to! Nezapomeňte. Prosím vyvarujte se downtrade

Samovysvětlující pozemní komunikace

EURO přeshraniční platba

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

Třídění a vyhledávání Searching and sorting

První kapitola úvod do problematiky

PREPROCESOR POKRAČOVÁNÍ

UŽIVATELSKÁ PŘÍRUČKA

Název projektu: Multimédia na Ukrajinské

PSANÍ. M e t o d i c k é p o z n á m k y k z á k l a d o v é m u t e x t u : My family, my hobbies Present simple and continuous, Wh- questions

Výuka programování v jazyce Python

Čtvrtý Pentagram The fourth Pentagram

Transkript:

B4BRPH: Řešení problémů a hry PEP 8. Čistý kód. Petr Pošík Katedra kybernetiky ČVUT FEL Formátování kódu 2 Proč?.............................................................................................................. PEP 8.............................................................................................................. 4 Doporučení........................................................................................................ 5 Clean Code 6 Který kód je čistší? A proč?........................................................................................... 7 Co je clean code?.................................................................................................. 8 Čistý kód v praxi................................................................................................... 9 Smysluplná jména................................................................................................. 10 Eratostenovo síto: smysluplná jména................................................................................. 11 Komentáře........................................................................................................ 12 Eratostenovo síto: komentáře........................................................................................ 1 Funkce a metody................................................................................................... 14 Eratostenovo síto: funkce........................................................................................... 15 Eratostenovo síto: pomocná třída?.................................................................................... 16 Příklad Podle přednáškyraymond Hettinger: Beyond PEP 8 Best Practices for Beautiful Intelligible Code. PyCon 2015 17 Původní kód...................................................................................................... 18 Podle PEP 8....................................................................................................... 19 Lepší kód......................................................................................................... 20 Modulnettools................................................................................................... 21 Závěr............................................................................................................. 22 1

Formátování kódu 2 / 22 Proč je důležité formátování? Kód je čten mnohem častěji než psán. Na čitelnosti záleží. Použitý formát/styl by měl čtenáři pomáhat vizuálně sdružovat věci, které spolu souvisí, vizuálně oddělovat věci, které nejsou těsně svázané; vizuálně evokovat začátek a konec výrazu, bloku kódu, funkce, metody, třídy, atd.; a neměl by čtenáře mást. P. Pošík c 2016 B4BRPH: Řešení problémů a hry / 22 PEP 8 Python Enhancement Proposal 8: Style guide for Python code https://www.python.org/dev/peps/pep-0008/ Doporučení, jak formátovat kód tak, aby formát nebránil v jeho snadném pochopení. Konzistence s PEP 8 je důležitá, ale konzistence v rámci projektu je důležitější, konzistence v rámci jednoho modulu je nejdůležitější. Dobré důvody ignorovat určité doporučení z PEP 8: když doporučení dělá kód méně čitelným; když je třeba zachovat konzistenci v rámci modulu, či projektu (např. z historických důvodů (ale možná je to příležitost jak vyčistit nečitelný kód?); když je kód starší než doporučení a není žádný jiný důvod daný kód modifikovat; když kód musí zůstat kompatibilní se starší verzí Pythonu, která ještě nepodporuje doporučovaný způsob. Modulpep8: https://pypi.python.org/pypi/pep8 Automatická kontrola formátování kódu podle doporučení PEP 8. P. Pošík c 2016 B4BRPH: Řešení problémů a hry 4 / 22 2

Některá doporučení PEP 8 Rozložení a organizace kódu: Pro odsazení používejte 4 mezery (nikoli tabulátory). Omezte délku řádků na 79 znaků, 72 pro docstringy a komentáře. Používejte výchozí kódování UTF-8; jinak jej specifikujte v úvodu modulu např. takto: # -*- encoding: latin_1 -*- importy umístěte na začátek souboru, každý modul na zvláštní řádek Definice funkcí udržujte pohromadě. Definice tříd a funkcí nejvyšší úrovně oddělujte 2 prázdnými řádky. Definice vnořených funkcí a metod oddělujte 1 prázdným řádkem. Příkazy a volání funkcí na nejvyšší úrovni udržujte pohromadě na konci programu. Komentáře a docstringy: Komentáře pište v angličtině. (Výjimkou jsou případy, kdy jste si na 120 % jistí, že váš kód nebude číst nikdo, kdo by nerozuměl vašemu jazyku.) Konvence pro pojmenování: lowercase_with_underscores pro proměnné, funkce, moduly a balíky; CamelCase pro názvy tříd a výjimek; CAPITAL_LETTERS_WITH_UNDERSCORES pro konstanty. A to stačí, aby byl můj kód čistý??? P. Pošík c 2016 B4BRPH: Řešení problémů a hry 5 / 22 Clean Code Zpracováno podle Robert C. Martin: Clean Code: A Handbook of Agile Software Craftsmanship, Prentice Hall, 2008. 6 / 22 Který kód je čistší? A proč? Eratostenovo síto Dvě implementace téhož algoritmu: 1 def generate_primes_up_to(max_value): 2 """Find primes up to the max_value using the Sieve of Eratosthenes. 4 """ 5 if max_value >= 2: # There are some primes 6 # Initialize the list (incl. 0) 7 f = [True for i in range(max_value+1)] 8 # Get rid of the known non-primes 9 f[0] = f[1] = False 10 # Run the sieve 11 for i in range(2, len(f)): 12 if f[i]: # i is still a candidate 1 # mark its multiples as not prime 14 for j in range(2*i, len(f), i): 15 f[j] = False 16 # Find the primes and put them in a list 17 primes = [i for i in range(len(f)) if f[i]] 18 return primes 19 else: # max_value < 2 20 # no primes, return empty list 21 return list() 5 """Find primes up to the max_value 6 using the Sieve of Eratosthenes. 7 """ 8 if max_value < 2: 9 return [] 10 else: 11 candidates = init_integers_up_to(max_value) 12 mark_non_primes(candidates) 1 return collect_remaining(candidates) 14 15 def init_integers_up_to(max_value): 16 return [PRIME for i in range(max_value+1)] 17 18 def mark_non_primes(candidates): 19 # Mark 0 and 1, they are not primes. 20 candidates[0] = candidates[1] = NONPRIME 21 for number in range(2, len(candidates)): 22 if candidates[number] == PRIME: 2 mark_multiples_of(number, candidates) 24 25 def mark_multiples_of(number, candidates): 26 for multiple in range( 27 2*number, len(candidates), number): 28 candidates[multiple] = NONPRIME 29 0 def collect_remaining(candidates): 1 primes = [i for i in range(len(candidates)) 2 if candidates[i] == PRIME] return primes P. Pošík c 2016 B4BRPH: Řešení problémů a hry 7 / 22

Co je clean code? Bjarne Stroustrup, autor jazyka C++ a knihy The C++ Programming Language : I like my code to be elegant and efficient. The logic should be straightforward to make it hard for bugs to hide, the dependencies minimal to ease maintenance, error handling complete according to an articulated strategy, and performance close to optimal so as not to tempt people to make the code messy with unprincipled optimizations. Clean code does one thing well. Grady Booch, autor knihy Object Oriented Analysis and Design with Applications : Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer s intent but rather is full of crisp abstractions and straightforward lines of control. Dave Thomas, zakladatel firmy OTI (převzata firmou IBM v roce 1996), kmotr Eclipse: Clean code can be read, and enhanced by a developer other than its original author. It has unit and acceptance tests. It has meaningful names. It provides one way rather than many ways for doing one thing. It has minimal dependencies, which are explicitly defined, and provides a clear and minimal API. P. Pošík c 2016 B4BRPH: Řešení problémů a hry 8 / 22 Čistý kód v praxi Code review: Jediné správné měřítko kvality kódu: Co-to-k-čerty za minutu P. Pošík c 2016 B4BRPH: Řešení problémů a hry 9 / 22 4

Smysluplná jména Vymyslet dobrá jména je velmi těžké! Nebojte se jméno změnit, přijdete-li na lepší! Dobré jméno odhaluje autorův záměr (intention-revealing). Pokud jméno vyžaduje komentář, neodhaluje záměr. Porovnejte: self.d = 0 # Elapsed time in days self.elapsed_days = 0 Porovnejte (co když i ten komentář chybí?): st("obama", 20, False, True) search_twitter("obama", 20, False, True) Názvy tříd: podstatná jména (s přívlastky): Customer, WikiPage, AddressParser, Filter, StupidFilter, Corpus, TrainingCorpus Názvy funkcí/metod: slovesa (s předmětem): post_payment, delete_page, save, train, test, get_email Jeden termín pro jeden koncept! Nepoužívejte stejné slovo k více účelům! Nebojte se dlouhých jmen! Dlouhé popisné jméno je lepší než dlouhý popisný komentář. Čím delší oblast platnosti proměnné, tím popisnější jméno by měla mít. Používejte pojmenované konstanty místo magických čísel v kódu! Porovnejte: if opponents_move == True: if opponents_move == DEFECT: P. Pošík c 2016 B4BRPH: Řešení problémů a hry 10 / 22 Eratostenovo síto: smysluplná jména 1 def generate_primes_up_to(max_value): 2 """Find primes up to the max_value using the Sieve of Eratosthenes. 4 """ 5 if max_value >= 2: # There are some primes 6 # Initialize the list (incl. 0) 7 f = [True for i in range(max_value+1)] 8 # Get rid of the known non-primes 9 f[0] = f[1] = False 10 # Run the sieve 11 for i in range(2, len(f)): 12 if f[i]: # i is still a candidate 1 # mark its multiples as not prime 14 for j in range(2*i, len(f), i): 15 f[j] = False 16 # Find the primes and put them in a list 17 primes = [i for i in range(len(f)) if f[i]] 18 return primes 19 else: # max_value < 2 20 # no primes, return empty list 21 return list() 5 """Find primes up to the max_value 6 using the Sieve of Eratosthenes. 7 """ 8 if max_value >= 2: # There are some primes 9 # Initialize the list (incl. 0) 10 candidates = [ 11 PRIME for i in range(max_value+1)] 12 # Get rid of the known non-primes 1 candidates[0] = candidates[1] = NONPRIME 14 # Run the sieve 15 for number in range(2, len(candidates)): 16 if candidates[number] == PRIME: 17 # mark its multiples as not prime 18 for multiple in range( 19 2*number, len(candidates), number): 20 candidates[multiple] = NONPRIME 21 # Find the primes and put them in a list 22 primes = [i for i in range(len(candidates)) 2 if candidates[i] == PRIME] 24 return primes 25 else: # max_value < 2 26 # no primes, return empty list 27 return list() Další smyslupná jména budou následovat!!! P. Pošík c 2016 B4BRPH: Řešení problémů a hry 11 / 22 5

Komentáře Čistý kód komentáře (skoro) nepotřebuje! Komentáře kompenzují naše selhání vyjádřit se v prog. jazyce. Porovnej: 1 # Check whether point lies inside the unit circle 2 if point[0]**2 + point[1]**2 <= 1: versus 1 if is_inside_unit_circle(point): Komentáře lžou! Ne vždy a ne záměrně, ale až příliš často! Nepřesné komentáře jsou horší než žádné komentáře! Komentáře nenapraví špatný kód! Dobré komentáře: (do)vysvětlení, (do)upřesnění zdůraznění, varování před následky TODOs Špatné komentáře: staré (už neplatné), bezvýznamné, nevhodné, redundantní, nebo zavádějící komentáře komentáře z povinnosti zakomentovaný kód nelokální nebo nadbytečné informace P. Pošík c 2016 B4BRPH: Řešení problémů a hry 12 / 22 Eratostenovo síto: komentáře 1 # This function generates prime numbers up to 2 # a user specified maximum. The algorithm # used is the Sieve of Eratosthenes 4 # 5 # Eratosthenes of Cyrene, b. c. 276 BC, 6 # Cyrene, Libya -- d. c. 194 BC, Alexandria. 7 # The first man to calculate the circumference 8 # of the Earth. Also known for working on 9 # calendars with leap years and ran 10 # the library at Alexandria. 11 # 12 # The algorithm is quite simple. 1 # Given an array of integers starting at 2, 14 # cross out all multiples of 2. 15 # Find the next uncrossed integer, 16 # and cross out all of its multiples. 17 # Repeat until you have passed 18 # the maximum value. 19 # 20 # @author hugo 21 # @version 1 1 # This function generates prime numbers up to 2 # a user specified maximum. The algorithm # used is the Sieve of Eratosthenes. 4 # Given an array of integers starting at 2, 5 # cross out all multiples of 2. 6 # Find the next uncrossed integer, 7 # and cross out all of its multiples. 8 # Repeat until you have passed 9 # the maximum value. 10 # 11 # @author hugo 12 # @version 1 Za chvíli se zbavíme dalších komentářů! P. Pošík c 2016 B4BRPH: Řešení problémů a hry 1 / 22 6

Funkce a metody Funkce by měly být krátké! (A ještě kratší!) Funkce by měla dělat právě 1 věc a měla by ji dělat dobře. (A bez vedlejších efektů.) Funkce dlouhé méně než 5 řádků většinou dělají právě 1 věc, mohou mít přesné a výstižné jméno, nemohou obsahovat vnořené příkazy if, for,..., a bloky uvnitř příkazů if, for,... jsou pouze 1-2 řádky dlouhé. Krátké funkce umožňují testovat dílčí části algoritmu! Sekce uvnitř funkcí/metod: Jasná indikace toho, že funkce/metoda nedělá jen 1 věc a měla by být rozdělena. Parametry funkcí/metod: Udržujte jejich počet malý! 0, 1, 2, výjimečně. Vytvořte jméno tak, aby evokovalo pořadí argumentů. Boolovské argumenty funkcí často značí, že funkce nedělá 1 věc! Rozdělte ji. Při volání používejte častěji keyword arguments! Porovnejte: st("obama", 20, False, True) search_twitter("obama", 20, False, True) search_twitter("obama", numtweets=20, retweets=false, unicode=true) P. Pošík c 2016 B4BRPH: Řešení problémů a hry 14 / 22 Eratostenovo síto: funkce 5 """Find primes up to the max_value 6 using the Sieve of Eratosthenes. 7 """ 8 if max_value >= 2: # There are some primes 9 # Initialize the list (incl. 0) 10 candidates = [ 11 PRIME for i in range(max_value+1)] 12 # Get rid of the known non-primes 1 candidates[0] = candidates[1] = NONPRIME 14 # Run the sieve 15 for number in range(2, len(candidates)): 16 if candidates[number] == PRIME: 17 # mark its multiples as not prime 18 for multiple in range( 19 2*number, len(candidates), number): 20 candidates[multiple] = NONPRIME 21 # Find the primes and put them in a list 22 primes = [i for i in range(len(candidates)) 2 if candidates[i] == PRIME] 24 return primes 25 else: # max_value < 2 26 # no primes, return empty list 27 return list() 5 """Find primes up to the max_value 6 using the Sieve of Eratosthenes. 7 """ 8 if max_value < 2: 9 return [] 10 else: 11 candidates = init_integers_up_to(max_value) 12 mark_non_primes(candidates) 1 return collect_remaining(candidates) 14 15 def init_integers_up_to(max_value): 16 return [PRIME for i in range(max_value+1)] 17 18 def mark_non_primes(candidates): 19 # Mark 0 and 1, they are not primes. 20 candidates[0] = candidates[1] = NONPRIME 21 for number in range(2, len(candidates)): 22 if candidates[number] == PRIME: 2 mark_multiples_of(number, candidates) 24 25 def mark_multiples_of(number, candidates): 26 for multiple in range( 27 2*number, len(candidates), number): 28 candidates[multiple] = NONPRIME 29 0 def collect_remaining(candidates): 1 primes = [i for i in range(len(candidates)) 2 if candidates[i] == PRIME] return primes P. Pošík c 2016 B4BRPH: Řešení problémů a hry 15 / 22 7

Eratostenovo síto: pomocná třída? 5 """Find primes up to the max_value 6 using the Sieve of Eratosthenes. 7 """ 8 if max_value < 2: 9 return [] 10 else: 11 candidates = init_integers_up_to(max_value) 12 mark_non_primes(candidates) 1 return collect_remaining(candidates) 14 15 def init_integers_up_to(max_value): 16 return [PRIME for i in range(max_value+1)] 17 18 def mark_non_primes(candidates): 19 # Mark 0 and 1, they are not primes. 20 candidates[0] = candidates[1] = NONPRIME 21 for number in range(2, len(candidates)): 22 if candidates[number] == PRIME: 2 mark_multiples_of(number, candidates) 24 25 def mark_multiples_of(number, candidates): 26 for multiple in range( 27 2*number, len(candidates), number): 28 candidates[multiple] = NONPRIME 29 0 def collect_remaining(candidates): 1 primes = [i for i in range(len(candidates)) 2 if candidates[i] == PRIME] return primes 5 """Return a list of primes up to the max_value.""" 6 if max_value < 2: return [] 7 candidates = CandidateNumbers(max_value) 8 candidates.checkout_multiples() 9 return candidates.collect_remaining() 10 11 class CandidateNumbers: 12 """List of boolean values for use in the Sieve of Eratosthenes. 1 Shall be used with the generate_primes_up_to function. 14 """ 15 def init (self, max_value): 16 self.max = max_value + 1 17 self.candidates = [PRIME for i in range(self.max)] 18 self.candidates[0] = self.candidates[1] = NONPRIME 19 20 def checkout_multiples(self): 21 """Mark multiples of all prime numbers as not prime.""" 22 for number in range(2, int(self.max**0.5)+1): 2 if self.candidates[number] == PRIME: 24 self.checkout_multiples_of(number) 25 26 def checkout_multiples_of(self, number): 27 """Mark multiples of number as not prime.""" 28 for multiple in range(2*number, self.max, number): 29 self.candidates[multiple] = NONPRIME 0 1 def collect_remaining(self): 2 """Return a list of remaining candidates, they are prime.""" return [i for i in range(self.max) 4 if self.candidates[i] == PRIME] P. Pošík c 2016 B4BRPH: Řešení problémů a hry 16 / 22 Příklad Podle přednášky Raymond Hettinger: Beyond PEP 8 Best Practices for Beautiful Intelligible Code. PyCon 201517 / 22 Původní kód 1 import jnettool.tools.elements.networkelement, \ 2 jnettool.tools.routing, \ jnettool.tools.routeinspector 4 5 ne=jnettool.tools.elements.networkelement( 171.0.2.45 ) 6 try: 7 routing_table=ne.getroutingtable() # fetch table 8 9 except jnettool.tools.elements.missingvar: 10 # Record table fault 11 logging.exception( No routing table found ) 12 # Undo partial changes 1 ne.cleanup( rollback ) 14 15 else: 16 num_routes=routing_table.getsize() # determine table size 17 for RToffset in range( num_routes ): 18 route=routing_table.getroutebyindex( RToffset ) 19 name=route.getname() # route name 20 ipaddr=route.getipaddr() # ip address 21 print( {:15s} -> {:s}.format(name, ipaddr)) # format nicely 22 finally: 2 ne.cleanup( commit ) # lockin changes 24 ne.disconnect() Vyhovuje tento kód doporučením PEP 8? P. Pošík c 2016 B4BRPH: Řešení problémů a hry 18 / 22 8

Původní kód - podle PEP 8 1 import jnettool.tools.elements.networkelement 2 import jnettool.tools.routing import jnettool.tools.routeinspector 4 5 6 ne = jnettool.tools.elements.networkelement( 171.0.2.45 ) 7 8 try: 9 routing_table = ne.getroutingtable() 10 except jnettool.tools.elements.missingvar: 11 logging.exception( No routing table found ) 12 ne.cleanup( rollback ) 1 else: 14 num_routes = routing_table.getsize() 15 for RToffset in range(num_routes): 16 route = routing_table.getroutebyindex(rtoffset) 17 name = route.getname() 18 ipaddr = route.getipaddr() 19 print( {:15s} -> {:s}.format(name, ipaddr)) 20 finally: 21 ne.cleanup( commit ) 22 ne.disconnect() Je toto čistý kód? Co ten kód vlastně dělá? 1. Importuje potřebné věci z knihovny pro práci se sít ovými prvky. 2. Připojuje se k sít ovému zařízení (routeru).. Pokouší se stáhnout směrovací tabulku. 4. Pokud tabulka chybí, zaznamená chybu a uklidí po sobě a skončí. (Pokud byste neuklidili, mohlo byto router zanechat ve stavu, kdy se k němu nelze připojit.) 5. Zjistí velikost tabulky. 6. Následně iteruje přes indexy ve směrovací tabulce. 7. Najde směrovací pravidlo podle indexu. 8. Zjistí název pravidla, IP adresu a vytiskne je. 9. Nakonec uloží všechny změny a odpojí se od směrovače. Čeho chce programátor tímto kódem dosáhnout? Je to čistý kód? Nehezky kombinuje ošetření chyb s vlastní logikou. Není zřejmé, co kód vlastně dělá. P. Pošík c 2016 B4BRPH: Řešení problémů a hry 19 / 22 Lepší kód Jak to udělat lépe? 1 from nettools import NetworkElement 2 with NetworkElement( 171.0.2.45 ) as ne: 4 for route in ne.routing_table: 5 print( {:15s} -> {:s}.format(route.name, route.ipaddr)) Krátký, přehledný kód. Jasně sděluje, co je jeho hlavním účelem. Má jedinou vadu. Nefunguje. (Zatím.) Aby kód fungoval, musíme vytvořit nový modul nettools, který bude překládat náš krásný kód na volání původní knihovny jnettools. To není zcela triviální a my to ještě neumíme. Nicméně Python to umožňuje a podporuje. Modul nettools schovává detaily ošetření chyb, atd. Váš hlavní kód se může soustředit na logiku aplikace. Je to nezanedbatelná práce navíc. Ale uděláte ji jedinkrát, a v budoucnu z toho budete profitovat vy i vaši spolupracovníci. P. Pošík c 2016 B4BRPH: Řešení problémů a hry 20 / 22 9

Modulnettools Pro pokročilejší programátory, které zajímá, jak se takový modul dá udělat: 1 import jnettool.tools.elements.networkelement 2 import jnettool.tools.routing 4 class NetworkElementError(Exception): 5 pass 6 7 class NetworkElement: 8 9 def init (self, ipaddr): 10 self.ipaddr = ipaddr 11 self.oldne = jnettool.tools.elements.networkelement(ipaddr) 12 1 @property 14 def routing_table(self): 15 try: 16 return RoutingTable(self.oldne.getRoutingTable()) 17 except jnettool.tools.elements.missingvar: 18 raise NetworkElementError( No routing table found ) 19 20 def enter (self): 21 return self 22 2 def exit (self, exctype, excinst, exctb): 24 if exctype == NetworkElementError: 25 logging.exception( No routing table found ) 26 self.oldne.cleanup( rollback ) 27 else: 28 self.oldne.cleanup( commit ) 29 self.oldne.disconnect() 0 1 def repr (self): 2 return {:s}({:s}).format(self. class.name, self.ipaddr) 4 class RoutingTable: 5 6 def init (self, oldrt): 7 self.oldrt = oldrt 8 9 def len (self): 40 return self.oldrt.getsize() 41 42 def getitem (self, index): 4 if index >= len(self): 44 raise IndexError 45 return Route( 46 self.oldrt.getroutebyindex(index)) 47 48 49 class Route: 50 51 def init (self, old_route): 52 self.old_route = old_route 5 54 @property 55 def name(self): 56 return self.old_route.getname() 57 58 @property 59 def ipaddr(self): 60 return self.old_route.getipaddr() P. Pošík c 2016 B4BRPH: Řešení problémů a hry 21 / 22 Závěr Čistý kód je subjektivní pojem, přesto by se o něj měl každý programátor snažit. Čistý kód by měl být především čitelný (skoro jako v přirozeném jazyce). 80 % čistého kódu jsou správně zvolená jména! Vhodná jména lze volit, jsou-li funkce/metody dostatečně krátké! Opakují-li se ve vašem programu stejné nebo podobné kusy kódu, prakticky vždy je možné takový kód definovat jako samostatnou funkci/metodu. P. Pošík c 2016 B4BRPH: Řešení problémů a hry 22 / 22 10