{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "### Czysty kod" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Gorąco zachęcam do przeczytania książki: Czysty kod. Podręcznik dobrego programisty" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Co to znaczy \"czysty kod\"?\n", "\n", "Czysty kod to taki zapis kodu, który będzie czytelny/przyjazny dla innych osób (lub samego siebie przy powrocie do danego kodu po kilku miesiącach przerwy)\n", "\n", "Czysty kod powinien być:\n", "* poprawnie sformatowany (dla chętnych dokument PEP 8 opisujący formatowanie kodu w Pythonie https://peps.python.org/pep-0008/)\n", "* samoopisywalny - nazwy zmiennych/funkcji powinny opisywać, co dzieje się w danym fragmencie kodu\n", "* możliwie krótki i prosty (brak wielokrotnych zagnieżdżeń, wielu różnych wariantów w blokach if-elif-else itp.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**1. Nazwy:**\n", "\n", "* **Znaczące i opisowe:** Nazwy zmiennych, funkcji i klas powinny jasno wskazywać ich przeznaczenie (czyli definiować, z czym mamy doczynienia). Krótka nazwa to nie zawsze dobra nazwa! Przykłady:\n", " * `words` zamiast `w`\n", " * `number_of_ill_patients` jako liczba chorych pacjentów. Jeśli chcielibyśmy przetrzymywać listę/zbiór chorych pacjentów (obiektów posiadających informacje o pacjentach), wtedy możemy skorzystać ze zmiennej `ill_patients`.\n", " * `calculate_sum()` zamiast `calc()`\n", " * nazwy takie jak `x` czy `y` możemy wykorzystywać w takich zastosowaniach jak indeks podczas iterowania pętli\n", "* **Konwencja:** Używaj `snake_case` dla nazw zmiennych i funkcji (małe litery, podkreślenia). Klasy piszemy w `CamelCase` (duże litery na początku każdego słowa).\n", "* **Unikaj skrótów:** `unique_elements` zamiast `uni_elem`, wyjątek stanowią skróty, które są jednoznaczne, powszechnie przyjęte i rozumiane przez zdecydowaną większość osób mających styczność z kodem (np. number -> num, dataframe -> df, vocabulary -> vocab, character -> char).\n", "\n", "**2. Formatowanie:**\n", "\n", "* **Wcięcia:** Używaj 4 spacji na każde wcięcie.\n", "* **Puste linie:** Oddzielaj bloki kodu pustymi liniami dla lepszej czytelności (funkcje, klasy, oraz fragmenty kodu staniowące pewną logiczną spójność).\n", "* **Długość linii:** Staraj się, aby linie kodu nie były dłuższe niż 80 znaków.\n", "\n", "**3. Funkcje:**\n", "\n", "* **Jedno zadanie:** Każda funkcja powinna wykonywać tylko jedno, konkretne zadanie.\n", "* **Krótkie i zwięzłe:** Funkcje powinny być krótkie i łatwe do zrozumienia (tak samo ich nazwy).\n", "\n", "**4. Komentarze:**\n", "* **Podstawowa zasada:** W komentarzu umieszczaj informacje, których nie da się wyrazić w kodzie, a które są ważne. \n", "* **Unikaj nadmiaru komentarzy:** Zbyt wiele komentarzy może utrudnić czytanie kodu.\n", "\n", "**5. Moduły i pakiety:**\n", "\n", "* **Organizacja:** Dziel duży kod na mniejsze moduły i pakiety, aby ułatwić jego zarządzanie.\n", "* **Import:** Importuj tylko niezbędne moduły.\n", "\n", "**Narzędzia:**\n", "\n", "* **Linters:** Używaj linterów, takich jak `pylint` lub `flake8`, aby automatycznie sprawdzać styl i jakość kodu.\n", "* **Formatery:** Używaj formaterów kodu, takich jak `black` lub `autopep8`, aby automatycznie formatować kod zgodnie z ustalonymi konwencjami.\n", "\n", "**Pamiętaj:** Celem czystego kodu jest jego zrozumienie i utrzymanie. Inwestycja w czysty kod zaoszczędzi Ci (oraz Twoim współpracownikom) czasu i wysiłku w przyszłości." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Przykład nieczytelnego kodu" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open(\"file1.txt\", \"r\") as f:\n", " b = f.readlines()\n", " b = [x.strip() for x in b]\n", " b = set(b)\n", "with open(\"file2.txt\", \"r\") as f:\n", " a = f.readlines()\n", " a = [x.strip() for x in a]\n", " a = \" \".join(a)\n", "\n", "a = a.split()\n", "\n", "aa = []\n", "for a1 in a:\n", " aaa = \"\".join([c for c in a1 if c.isalpha()])\n", " aa.append(aaa)\n", "\n", "o = []\n", "for a2 in aa:\n", " if a2 not in b:\n", " o.append(a2)\n", " \n", "print(o)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Przykład wyżej po poprawie" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def remove_nonletters_chars(words):\n", " filtered_words = []\n", "\n", " for word in words:\n", " filtered_word = \"\".join([char for char in word if char.isalpha()])\n", " filtered_words.append(filtered_word)\n", " \n", " return filtered_words\n", "\n", "\n", "def get_out_of_vocab_words(text, vocab):\n", " words = text.split()\n", " words = remove_nonletters_chars(words)\n", " \n", " out_of_vocab_words = []\n", " for word in words:\n", " if word not in vocab:\n", " out_of_vocab_words.append(word)\n", " \n", " return out_of_vocab_words" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open(\"vocabulary.txt\", \"r\") as file:\n", " vocab = file.readlines()\n", " vocab = [x.strip() for x in vocab]\n", " vocab = set(vocab)\n", "\n", "with open(\"article.txt\", \"r\") as file:\n", " article = file.readlines()\n", " article = [x.strip() for x in article]\n", " article = \" \".join(article)\n", "\n", "out_of_vocab_words = get_out_of_vocab_words(article, vocab)\n", "print(out_of_vocab_words)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### W powyższym kodzie:\n", "* zmienne jednoznacznie wskazują \"czym\" są\n", "* nazwy funkcji opisują co w nich jest wykonywane\n", "* fragmenty kodu są właściwie oddzielone nowymi liniami\n", "* kod nie zawiera komentarzy, ponieważ strukturę działania programu dało się wyrazić poprzez nadanie właściwych nazw zmiennym oraz funkcjom" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "undefined.undefined.undefined" } }, "nbformat": 4, "nbformat_minor": 2 }