{ "cells": [ { "cell_type": "markdown", "id": "divine-arthur", "metadata": {}, "source": [ "# Code kommentieren\n", "\n", "<br/>\n", "<br/>\n", "\n", "Dieses Notebook finden Sie hier: https://scm.cms.hu-berlin.de/ibi/python/-/blob/master/programmierspass/Kommentare.ipynb\n", "\n", "<br/>\n", "\n", "\n", "\n", "Dieses Notebook ist als freies Werk unter der Lizenz [Creative Commons Attribution-NonCommercial 3.0 Unported](http://creativecommons.org/licenses/by-nc/3.0/) verfügbar. Sie dürfen die Inhalte kopieren, verteilen und verändern, solange Sie die Urheber nennen und sie nicht für kommerzielle Zwecke nutzen." ] }, { "cell_type": "markdown", "id": "optimum-command", "metadata": {}, "source": [ "## Kommentare: was, wie, warum?" ] }, { "cell_type": "markdown", "id": "scientific-convertible", "metadata": {}, "source": [ "### Was?\n", "\n", "- Erklärung oder Anmerkung im Quellcode\n", "- unterstützen Verständlichkeit für Menschen\n", "- Compiler/Interpreter ignorieren diese i.d.R.\n", "\n", "```python\n", "#\n", "# traverses a directory and collects title names\n", "#\n", "def traverse(directory, titles):\n", " ...\n", "```" ] }, { "cell_type": "markdown", "id": "competitive-emission", "metadata": {}, "source": [ "### Wie? → (Python-)Syntax\n", "\n", "#### Zeilenkommentare\n", "\n", "```python\n", "# am Zeilenanfang\n", "\n", "print(\"Hello World!\") # am Ende einer Zeile\n", "```\n", "\n", "#### Blockkommentare\n", "\n", "```python\n", "def dothis():\n", " \"\"\"Als Beschreibung einer Funktion.\"\"\"\n", " pass\n", "```" ] }, { "cell_type": "markdown", "id": "affiliated-consumption", "metadata": {}, "source": [ "### Warum Code kommentieren?\n", "\n", "> Good code is its own best documentation. ([Steve McConnell](http://en.wikipedia.org/wiki/Steve_McConnell))\n", "\n", "> Code is far better describing what code does than English, so just write clear code. ([Mike Grouchy](https://mikegrouchy.com/blog/yes-your-code-does-need-comments))\n", "\n", "- viele widersprüchliche Meinungen, z.B.\n", " - möglichst selbsterklärender Code (\"self-documenting\") mit wenigen Kommentaren\n", " - ausführliche Kommentare und Erklärungen\n", "- wichtig: \n", " - Kommentare müssen korrekt sein und zum Code passen\n", " - überflüssige oder nicht hilfreiche Kommentare vermeiden\n", " - Zielgruppe beachten!" ] }, { "cell_type": "markdown", "id": "vulnerable-congress", "metadata": {}, "source": [ "```java\n", "String s = \"Wikipedia\"; /* Assigns the value \"Wikipedia\" to the variable s. */\n", "```\n", "→ als Einführungstext für Anfänger*innen ok, sonst überflüssig" ] }, { "cell_type": "markdown", "id": "competitive-binding", "metadata": {}, "source": [ "## Zweck von Kommentaren" ] }, { "cell_type": "markdown", "id": "laden-dependence", "metadata": {}, "source": [ "### Code planen und prüfen" ] }, { "cell_type": "code", "execution_count": null, "id": "ancient-indicator", "metadata": {}, "outputs": [], "source": [ "# alle Einträge rückwärts (chronologisch!) durchlaufen\n", "for eintrag in reversed(logbuch):\n", " # Eintrag verarbeiten\n", " update(eintrag)" ] }, { "cell_type": "markdown", "id": "insured-bronze", "metadata": {}, "source": [ "- vor dem Programmieren in einer Art Pseudocode den zu schreibenden Code skizzieren\n", "- sollte den Sinn des Codes beschreiben, nicht den Code selbst\n", "- ermöglicht Begutachtung/Prüfung des fertigen Codes → erfüllt dieser seine Aufgabe?" ] }, { "cell_type": "markdown", "id": "roman-astrology", "metadata": {}, "source": [ "## Code beschreiben\n", "\n", "> Don't document bad code – rewrite it. ([The Elements of Programming Style](https://en.wikipedia.org/wiki/The_Elements_of_Programming_Style_(book)), Kernighan & Plauger)\n", "\n", "> Good comments don't repeat the code or explain it. They clarify its intent. Comments should explain, at a higher level of abstraction than the code, what you're trying to do. ([Code Complete](https://en.wikipedia.org/wiki/Code_Complete), McConnell)" ] }, { "cell_type": "markdown", "id": "deluxe-replica", "metadata": {}, "source": [ "```python\n", "\"status\" : d[\"status\"] # unused but required by standard\n", "```" ] }, { "cell_type": "code", "execution_count": null, "id": "practical-appointment", "metadata": {}, "outputs": [], "source": [ "# Wir benötigen eine stabile Sortierung. Geschwindigkeit spielt keine Rolle.\n", "insertion_sort(liste) " ] }, { "cell_type": "markdown", "id": "moderate-forwarding", "metadata": {}, "source": [ "- Code zusammenfassen oder Absicht erklären\n", "- NICHT: Code in natürlicher Sprache wiederholen\n", "- auch: (Ursache für) Besonderheiten erklären\n", "- auch: Algorithmus beschreiben " ] }, { "cell_type": "markdown", "id": "black-constraint", "metadata": {}, "source": [ "## Einbettung von Ressourcen\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "id": "arbitrary-baptist", "metadata": {}, "outputs": [], "source": [ "# Graph:\n", "#\n", "# 5\n", "# / \\\n", "# 3---4\n", "# |\\ /|\n", "# | X |\n", "# |/ \\|\n", "# 1---2\n", "# \n", "# Adjazenzliste:\n", "nikolaus = {\n", " 1: [2, 3, 4],\n", " 2: [1, 3, 4],\n", " 3: [1, 2, 4, 5],\n", " 4: [1, 2, 3, 5],\n", " 5: [3, 4]\n", "}" ] }, { "cell_type": "markdown", "id": "chronic-perception", "metadata": {}, "source": [ "- Diagramme, Flussdiagramme, Tabellen, etc." ] }, { "cell_type": "markdown", "id": "binding-folder", "metadata": {}, "source": [ "## Metadaten" ] }, { "cell_type": "code", "execution_count": null, "id": "iraqi-coating", "metadata": {}, "outputs": [], "source": [ "#\n", "# Process (extract, filter, merge) Vossantos in an org mode file.\n", "#\n", "# Usage: Without any arguments, extracts all Vossanto canidates from\n", "# the given org file.\n", "#\n", "# Author: rja\n", "#\n", "# Changes:\n", "# 2019-12-18 (rja)\n", "# - added field sourceImageLicense\n", "# 2019-12-16 (rja)\n", "# - added option \"--images\" to enrich URLs for Wikipedia Commons images\n", "# ..." ] }, { "cell_type": "markdown", "id": "roman-mason", "metadata": {}, "source": [ "- Namen der Autor*innen, Versionshinweise, Lizenzangaben, Link zur Dokumentation, etc.\n", "- Hinweise zur Nutzung, zu Fehlern/Verbesserungsmöglichkeiten, zum Melden von Fehlern, etc." ] }, { "cell_type": "markdown", "id": "graduate-highland", "metadata": {}, "source": [ "## Debugging" ] }, { "cell_type": "code", "execution_count": null, "id": "pleased-filling", "metadata": {}, "outputs": [], "source": [ "def get_matching_item(bibentry, items):\n", " # heuristic: rely on Crossref's ranking and take the first item\n", " item = items[0]\n", " # heuristic: do (almost) exact string matching on the title (only)\n", " if item.get(\"title\")[0].casefold() == bibentry[\"title\"].casefold():\n", " return item\n", " # debug output\n", " # print(bibentry[\"ID\"], bibentry[\"title\"])\n", " # print(\" best Crossref match:\", item.get(\"title\"), item.get(\"DOI\"))\n", " return None" ] }, { "cell_type": "markdown", "id": "heavy-estate", "metadata": {}, "source": [ "- auskommentierter Code wird nicht ausgeführt\n", "- Fehlersuche; \"alten\" oder alternativen Code deaktivieren" ] }, { "cell_type": "markdown", "id": "metropolitan-horizontal", "metadata": {}, "source": [ "## Automatische Erzeugung von Dokumentation\n", "\n", "Quelle: https://scikit-learn.org/stable/modules/generated/sklearn.metrics.roc_curve.html" ] }, { "cell_type": "code", "execution_count": null, "id": "framed-stomach", "metadata": {}, "outputs": [], "source": [ "def roc_curve(y_true, y_score, *, pos_label=None, sample_weight=None,\n", " drop_intermediate=True):\n", " \"\"\"Compute Receiver operating characteristic (ROC)\n", "\n", " Note: this implementation is restricted to the binary classification task.\n", "\n", " Read more in the :ref:`User Guide <roc_metrics>`.\n", "\n", " Parameters\n", " ----------\n", "\n", " y_true : array, shape = [n_samples]\n", " True binary labels. If labels are not either {-1, 1} or {0, 1}, then\n", " pos_label should be explicitly given.\n", "\n", " y_score : array, shape = [n_samples]\n", " Target scores, can either be probability estimates of the positive\n", " class, confidence values, or non-thresholded measure of decisions\n", " (as returned by \"decision_function\" on some classifiers).\n", "\n", " pos_label : int or str, default=None\n", " The label of the positive class.\n", " When ``pos_label=None``, if y_true is in {-1, 1} or {0, 1},\n", " ``pos_label`` is set to 1, otherwise an error will be raised.\n", "\n", " sample_weight : array-like of shape (n_samples,), default=None\n", " Sample weights.\n", "\n", " drop_intermediate : boolean, optional (default=True)\n", " Whether to drop some suboptimal thresholds which would not appear\n", " on a plotted ROC curve. This is useful in order to create lighter\n", " ROC curves.\n", "\n", " .. versionadded:: 0.17\n", " parameter *drop_intermediate*.\n", "\n", " Returns\n", " -------\n", " fpr : array, shape = [>2]\n", " Increasing false positive rates such that element i is the false\n", " positive rate of predictions with score >= thresholds[i].\n", "\n", " tpr : array, shape = [>2]\n", " Increasing true positive rates such that element i is the true\n", " positive rate of predictions with score >= thresholds[i].\n", "\n", " thresholds : array, shape = [n_thresholds]\n", " Decreasing thresholds on the decision function used to compute\n", " fpr and tpr. `thresholds[0]` represents no instances being predicted\n", " and is arbitrarily set to `max(y_score) + 1`.\n", "\n", " See also\n", " --------\n", " roc_auc_score : Compute the area under the ROC curve\n", "\n", " Notes\n", " -----\n", " Since the thresholds are sorted from low to high values, they\n", " are reversed upon returning them to ensure they correspond to both ``fpr``\n", " and ``tpr``, which are sorted in reversed order during their calculation.\n", "\n", " References\n", " ----------\n", " .. [1] `Wikipedia entry for the Receiver operating characteristic\n", " <https://en.wikipedia.org/wiki/Receiver_operating_characteristic>`_\n", "\n", " .. [2] Fawcett T. An introduction to ROC analysis[J]. Pattern Recognition\n", " Letters, 2006, 27(8):861-874.\n", "\n", " Examples\n", " --------\n", " >>> import numpy as np\n", " >>> from sklearn import metrics\n", " >>> y = np.array([1, 1, 2, 2])\n", " >>> scores = np.array([0.1, 0.4, 0.35, 0.8])\n", " >>> fpr, tpr, thresholds = metrics.roc_curve(y, scores, pos_label=2)\n", " >>> fpr\n", " array([0. , 0. , 0.5, 0.5, 1. ])\n", " >>> tpr\n", " array([0. , 0.5, 0.5, 1. , 1. ])\n", " >>> thresholds\n", " array([1.8 , 0.8 , 0.4 , 0.35, 0.1 ])\n", "\n", " \"\"\"\n" ] }, { "cell_type": "markdown", "id": "tested-attendance", "metadata": {}, "source": [ "## Anweisungen für bestimmte Programme" ] }, { "cell_type": "code", "execution_count": null, "id": "honey-python", "metadata": {}, "outputs": [], "source": [ "#!/usr/bin/env python3\n", "# -*- coding: UTF-8 -*-\n", "# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4\n", "\n", "print(\"Testing\")" ] }, { "cell_type": "markdown", "id": "revised-potato", "metadata": {}, "source": [ "- \"Shebang\" (#!) → gibt den zu verwendenden Interpreter an\n", "- \"Magic comments\", z.B. zur verwendeten Codierung\n", "- ... oder zur Konfiguration des Editors" ] }, { "cell_type": "markdown", "id": "modern-nurse", "metadata": {}, "source": [ "## Stressabbau :-)" ] }, { "cell_type": "markdown", "id": "thick-hamburg", "metadata": {}, "source": [ "```c\n", "/*\n", " * Some dipshit decided to store some other bit of information\n", " * in the high byte of the file length. Truncate size in case\n", " * this CDROM was mounted with the cruft option.\n", " */\n", "```\n", "Quelle: https://github.com/torvalds/linux/blob/master/fs/isofs/inode.c#L1396\n", "\n", "→ [Linux Swear Count](http://www.vidarholen.net/contents/wordcount/)" ] }, { "cell_type": "markdown", "id": "pressing-rings", "metadata": {}, "source": [ "```c\n", "// \n", "// Dear maintainer:\n", "// \n", "// Once you are done trying to 'optimize' this routine,\n", "// and have realized what a terrible mistake that was,\n", "// please increment the following counter as a warning\n", "// to the next guy:\n", "// \n", "// total_hours_wasted_here = 42\n", "// \n", "```\n", "Quelle: https://stackoverflow.com/questions/184618/what-is-the-best-comment-in-source-code-you-have-ever-encountered " ] }, { "cell_type": "markdown", "id": "marked-genome", "metadata": {}, "source": [ "## Beispiele\n", "\n", "- https://borgelt.net/bin/apriori (→ apriori.c)\n", "- https://github.com/zedshaw/lamson/blob/master/lamson/server.py#L55\n", "- https://github.com/weltliteratur/vossanto/blob/master/org.py\n", "- https://scm.cms.hu-berlin.de/ibi/notebooks/-/blob/master/Mondrian.ipynb" ] }, { "cell_type": "markdown", "id": "directed-lithuania", "metadata": {}, "source": [ "## *Anleitung zum Unglücklichsein* oder *How to write unmaintainable code*\n", "\n", "> Any fool can tell the truth, but it requires a man of some sense to know how to lie well. ([Samuel Butler](https://en.wikipedia.org/wiki/Samuel_Butler_%28novelist%29) (1835 - 1902))\n", "\n", "> Incorrect documentation is often worse than no documentation. ([Bertrand Meyer](https://en.wikipedia.org/wiki/Bertrand_Meyer))\n", "\n", "Since the computer ignores comments and documentation, you can lie outrageously and do everything in your power to befuddle the poor maintenance programmer.\n", "\n", "Quelle: Roedy Green, [How To Write Unmaintainable Code](https://web.archive.org/web/20120306115925/http://freeworld.thc.org/root/phun/unmaintain.html) ([Originalseite](https://www.mindprod.com/jgloss/unmain.html))" ] }, { "cell_type": "markdown", "id": "unusual-excellence", "metadata": {}, "source": [ "### Lie in the comments\n", "\n", "You don't have to actively lie, just fail to keep comments as up to date with the code." ] }, { "cell_type": "code", "execution_count": null, "id": "normal-management", "metadata": {}, "outputs": [], "source": [ "# remove control characters\n", "def rm_ctrl(text):\n", " return re.sub(r\"[\\n\\t\\r]+\", \" \", text).strip()" ] }, { "cell_type": "markdown", "id": "attempted-mount", "metadata": {}, "source": [ "### Document the obvious\n", "\n", "Pepper the code with comments like `/* add 1 to i */` however, never document wooly stuff like the overall purpose of the package or method." ] }, { "cell_type": "code", "execution_count": null, "id": "choice-dialogue", "metadata": {}, "outputs": [], "source": [ "def einefunktion(a, b):\n", " # a² zu b² addieren\n", " c = a**2 + b**2\n", " # die Wurzel des Ergebnisses zurückgeben\n", " return math.sqrt(c)" ] }, { "cell_type": "code", "execution_count": null, "id": "alternate-resolution", "metadata": {}, "outputs": [], "source": [ "def einefunktion(a, b):\n", " # Für zwei gegebene Seitenlängen a und b die dritte Seitenlänge\n", " # c eines rechtwinkligen Dreiecks mit Hilfe des Satzes des \n", " # Pythagoras (a² + b² = c²) berechnen.\n", " c = a**2 + b**2\n", " return math.sqrt(c)" ] }, { "cell_type": "markdown", "id": "ahead-sheep", "metadata": {}, "source": [ "### Document How Not Why\n", "\n", "Document only the details of what a program does, not what it is attempting to accomplish. That way, if there is a bug, the fixer will have no clue what the code should be doing." ] }, { "cell_type": "code", "execution_count": null, "id": "juvenile-thanks", "metadata": {}, "outputs": [], "source": [ "def read_dict(lines):\n", " d = dict()\n", " for line in lines:\n", " if not line.startswith('#'):\n", " # nur Zeilen ohne # am Anfang verarbeiten\n", " key, val = line.strip().split('\\t', 1)\n", " d[key] = val\n", " return d" ] }, { "cell_type": "markdown", "id": "still-marketplace", "metadata": {}, "source": [ "### Avoid Documenting the \"Obvious\"\n", "\n", "If, for example, you were writing an airline reservation system, make sure there are at least 25 places in the code that need to be modified if you were to add another airline. Never document where they are. People who come after you have no business modifying your code without thoroughly understanding every line of it." ] }, { "cell_type": "code", "execution_count": null, "id": "divided-basin", "metadata": {}, "outputs": [], "source": [ "sep = '\\t' # column separator\n", "\n", "def print_csv(parts):\n", " for part in parts:\n", " print(sep.join([part_to_string(part[p]) for p in part]))\n", "\n", "def read_dict(lines):\n", " d = dict()\n", " for line in lines:\n", " if not line.startswith('#'):\n", " key, val = line.strip().split('\\t', 1)\n", " d[key] = val\n", " return d" ] }, { "cell_type": "markdown", "id": "interracial-translator", "metadata": {}, "source": [ "### On the Proper Use Of Documentation Templates\n", "\n", "Consider function documentation prototypes used to allow automated documentation of the code. These prototypes should be copied from one function (or method or class) to another, but never fill in the fields. If for some reason you are forced to fill in the fields make sure that all parameters are named the same for all functions, and all cautions are the same but of course not related to the current function at all." ] }, { "cell_type": "markdown", "id": "selected-exclusive", "metadata": {}, "source": [ "```java\t\n", "/**\n", " * @param receiver\n", " * @param limit\n", " * @param offset\n", " * @param session\n", " *\n", " * @return a lists of posts of type R with the inbox content\n", " */\n", "public List<Post<R>> getPostsFromInbox(final String receiver, final int limit, final int offset, final DBSession session) {\n", " ... \n", "}\n", "\n", "/**\n", " * TODO: improve docs\n", " *\n", " * @param days\n", " * @param limit\n", " * @param offset\n", " * @param hashId\n", " * @param session\n", " *\n", " * @return list of posts\n", " */\n", "public List<Post<R>> getPostsPopular(final int days, final int limit, final int offset, final HashID hashId, final DBSession session) {\n", " ...\n", "}\n", "```" ] }, { "cell_type": "markdown", "id": "charged-conviction", "metadata": {}, "source": [ "### On the Proper Use of Design Documents\n", "\n", "When implementing a very complicated algorithm, use the classic software engineering principles of doing a sound design before beginning coding. Write an extremely detailed design document that describes each step in a very complicated algorithm. The more detailed this document is, the better.\n", "\n", "In fact, the design doc should break the algorithm down into a hierarchy of structured steps, described in a hierarchy of auto-numbered individual paragraphs in the document. Use headings at least 5 deep. Make sure that when you are done, you have broken the structure down so completely that there are over 500 such auto-numbered paragraphs. For example, one paragraph might be (this is a real example)\n", "\n", "> 1.2.4.6.3.13 - Display all impacts for activity where selected mitigations can apply (short pseudocode omitted).\n", "\n", "**then ...** (and this is the kicker) when you write the code, for each of these paragraphs you write a corresponding global function named:\n", "\n", "```python\n", "Act1_2_4_6_3_13() \n", "```\n", "\n", "Do not document these functions. After all, that's what the design document is for!\n", "\n", "Since the design doc is auto-numbered, it will be extremely difficult to keep it up to date with changes in the code (because the function names, of course, are static, not auto-numbered.) This isn't a problem for you because you will not try to keep the document up to date. In fact, do everything you can to destroy all traces of the document.\n", "\n", "Those who come after you should only be able to find one or two contradictory, early drafts of the design document hidden on some dusty shelving in the back room near the dead 286 computers." ] }, { "cell_type": "markdown", "id": "rolled-starter", "metadata": {}, "source": [ "### Units of Measure\n", "\n", "Never document the units of measure of any variable, input, output or parameter, e.g., feet, metres, cartons. This is not so important in bean counting, but it is very important in engineering work. As a corollary, never document the units of measure of any conversion constants, or how the values were derived. It is mild cheating, but very effective, to salt the code with some incorrect units of measure in the comments. If you are feeling particularly malicious, make up your **own** unit of measure; name it after yourself or some obscure person and never define it. If somebody challenges you, tell them you did so that you could use integer rather than floating point arithmetic." ] }, { "cell_type": "code", "execution_count": null, "id": "varying-communist", "metadata": {}, "outputs": [], "source": [ "def wurfdistanz(geschwindigkeit, winkel):\n", " return geschwindigkeit**2 / 9.81 * math.sin(2*winkel)" ] }, { "cell_type": "markdown", "id": "eligible-graduate", "metadata": {}, "source": [ "### Gotchas\n", "\n", "Never document gotchas in the code. If you suspect there may be a bug in a class, keep it to yourself. If you have ideas about how the code should be reorganised or rewritten, for heaven's sake, do not write them down. Remember the words of Thumper in the movie Bambi \"*If you can't say anything nice, don't say anything at all*\". What if the programmer who wrote that code saw your comments? What if the owner of the company saw them? What if a customer did? You could get yourself fired. An anonymous comment that says \"This needs to be fixed!\" can do wonders, especially if it's not clear what the comment refers to. Keep it vague, and nobody will feel personally criticised." ] }, { "cell_type": "code", "execution_count": null, "id": "muslim-universe", "metadata": {}, "outputs": [], "source": [ "print(key, \":\", value) # FIXME" ] }, { "cell_type": "code", "execution_count": null, "id": "consecutive-amendment", "metadata": {}, "outputs": [], "source": [ "print(key, \":\", value) # FIXME: ignore keys with empty values" ] }, { "cell_type": "markdown", "id": "incident-queue", "metadata": {}, "source": [ "### Documenting Variables\n", "Never put a comment on a variable declaration. Facts about how the variable is used, its bounds, its legal values, its implied/displayed number of decimal points, its units of measure, its display format, its data entry rules (e.g. total fill, must enter), when its value can be trusted etc. should be gleaned from the procedural code. If your boss forces you to write comments, lard method bodies with them, but never comment a variable declaration, not even a temporary!" ] }, { "cell_type": "markdown", "id": "funny-consortium", "metadata": {}, "source": [ "```c\n", "const char *name;\n", "int len;\n", "char c;\n", "unsigned long hash;\n", "```" ] }, { "cell_type": "markdown", "id": "popular-bracelet", "metadata": {}, "source": [ "### Disparage In the Comments\n", "\n", "Discourage any attempt to use external maintenance contractors by peppering your code with insulting references to other leading software companies, especial anyone who might be contracted to do the work, e.g.:\n", "```java\n", "/* The optimised inner loop.\n", " This stuff is too clever for the dullard at Software Services Inc., who would\n", " probably use 50 times as memory & time using the dumb routines in <math.h>.\n", "*/\n", "class clever_SSInc\n", "{\n", " ...\n", "} \n", "```\n", "\n", "If possible, put insulting stuff in syntactically significant parts of the code, as well as just the comments so that management will probably break the code if they try to sanitise it before sending it out for maintenance." ] }, { "cell_type": "markdown", "id": "human-thomson", "metadata": {}, "source": [ "### COMMENT AS IF IT WERE CØBØL ON PUNCH CARDS\n", "\n", "Always refuse to accept advances in the development environment arena, especially SCIDs. Disbelieve rumors that all function and variable declarations are never more than one click away and always assume that code developed in Visual Studio 6.0 will be maintained by someone using edlin or vi. Insist on Draconian commenting rules to bury the source code proper." ] }, { "cell_type": "markdown", "id": "unusual-dairy", "metadata": {}, "source": [ "### Monty Python Comments\n", "\n", "On a method called makeSnafucated insert only the JavaDoc `/* make snafucated */`. Never define what *snafucated* means **anywhere**. Only a fool does not already know, with complete certainty, what *snafucated* means. For classic examples of this technique, consult the Sun AWT JavaDOC.\n", "\n", "```java\n", "/* make snafucated */\n", "void makeSnafucated() {\n", " ...\n", "}\n", "```" ] }, { "cell_type": "markdown", "id": "robust-stability", "metadata": {}, "source": [ "## Aufgaben" ] }, { "cell_type": "markdown", "id": "protecting-cleaners", "metadata": {}, "source": [ "### Kommentare beschreiben\n", "\n", "Suchen Sie nach Quellcode auf Ihrem Rechner oder im Web und lesen Sie die Kommentare im Code.\n", "1. Welche *Arten von Kommentaren* können Sie finden?\n", "2. Was ist der *Zweck* der Kommentare?\n", "\n", "Suchen Sie so lange, bis Sie jeweils zwei Varianten gefunden haben." ] }, { "cell_type": "markdown", "id": "human-redhead", "metadata": {}, "source": [ "### Code selber kommentieren\n", "\n", "Fügen Sie Kommentare zu den folgenden Codebeispielen hinzu. Überlegen Sie sich für jeden Kommentar, \n", "- welchen *Zweck* Sie mit dem Kommentar erreichen wollen, \n", "- welche *Art* von Kommentar Sie verwenden wollen und \n", "- welche *Zielgruppe(n)* Sie damit ansprechen wollen. " ] }, { "cell_type": "code", "execution_count": null, "id": "peaceful-cruise", "metadata": {}, "outputs": [], "source": [ "def boxsay(s, h=\"-\", v=\"|\", c=\"+\"):\n", " print(c + (2+len(str(s)))*h + c)\n", " print(v, str(s), v)\n", " print(c + (2+len(str(s)))*h + c)\n", " \n", "boxsay(\"Hallo Welt!\")" ] }, { "cell_type": "code", "execution_count": null, "id": "global-tomato", "metadata": {}, "outputs": [], "source": [ "def equal_chars(v, w):\n", " m = []\n", " for i in range(min(len(v), len(w))):\n", " if v[i] == w[i]:\n", " m.append(v[i])\n", " else:\n", " m.append(\"_\")\n", " return m\n", "\n", "equal_chars(\"Magdeburg\", \"Hannover\")" ] }, { "cell_type": "code", "execution_count": null, "id": "breeding-comfort", "metadata": {}, "outputs": [], "source": [ "import urllib.request\n", "import re\n", "\n", "with urllib.request.urlopen(\"https://de.wikipedia.org/wiki/IP-Adresse\") as f:\n", " html = f.read().decode('utf8')\n", " \n", " for ip in sorted(re.findall(\"[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\", html)):\n", " print(ip)" ] }, { "cell_type": "code", "execution_count": null, "id": "lonely-tablet", "metadata": {}, "outputs": [], "source": [ "import json\n", "\n", "def chars_markdown(fname, celltype):\n", " with open(fname) as json_file:\n", " data = json.load(json_file)\n", " \n", " count = 0\n", " for cell in data['cells']:\n", " if cell['cell_type'] == celltype:\n", " for line in cell['source']:\n", " count += len(line.strip().replace(\" \", \"\"))\n", " return count\n", "\n", "chars_markdown(\"Kommentare.ipynb\", \"code\")" ] }, { "cell_type": "code", "execution_count": null, "id": "resident-color", "metadata": {}, "outputs": [], "source": [ "from urllib import request\n", "import json \n", "\n", "def get_dracor(corpus, play=None):\n", " url = \"https://dracor.org/api/corpora/\" + corpus\n", " if play is not None:\n", " url = url + \"/play/\" + play + \"/spoken-text\"\n", " with request.urlopen(url) as req:\n", " text = req.read().decode()\n", " if play is None:\n", " return json.loads(text)\n", " return text\n", " \n", "get_dracor(\"ger\")[\"description\"]" ] }, { "cell_type": "code", "execution_count": null, "id": "close-assessment", "metadata": {}, "outputs": [], "source": [ "from collections import Counter\n", "import re\n", "\n", "re_word = re.compile(\"\\W\")\n", "\n", "def count_terms(text):\n", " nouns = Counter()\n", " upper = Counter()\n", " tokens = text.split(' ')\n", " for i, term in enumerate(tokens):\n", " if len(term) > 0 and term[0].isupper():\n", " if i > 0 and len(tokens[i-1]) > 0 and tokens[i-1][-1] not in ['.', '?', '!', ':']:\n", " term = re_word.sub(\"\", term)\n", " nouns[term] += 1\n", " if term.isupper():\n", " term = re_word.sub(\"\", term)\n", " if len(term) > 1:\n", " upper[term] += 1\n", " return nouns, upper\n", "\n", "count_terms(\"Die Europäische Union hat Beobachterstatus in der G7, ist Mitglied in der G20 und vertritt ihre Mitgliedstaaten in der Welthandelsorganisation.\")" ] }, { "cell_type": "code", "execution_count": null, "id": "opposite-astrology", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "k = 50 # number of horizontal points\n", "n = 80 # number of vertical lines\n", "\n", "plt.rcParams['figure.figsize'] = (15, 15)\n", "plt.rcParams['figure.dpi'] = 140\n", "plt.style.use('dark_background')\n", "plt.axis('off')\n", "plt.xlim(-100, 200)\n", "plt.ylim(-60, 240)\n", "\n", "xs = np.linspace(0, 100, k)\n", "\n", "def sq(x, minx, maxx, miny, maxy, invert=False):\n", " x = (x - minx) / (maxx - minx)\n", " if invert:\n", " x = 1 - x\n", " if x < 0.5: # ascent\n", " fx = 2*x**2\n", " else: # descent\n", " fx = (1 - 2*(1-x)**2)\n", " return fx * (maxy - miny) + miny\n", "\n", "def f(x, left, right, width, height):\n", " if x < left or x > right: # left + right\n", " return np.abs(np.random.normal(0, 0.5))\n", " if x < left + width: # ascent\n", " return np.abs(np.random.normal(0, 1.0)) + sq(x, left, left + width, 0, height)\n", " if x > right - width: # descent\n", " return np.abs(np.random.normal(0, 1.0)) + sq(x, right - width, right, 0, height, True)\n", " else: # middle\n", " return np.random.exponential(2) + height\n", "\n", "for i in range(1, n+1):\n", " data = [f(x, 25, 75, 10, 5) + i*2 for x in xs]\n", " plt.plot(xs, data, color=\"white\", zorder=n-i, linewidth=1)\n", " plt.fill_between(xs, data, color=\"black\", zorder=n-i)\n", "\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "developed-figure", "metadata": {}, "source": [ "## Literatur\n", "\n", "- https://en.wikipedia.org/wiki/Comment_(computer_programming)\n", "- Keyes, Jessica (2003). Software Engineering Handbook. CRC Press. ISBN 978-0-8493-1479-7.\n", "- Roedy Green, [How To Write Unmaintainable Code](https://web.archive.org/web/20120306115925/http://freeworld.thc.org/root/phun/unmaintain.html) ([Originalseite](https://www.mindprod.com/jgloss/unmain.html))\n", "- https://mikegrouchy.com/blog/yes-your-code-does-need-comments\n", "- https://stackoverflow.com/questions/184618/what-is-the-best-comment-in-source-code-you-have-ever-encountered" ] } ], "metadata": { "language_info": { "name": "python", "pygments_lexer": "ipython3" } }, "nbformat": 4, "nbformat_minor": 5 }