From 7d685c56ad720512ce1d34fbaa057c13b1259fd1 Mon Sep 17 00:00:00 2001 From: Jan Grewe Date: Fri, 13 Nov 2015 18:27:06 +0100 Subject: [PATCH 1/6] new programmingstyle chapter --- Makefile | 2 +- programmingstyle/lecture/Makefile | 31 +++++ .../lecture/beamercolorthemetuebingen.sty | 61 +++++++++ .../lecture/figures/program_organization.png | Bin 0 -> 48276 bytes .../lecture/figures/search_path.png | Bin 0 -> 63715 bytes .../lecture/programmingstyle-chapter.tex | 17 +++ programmingstyle/lecture/programmingstyle.tex | 129 ++++++++++++++++++ scientificcomputing-script.tex | 5 + 8 files changed, 244 insertions(+), 1 deletion(-) create mode 100644 programmingstyle/lecture/Makefile create mode 100644 programmingstyle/lecture/beamercolorthemetuebingen.sty create mode 100644 programmingstyle/lecture/figures/program_organization.png create mode 100644 programmingstyle/lecture/figures/search_path.png create mode 100644 programmingstyle/lecture/programmingstyle-chapter.tex create mode 100644 programmingstyle/lecture/programmingstyle.tex diff --git a/Makefile b/Makefile index 1fcb26f..2038f42 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ BASENAME=scientificcomputing-script -SUBDIRS=programming plotting statistics bootstrap regression likelihood pointprocesses designpattern +SUBDIRS=programming plotting programmingstyle statistics bootstrap regression likelihood pointprocesses designpattern SUBTEXS=$(foreach subd, $(SUBDIRS), $(subd)/lecture/$(subd).tex) pdf : chapters $(BASENAME).pdf diff --git a/programmingstyle/lecture/Makefile b/programmingstyle/lecture/Makefile new file mode 100644 index 0000000..ad1b36a --- /dev/null +++ b/programmingstyle/lecture/Makefile @@ -0,0 +1,31 @@ +BASENAME=programmingstyle + +#TEXFILES=programmingstyle.tex + +PYFILES=$(wildcard *.py) +PYPDFFILES=$(PYFILES:.py=.pdf) + +all : pdf + +# script: +pdf : $(BASENAME)-chapter.pdf + +$(BASENAME)-chapter.pdf : $(BASENAME)-chapter.tex $(BASENAME).tex $(PYPDFFILES) ../../header.tex + pdflatex -interaction=scrollmode $< | tee /dev/stderr | fgrep -q "Rerun to get cross-references right" && pdflatex -interaction=scrollmode $< || true + +$(PYPDFFILES) : %.pdf : %.py + python $< + +clean : + rm -f *~ + rm -f $(BASENAME).aux $(BASENAME).log + rm -f $(BASENAME)-chapter.aux $(BASENAME)-chapter.log $(BASENAME)-chapter.out + rm -f $(PYPDFFILES) $(GPTTEXFILES) + +cleanall : clean + rm -f $(BASENAME)-chapter.pdf + +watchpdf : + while true; do ! make -q pdf && make pdf; sleep 0.5; done + + diff --git a/programmingstyle/lecture/beamercolorthemetuebingen.sty b/programmingstyle/lecture/beamercolorthemetuebingen.sty new file mode 100644 index 0000000..c4a5da6 --- /dev/null +++ b/programmingstyle/lecture/beamercolorthemetuebingen.sty @@ -0,0 +1,61 @@ +% Copyright 2007 by Till Tantau +% +% This file may be distributed and/or modified +% +% 1. under the LaTeX Project Public License and/or +% 2. under the GNU Public License. +% +% See the file doc/licenses/LICENSE for more details. + +\usepackage{color} +\definecolor{karminrot}{RGB}{165,30,55} +\definecolor{gold}{RGB}{180,160,105} +\definecolor{anthrazit}{RGB}{50 ,65 ,75 } + +\mode + +\setbeamercolor*{normal text}{fg=anthrazit,bg=white} +\setbeamercolor*{alerted text}{fg=anthrazit} +\setbeamercolor*{example text}{fg=anthrazit} +\setbeamercolor*{structure}{fg=gold,bg=karminrot} + +\providecommand*{\beamer@bftext@only}{% + \relax + \ifmmode + \expandafter\beamer@bftext@warning + \else + \expandafter\bfseries + \fi +} +\providecommand*{\beamer@bftext@warning}{% + \ClassWarning{beamer} + {Cannot use bold for alerted text in math mode}% +} + +\setbeamerfont{alerted text}{series=\beamer@bftext@only} + +\setbeamercolor{palette primary}{fg=karminrot,bg=white} +\setbeamercolor{palette secondary}{fg=gold,bg=white} +\setbeamercolor{palette tertiary}{fg=anthrazit,bg=white} +\setbeamercolor{palette quaternary}{fg=black,bg=white} + +\setbeamercolor{sidebar}{bg=karminrot!100} + +\setbeamercolor{palette sidebar primary}{fg=karminrot} +\setbeamercolor{palette sidebar secondary}{fg=karminrot} +\setbeamercolor{palette sidebar tertiary}{fg=karminrot} +\setbeamercolor{palette sidebar quaternary}{fg=karminrot} + +\setbeamercolor{item projected}{fg=black,bg=black!20} + +\setbeamercolor*{block body}{} +\setbeamercolor*{block body alerted}{} +\setbeamercolor*{block body example}{} +\setbeamercolor*{block title}{parent=structure} +\setbeamercolor*{block title alerted}{parent=alerted text} +\setbeamercolor*{block title example}{parent=example text} + +\setbeamercolor*{titlelike}{parent=structure} + +\mode + diff --git a/programmingstyle/lecture/figures/program_organization.png b/programmingstyle/lecture/figures/program_organization.png new file mode 100644 index 0000000000000000000000000000000000000000..56a7a98fe70b05fab0338aae44b57c8933255461 GIT binary patch literal 48276 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 literal 0 HcmV?d00001 diff --git a/programmingstyle/lecture/programmingstyle-chapter.tex b/programmingstyle/lecture/programmingstyle-chapter.tex new file mode 100644 index 0000000..fffe3a4 --- /dev/null +++ b/programmingstyle/lecture/programmingstyle-chapter.tex @@ -0,0 +1,17 @@ +\documentclass[12pt]{report} + +\input{../../header} + +\lstset{inputpath=../code} + +\graphicspath{{figures/}} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{document} + +\include{programmingstyle} + +\end{document} + diff --git a/programmingstyle/lecture/programmingstyle.tex b/programmingstyle/lecture/programmingstyle.tex new file mode 100644 index 0000000..ca5e0bd --- /dev/null +++ b/programmingstyle/lecture/programmingstyle.tex @@ -0,0 +1,129 @@ +\chapter{\tr{Programming style}{Programmierstil}} + +Guter Programmierstil ist keine Frage des guten Geschmacks sondern des +Verst\"andnisses von Programmcode und ein Baustein in dem Bestreben +wissenschaftlichen Erkenntnisgewinn reproduzierbar zu +machen. + +Programme sollten so geschrieben und strukturiert sein, dass es sowohl +einem Au{\ss}enstehenden als auch einem selbst, nach ein paar Monaten, +leicht f\"allt den Programmablauf nachzuvollziehen und zu +verstehen. Guter Programmierstil zahlt sich auch f\"ur den Sch\"opfer +eines Programmes aus. + +Guter Programmierstil greift auf unterschiedlichen Ebenen an: +\begin{enumerate} +\item Die Struktur von Programmen. +\item Die Namensgebung von Skripten und Funktionen. +\item Die Namensgebung fuer Variablen und Konstanten. +\item Die Verwendung von Einr\"uckungen und Leerzeilen um Bl\"ocke im Code hervorzuheben. +\item Verwendung von Kommentaren und Hilfetexten. +\end{enumerate} + +\section{Struktur von Programmen, Organisation von m-Files im Dateisystem} + +In der Einf\"uhrung zu Funktionen und Skripten wurde schon einmal ein +typisches Programmlayout vorgestellt (Abbildung +\ref{programlayoutfig}). Hier wurde vorgeschlagen ein Skript als +Kontrollskript zu verwenden. Dieses kontrolliert den weiteren +Programmablauf, ruft Funktionen auf, \"ubergibt Argumente und nimmt +R\"uckgabewerte entgegen. Eine solche Struktur macht es einfach den +Ablauf zu verstehen. Es bleibt aber die Frage, wie man das +Kontrollskript unter den anderen \codeterm{m-files} als solches +erkennt. Um dieses zu erleichtern gilt es zwei Dinge zu beachten: +1. Wie werden Programme im Dateisystem organisiert? 2. Wie werden +Programme benannt? + +Es hilft ungemein, wenn zusammengeh\"orige Skripte und Funktionen im +gleichen Ordner auf der Festplatte zu finden sind. Es bietet sich also +an f\"ur jede Analyse einen eigenen Ordner anzulegen und in diesem die +zugeh\"origen \codeterm{m-files} abzulegen. Auf eine tiefere +Schachtelung in weitere Unterordner kann in der Regel verzichtet +werden. \matlab{} erzeugt einen ``MATLAB'' Ordner im eingenen +``Documents'' (Linux) oder ``Eigene Dokumente'' (Windows) Ordner. Es +bietet sich an diesen als Wurzelverzeichnis f\"ur eigene Arbeiten zu +verwenden. Nat\"urlich kann auch jeder andere Ort gew\"ahlen +werden. In dem Beispiel in Abbildung \ref{fileorganizationfig} wird +innerhalb dieses Ordners f\"ur jedes Projekt ein eigener Unterordner +erstellt in welchem widerum f\"ur jedes Problem, jede Analyse ein +weitere Unterodner erstellt wird. In diesen liegen sowohl die +ben\"otigten m-files also auch die Resultate der Analyse (Abbildungen, +Dateien). Zu bemerken sind noch zwei weitere Dinge. Im Projektordner +existiert ein Skript (analysis.m), das dazu gedacht ist, alle Analysen +aufzurufen. Des Weiteren gitb es parallel zu den Projektordnern einen +``functions'' Ordner in dem Funktionen liegen, die in mehr als einem +Projekt oder einer Analyse gebraucht werden. + +Wenn man sich dieses Layout anschaut f\"allt auf, dass es sehr +wahrscheinlich ist, dass bestimmte Namen f\"ur Funktionen und Skripte +mehrfach verwendet werden. Es ist nicht verwunderlich, wenn eine +``load\_data.m'' Funktion in jeder Analyse vorkommt. In der Regel +wird dies nicht zu Konflikten f\"uhren, da \matlab{} zuforderst im +aktuellen Ordner nach passenden Dateien sucht (mehr Information in Box +\ref{matlabpathbox}). + +\begin{figure} + \includegraphics[width=0.75\textwidth]{program_organization} + \titlecaption{\label{fileorganizationfig} M\"ogliche Oganisation von + Programmcode im Dateisystem.}{ F\"ur jedes Projekt werden + Unterordner f\"ur die einzelnen Analysen angelegt. Auf Ebene des + Projektes k\"onnte es ein Skript (hier ``analysis.m'') geben, + welches alle Analysen in den Unterordnern anst\"o{\ss}t.} +\end{figure} + + +\begin{ibox}[t]{\label{matlabpathbox}Der \matlab{} Suchpfad} + + \begin{itemize} + \item Suchpfad, was soll das. + \item Reihenfolge. + \item \"Andern des Pfades. + \end{itemize} + + \includegraphics[width=0.75\textwidth]{search_path} +\end{ibox} + +\section{Namensgebung von Funktionen und Skripten} + + \begin{enumerate} + \item Die Namensgebung fuer Variablen und Konstanten. + \item Die Namensgebung von Skripten und Funktionen. + \item Die Verwendung von Einr\"uckungen und Leerzeilen um Bl\"ocke im Code hervorzuheben. + \item Verwendung von Kommentaren und Hilfetexten. + \end{enumerate} + + + In verschiedenen Sprachen verschiedene Konventionen. In MATLAB ... + \begin{itemize} + \item Funktionen, Skripte: Kleinbuchstaben, Abk\"urzungen. (z.B. \verb+xcorr+, \verb+repmat+) + \item Konvertierungen immer mit format2format (z.B. \verb+num2str+) + \item Variablen immer klein, h\"aufig Abk\"urzungen. + \item Kommentare h\"aufig fuer interne Zwecke aber ausf\"uhrliche Dokumentation mit Hilftexten. + \end{itemize} + + +\section{Namensgebung von Variablen und Konstanten} + + \textbf{``Programmcode muss lesbar sein.''} + \begin{enumerate} + \item Variablen werden klein geschrieben. Wenn n\"otig entweder im + \textit{camelCase} oder mit Unterstrichen (z.B. \verb+spikeCount+ + oder \verb+spike_count+). + \item Funktionen und Skripte mit ausdrucksstarken Namen (z.B. \verb+loadSpikeData+). + \item Kommentare sparsam. Eventuell um Abschnitte zu trennen. + \item Hilfetexte: Ein Problem; sie m\"ussen aktuell sein sonst sind + sie sch\"adlicher als wenn sie gar nicht da w\"aren. + \item Einr\"uckung ist Pflicht. + \item Bl\"ocke im Code werden durch 1 Leerzeile getrennt. + \end{enumerate} + + + Ihr d\"urft all das missachten und einen eingenen Stil entwickeln. Aber:\\ + \vspace{2.5cm} + \centering + \huge{Bleibt konsitent!} + \vspace{2.5cm} + \normalsize + + Es gibt dazu ganze B\"ucher. z.B. Robert C. Martin: \textit{Clean + Code: A Handbook of Agile Software Craftmanship}, Prentice Hall diff --git a/scientificcomputing-script.tex b/scientificcomputing-script.tex index 7103672..3e883ac 100644 --- a/scientificcomputing-script.tex +++ b/scientificcomputing-script.tex @@ -27,6 +27,11 @@ \lstset{inputpath=plotting/code/} \include{plotting/lecture/plotting} + +\graphicspath{{programmingstyle/lecture/}{programmingstyle/lecture/figures/}} +\lstset{inputpath=programmingstyle/code/} +\include{programmingstyle/lecture/programmingstyle} + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \part{Grundlagen der Datenanalyse} From b9cda525d7e9b8baf0785218043e3b24f05ef718 Mon Sep 17 00:00:00 2001 From: Jan Grewe Date: Sat, 14 Nov 2015 00:23:21 +0100 Subject: [PATCH 2/6] ibox for search path --- programmingstyle/lecture/programmingstyle.tex | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/programmingstyle/lecture/programmingstyle.tex b/programmingstyle/lecture/programmingstyle.tex index ca5e0bd..8e634ab 100644 --- a/programmingstyle/lecture/programmingstyle.tex +++ b/programmingstyle/lecture/programmingstyle.tex @@ -8,7 +8,7 @@ machen. Programme sollten so geschrieben und strukturiert sein, dass es sowohl einem Au{\ss}enstehenden als auch einem selbst, nach ein paar Monaten, leicht f\"allt den Programmablauf nachzuvollziehen und zu -verstehen. Guter Programmierstil zahlt sich auch f\"ur den Sch\"opfer +verstehen. Saubere Programmierung zahlt sich auch f\"ur den Sch\"opfer eines Programmes aus. Guter Programmierstil greift auf unterschiedlichen Ebenen an: @@ -73,14 +73,34 @@ aktuellen Ordner nach passenden Dateien sucht (mehr Information in Box \begin{ibox}[t]{\label{matlabpathbox}Der \matlab{} Suchpfad} - - \begin{itemize} - \item Suchpfad, was soll das. - \item Reihenfolge. - \item \"Andern des Pfades. - \end{itemize} + Der Suchpfad definiert, wo \matlab{} nach Skripten und Funktionen + sucht. Wird eine Funktion aufgerufen wird zun\"achst im aktuellen + Arbeitsverzeichnis einem Treffer gesucht. Schl\"agt diese Suche + fehl, so arbeitet sich \matlab{} durch den \codeterm{Suchpfad} + (siehe Abbildung). Der \codeterm{Suchpfad} ist eine Liste von + Ordnern in denen \matlab{} nach Funktionen und Skripten suchen + soll. Die Suche nach der aufgerufenen Funktion wird dabei von oben + nach unten durchgef\"uhrt. Das heisst, dass es, bei + Namensgleichheit, eine Rolle spielen kann an welcher Stelle im + Suchpfad der erste Treffer gefunden wird. Wichtig: \matlab{} sucht + nicht rekursiv! Wenn die gew\"unschte Funktion in einem Unterordner + des aktuellen Arbeitsverzeichnisses liegt, dieses aber nicht + explizit im Suchpfad enthalten ist, so wird die Funktion nicht + gefunden werden. \includegraphics[width=0.75\textwidth]{search_path} + + Man kann den Suchpfad sowohl \"uber die in der Abbildung gezeigte + GUI oder auch \"uber die Kommandozeile editieren. In der GUI hat man + die M\"oglichkeit Ordner aus dem Suchpfad zu entfernen, neue Ordner + (optional inklusive aller Unterordner) hinzuzuf\"ugen oder die + Reihenfolge zu ver\"andern. + + Will man das aktuelle Arbeitsverzeichis wechseln benutzt man das + Kommando \code{cd}, um herauszufinden, in welchem Pfad eine + bestimmte Funktion gefunden wurde, benutzt man das Kommando + \code{which}. Der das aktuelle Areitsverzeichnis wird durch den + Aufruf \code{pwd} auf der Kommandozeile ausgegeben. \end{ibox} \section{Namensgebung von Funktionen und Skripten} From 9af291738f9f65fa73e6e663b33c869641b1f23f Mon Sep 17 00:00:00 2001 From: Jan Grewe Date: Sat, 14 Nov 2015 01:50:28 +0100 Subject: [PATCH 3/6] more work, unfinished --- programmingstyle/lecture/programmingstyle.tex | 153 +++++++++++++----- 1 file changed, 116 insertions(+), 37 deletions(-) diff --git a/programmingstyle/lecture/programmingstyle.tex b/programmingstyle/lecture/programmingstyle.tex index 8e634ab..5090943 100644 --- a/programmingstyle/lecture/programmingstyle.tex +++ b/programmingstyle/lecture/programmingstyle.tex @@ -57,8 +57,8 @@ Projekt oder einer Analyse gebraucht werden. Wenn man sich dieses Layout anschaut f\"allt auf, dass es sehr wahrscheinlich ist, dass bestimmte Namen f\"ur Funktionen und Skripte mehrfach verwendet werden. Es ist nicht verwunderlich, wenn eine -``load\_data.m'' Funktion in jeder Analyse vorkommt. In der Regel -wird dies nicht zu Konflikten f\"uhren, da \matlab{} zuforderst im +``load\_data.m'' Funktion in jeder Analyse vorkommt. In der Regel wird +dies nicht zu Konflikten f\"uhren, da \matlab{} zuforderst im aktuellen Ordner nach passenden Dateien sucht (mehr Information in Box \ref{matlabpathbox}). @@ -105,45 +105,124 @@ aktuellen Ordner nach passenden Dateien sucht (mehr Information in Box \section{Namensgebung von Funktionen und Skripten} - \begin{enumerate} - \item Die Namensgebung fuer Variablen und Konstanten. - \item Die Namensgebung von Skripten und Funktionen. - \item Die Verwendung von Einr\"uckungen und Leerzeilen um Bl\"ocke im Code hervorzuheben. - \item Verwendung von Kommentaren und Hilfetexten. - \end{enumerate} +\matlab{} sucht Funktionen und Skripte ausschlie{\ss}lich anhand der +Namen. Dabei spielt die Gro{\ss}- und Kleinschreibung eine Rolle. Das +hei{\ss}t, dass die Namen ``test_funktion.m'' und ``Test_funktion.m'' +zwei unterschiedliche Funktionen benennen k\"onnen. Diese Art +Variation des Namens ist nat\"urlich nicht sinnvoll. Sie tr\"agt keine +Information \"uber den Unterschied der beiden Funktionen. Auch sagt +der Name nahezu nichts \"uber den Zweck der Funktion aus. Die +Namensgebung f\"allt mitunter nicht leicht, es lohnt sich aber +ausdruckstarke Namen zu finden. Ausdrucksstark bedeutet, dass sich aus +dem Namen ein R\"uckschluss auf den Zweck ziehen lassen sollte. + +\matlab{} macht keine weiteren Vorgaben, was die Namen +angeht. Allerdings folgt die Benennung der vordefinierten Funktionen +gewissen Mustern: +\begin{itemize} +\item Namen werden immer klein geschrieben. +\item Es werden gerne Abk\"urzungen eingesetzt (z.B. \code{xcorr} + f\"ur die Kreuzkorrelation oder \code{repmat} f\"ur ``repeat matrix'') +\item Funktionen, die zwischen Formaten konvertieren sind immer nach + dem Muster ``format2format'' (z.B. \code{num2str} f\"ur die + Konvertierung ``number to string'', Umwandlung eines numerischen + Wertes in einen Text) benannt. +\end{itemize} + +Andere \"ubliche Muster sind der \emph{camelCase} bei dem die +Anf\"ange zusammengesetzter Worte jeweils gro{\ss} geschrieben werden +oder auch die Verwendung von Unterstrichen zur Trennung von +Namenskomponenten. Eine Funktion, die die Anzahl Aktionspotentiale +berechnet k\"onnte etwa \codeterm{spikeCount.m} oder auch +\codeterm{spike\_count.m} benannt werden. Leerzeichen, Sonderzeichen +oder Anf\"ange mit Zahlen sind in Namen nicht erlaubt. - In verschiedenen Sprachen verschiedene Konventionen. In MATLAB ... +\section{Namensgebung von Variablen und Konstanten} + +F\"ur die Bennennung von Variablen und Konstanten gelten die gleichen +Regeln wie f\"ur die Namen von Funktionen und Skripten. Die Maxime von +gutem Programmierstil ist: \emph{``Programmcode muss lesbar + sein.''}. Dabei helfen gute Namen ungemein. Auch wenn es schwer +f\"allt passende Namen zu finden, die nicht zu lang werden sollte man +sich auch da M\"uhe geben. + +Bei den Funktionen und Skripten fragt man danach, welchen Zweck sie +erf\"ullen, bei Variablen fragt man nach dem Inhalt. Eine Varaible die +die mittlere Anzahl Aktionspotentiale speichert k\"onnte also +\codeterm{average\_spike\_count} hei{\ss}en. Wenn die Variable nicht nur +einen sondern mehrere Werte aufnimmt, dann ist der Plural angebracht +(\codeterm{average\_spike\_counts}). + + +\section{Codestil} + +Die Lesbarkeit von Programmen wird sehr durch den Codestil +beeinflusst. Ein Programm, in dem z.B. Schleifenk\"orper nicht (oder +zuf\"allig) einger\"uckt sind ist deutlich schwerer zu lesen und zu +verstehen, als eines, in dem eine konsistente Einr\"uckung vorgenommen +wurde. + +Gerne werden Leerzeielen eingef\"ugt um Abschnitte im Programm zu +trennen. Das ist v\"ollig ok, wenn es konsistent und sparsam benutzt +wird. Hier sollte eine Leerzeile ausreichen. Zu gro{\ss}e Abst\"ande +f\"uhren dazu das das Programm nicht mehr auf eine Seite passt und man +leicht den \"Uberblick verliert. + + + \TODO chaotisches und aufger\"aumtes Listing + +\section{Verwendung von Kommentaren} + +Kommentare k\"onnen ebenfalls sehr zum Verst\"andnis beitragen. Bei +allen vordefinierten \matlab{} Funktionen findet sich am Anfang eine +Kommentarblock, der den Zweck der Funktion, die verschiedenen +M\"oglichkeiten des Funktionsaufrufs und die Argumente und +R\"uckgabewerte beschreibt. Auch in eingenen Funktionen, vor allem +wenn auch andere Personen sie benutzen sollen, sind diese Kommentare +hilfreich. H\"aufig werden kurze Kommentare eingesetzt um Abschnitte +im Programm zu trennen. Hierbei sollte man auch sparsam sein. Jede +Zeile zu erkl\"aren kann in der Entwicklungsphase eines Programms sehr +hilfreich sein, bl\"aht aber den Code auf und bei der Verwendung guter +Variablennamen sind viel Zeilen weitestgehend selbsterkl\"arend. + +\begin{important} \begin{itemize} - \item Funktionen, Skripte: Kleinbuchstaben, Abk\"urzungen. (z.B. \verb+xcorr+, \verb+repmat+) - \item Konvertierungen immer mit format2format (z.B. \verb+num2str+) - \item Variablen immer klein, h\"aufig Abk\"urzungen. - \item Kommentare h\"aufig fuer interne Zwecke aber ausf\"uhrliche Dokumentation mit Hilftexten. + \item Kommentare sind gut und wichtig aber: Sie m\"ussen richtig + sein! + \item Ein Kommentar der l\"ugt, ist schlimmer als gar kein Kommentar! + \item Kommentare m\"ussen gepflegt werden sonst sind sie mehr als + wertlos! \end{itemize} +\end{important} + +\section{Auslagerung von Aufgaben in Funktionen} -\section{Namensgebung von Variablen und Konstanten} +Spaghetticode - \textbf{``Programmcode muss lesbar sein.''} - \begin{enumerate} - \item Variablen werden klein geschrieben. Wenn n\"otig entweder im - \textit{camelCase} oder mit Unterstrichen (z.B. \verb+spikeCount+ - oder \verb+spike_count+). - \item Funktionen und Skripte mit ausdrucksstarken Namen (z.B. \verb+loadSpikeData+). - \item Kommentare sparsam. Eventuell um Abschnitte zu trennen. - \item Hilfetexte: Ein Problem; sie m\"ussen aktuell sein sonst sind - sie sch\"adlicher als wenn sie gar nicht da w\"aren. - \item Einr\"uckung ist Pflicht. - \item Bl\"ocke im Code werden durch 1 Leerzeile getrennt. - \end{enumerate} - - - Ihr d\"urft all das missachten und einen eingenen Stil entwickeln. Aber:\\ - \vspace{2.5cm} - \centering - \huge{Bleibt konsitent!} - \vspace{2.5cm} - \normalsize - - Es gibt dazu ganze B\"ucher. z.B. Robert C. Martin: \textit{Clean - Code: A Handbook of Agile Software Craftmanship}, Prentice Hall +inline functions + + +\section{Besonderheiten bei Skripten} + +Achtung, globaler G\"ultigkeitsbereich! + +Kollision von Variablennamen. + +Best practice. + +\begin{important} + Programmcode soll lesbar sein. Namen von Variablen, Funktionen und + Skripten sollten ausdrucksstark sein und R\"uckschl\"usse auf den + Inhalt oder den Zweck erlauben. Einen pers\"onlichen Programmierstil + zu entwickeln ist v\"ollig in Ordnung solange er konsistent ist. In + machen Programmiersprachen gibt es Traditionen und + \"Ubereink\"unfte, diese sollten dann beachtet werden. + + Es lohnt sich! +\end{important} + + +Literatur zum Programmierstil: z.B. Robert C. Martin: \textit{Clean + Code: A Handbook of Agile Software Craftmanship}, Prentice Hall From 108210210a364a3c3c180189183eb0d354aaacdb Mon Sep 17 00:00:00 2001 From: Jan Grewe Date: Sat, 14 Nov 2015 13:08:21 +0100 Subject: [PATCH 4/6] finished (?) chapter, add example code --- programmingstyle/code/calculate_sines.m | 30 ++++ programmingstyle/lecture/programmingstyle.tex | 151 +++++++++++++++--- 2 files changed, 155 insertions(+), 26 deletions(-) create mode 100644 programmingstyle/code/calculate_sines.m diff --git a/programmingstyle/code/calculate_sines.m b/programmingstyle/code/calculate_sines.m new file mode 100644 index 0000000..635764d --- /dev/null +++ b/programmingstyle/code/calculate_sines.m @@ -0,0 +1,30 @@ +function sines = calculate_sines(x, amplitudes, frequencies) + % Function calculates sinewaves with all combinations of + % given amplitudes and frequencies. + % Arguments: x, a vector of radiants for which the sine should be + % computed + % amplitudes, a vector of amplitudes + % frequencies, a vector of frequencies + % + % Returns: a 3-D Matrix of sinewaves, 2nd dimension represents + % the amplitudes, 3rd the frequencies. + + sines = zeros(length(x), length(amplitudes), length(frequencies)); + + for i = 1:length(amplitudes) + sines(:, i, :) = sines_with_frequencies(x, amplitudes(i), frequencies); + end +end + + +function sines = sines_with_frequencies(x, amplitude, frequencies) + sines = zeros(length(x), length(frequencies)); + for i = 1:length(frequencies) + sines(:,i) = sinewave(x, amplitude, frequencies(i)); + end +end + + +function sine = sinewave(x, amplitude, frequency) + sine = sin(2 .* pi .* x *frequency) .* amplitude; +end \ No newline at end of file diff --git a/programmingstyle/lecture/programmingstyle.tex b/programmingstyle/lecture/programmingstyle.tex index 5090943..e977ace 100644 --- a/programmingstyle/lecture/programmingstyle.tex +++ b/programmingstyle/lecture/programmingstyle.tex @@ -15,9 +15,11 @@ Guter Programmierstil greift auf unterschiedlichen Ebenen an: \begin{enumerate} \item Die Struktur von Programmen. \item Die Namensgebung von Skripten und Funktionen. -\item Die Namensgebung fuer Variablen und Konstanten. -\item Die Verwendung von Einr\"uckungen und Leerzeilen um Bl\"ocke im Code hervorzuheben. +\item Die Namensgebung f\"ur Variablen und Konstanten. +\item Die Verwendung von Einr\"uckungen und Leerzeilen um Bl\"ocke im + Code hervorzuheben. \item Verwendung von Kommentaren und Hilfetexten. +\item Auslagerung von Funktionalit\"at in eigene Funktionen. \end{enumerate} \section{Struktur von Programmen, Organisation von m-Files im Dateisystem} @@ -107,7 +109,7 @@ aktuellen Ordner nach passenden Dateien sucht (mehr Information in Box \matlab{} sucht Funktionen und Skripte ausschlie{\ss}lich anhand der Namen. Dabei spielt die Gro{\ss}- und Kleinschreibung eine Rolle. Das -hei{\ss}t, dass die Namen ``test_funktion.m'' und ``Test_funktion.m'' +hei{\ss}t, dass die Namen ``test\_funktion.m'' und ``Test\_funktion.m'' zwei unterschiedliche Funktionen benennen k\"onnen. Diese Art Variation des Namens ist nat\"urlich nicht sinnvoll. Sie tr\"agt keine Information \"uber den Unterschied der beiden Funktionen. Auch sagt @@ -163,14 +165,55 @@ zuf\"allig) einger\"uckt sind ist deutlich schwerer zu lesen und zu verstehen, als eines, in dem eine konsistente Einr\"uckung vorgenommen wurde. -Gerne werden Leerzeielen eingef\"ugt um Abschnitte im Programm zu +Gerne werden Leerzeilen eingef\"ugt um Abschnitte im Programm zu trennen. Das ist v\"ollig ok, wenn es konsistent und sparsam benutzt wird. Hier sollte eine Leerzeile ausreichen. Zu gro{\ss}e Abst\"ande -f\"uhren dazu das das Programm nicht mehr auf eine Seite passt und man +f\"uhren dazu, dass das Programm nicht mehr auf eine Seite passt und man leicht den \"Uberblick verliert. - - \TODO chaotisches und aufger\"aumtes Listing +Die beiden folgenden Listings \ref{chaoticcode} und \ref{cleancode} +zeigen die Implementation des random-walk einmal eher chaotisch und +einmal aufger\"aumt. + +\begin{lstlisting}[label=chaoticcode, caption={Random-walk Implementation unaufgr\"aumt.}] +num_runs = 10; +max_steps = 1000; + +positions = zeros(max_steps, num_runs); + +for run = 1:num_runs + + +for step = 2:max_steps + +x = randn(1); +if x<0 +positions(step, run)= positions(step-1, run)+1; + + +elseif x>0 + positions(step,run)=positions(step-1,run)-1; + end +end +end +\end{lstlisting} + +\begin{lstlisting}[label=cleancode, caption={Random-walk Implementation etwas ordentlicher.}] +num_runs = 10; +max_steps = 1000; +positions = zeros(max_steps, num_runs); + +for run = 1:num_runs + for step = 2:max_steps + x = randn(1); + if x < 0 + positions(step, run) = positions(step-1, run) + 1; + elseif x > 0 + positions(step, run) = positions(step-1, run) - 1; + end + end +end +\end{lstlisting} \section{Verwendung von Kommentaren} @@ -190,8 +233,8 @@ Variablennamen sind viel Zeilen weitestgehend selbsterkl\"arend. \begin{itemize} \item Kommentare sind gut und wichtig aber: Sie m\"ussen richtig sein! - \item Ein Kommentar der l\"ugt, ist schlimmer als gar kein Kommentar! - \item Kommentare m\"ussen gepflegt werden sonst sind sie mehr als + \item Ein Kommentar, der l\"ugt, ist schlimmer als gar kein Kommentar! + \item Kommentare m\"ussen gepflegt werden, sonst sind sie mehr als wertlos! \end{itemize} \end{important} @@ -199,30 +242,86 @@ Variablennamen sind viel Zeilen weitestgehend selbsterkl\"arend. \section{Auslagerung von Aufgaben in Funktionen} -Spaghetticode - -inline functions +Kommentare oder Leerzeilen werden benutzt um Abschnitte des Codes +abzutrennen und nazudeuten, dass ab da etwas inhaltlich anderes +gemacht wird. Wenn man im Zuge ist, eine solche inhaltliche Trennung +einzuf\"ugen muss man sich immer fragen, ob dieser Teil des Programms +nicht in eine eigene Funktion ausgelagert werden sollte. Fast immer +kann man das bejahen. +Abschnitte nicht auszulagern f\"uhrt zu sehr langen m-Files, die +leicht un\"ubersichtlich sind. Man nennt sie +\codeterm{Spaghetticode}. Es ist h\"ochste Zeit \"uber Auslagerung in +Funktionen nachzudenken. -\section{Besonderheiten bei Skripten} +\begin{important} + Wann sollte man Programmteile in eigene Funktionen auslagern? + \begin{itemize} + \item Wenn man innerhalb einer Funktion, eines Skripts mehr als zwei + Einr\"uckungsebenen hat. + \item Wenn man wiederholte Strukturen im Code hat. + \item Wenn man versucht ist, diese mit Copy and Paste zu erzeugen. + \end{itemize} +\end{important} -Achtung, globaler G\"ultigkeitsbereich! +\subsection{Lokale Funktionen und geschachtelte Funktionen} + +Eine M\"oglichkeit Spaghetticode zu vermeiden ist das Auslagern von +Funktionalit\"at in eigene Funktionen. Dies f\"uhrt dazu, dass man +eine F\"ulle von Dateien erzeugt, die die \"Ubersichtlichkeit nicht +unbedingt erh\"ohen. Wenn die auszulagernde Funktionalit\"at an vielen +Stellen ben\"otigt werden k\"onnte ist es dennoch sinnvol dies zu +tun. Wenn nicht, dann bietet \matlab{} die M\"oglichkeit sogenannte +\codeterm{lokale Funktionen} oder auch \codeterm{geschachtelte + Funktionen} (\enterm{nested functions}) zu erstellen (Listing +\ref{localfunctions} zeigt ein Beispiel f\"ur eine lokale Funktion). + +\lstinputlisting[label=localfunctions, caption={\codeterm{Lokale Funktionen} erh\"ohen die Lesbarkeit sind aber nur innerhalb der definierenden Datei verf\"ugbar.}]{calculate_sines.m} + +Lokale Funktionen existieren in der gleichen Datei und sind nur dort +verf\"ugbar. Jede Funktion hat ihren eigenen G\"ultigkeitsbereich, das +hei{\ss}t, dass Variablen aus den aufrufenden Funktionen nicht +sichtbar sind. Bei sogenannten \codeterm{geschachtelten Funktionen} +ist das anders. Diese werden innerhalb eines Funktionsk\"orpers +(zwischen den Schl\"usselworten \codeterm{function} und dem +\codeterm{end} definiert und k\"onnen auf alle Variablen der +``Mutterfunktion'' zugreifen und diese auch ver\"andern. Folglich +sollten sie nur mit Bedacht eingesetzt werden. -Kollision von Variablennamen. +\section{Besonderheiten bei Skripten} -Best practice. +Ein \"ahnliches Problem wurde schon bei der Einf\"uhrung der Skripte +erw\"ahnt. Variablen, die in Skripten definiert werden sind global im +\codeterm{Workspace} verf\"ugbar. Es besteht die Gefahr von +Namenskollisionen. Problem dabei ist, dass der Nutzer gar nicht +mitbekommt, wenn eine Variable redefiniert oder neuen Inhalt +zugewiesen bekommt. Fehler, die auf derartigen Kollisionen beruhen +sind h\"aufig nur schwer zu finden, da das Programm f\"ur sich korrekt +aussieht. \begin{important} - Programmcode soll lesbar sein. Namen von Variablen, Funktionen und - Skripten sollten ausdrucksstark sein und R\"uckschl\"usse auf den - Inhalt oder den Zweck erlauben. Einen pers\"onlichen Programmierstil - zu entwickeln ist v\"ollig in Ordnung solange er konsistent ist. In - machen Programmiersprachen gibt es Traditionen und - \"Ubereink\"unfte, diese sollten dann beachtet werden. - - Es lohnt sich! + Es empfiehlt sich zu Beginn eines Skriptes alle Variablen im + \codeterm{Workspace} zu l\"oschen (\code{clear}). Meist ist auch + ein \code{close all} angebracht. + + Am Ende eines Skriptes sollte der \codeterm{Workspace} mithilfe von + \code{clear} wieder von all den Variablen ges\"aubert werden, die + nicht mehr ben\"otigt werden. \end{important} +\section{Fazit} + +Programmcode soll lesbar sein. Namen von Variablen, Funktionen und +Skripten sollten ausdrucksstark sein und R\"uckschl\"usse auf den +Inhalt oder den Zweck erlauben. Einen pers\"onlichen Programmierstil +zu entwickeln ist v\"ollig in Ordnung solange er konsistent ist. In +machen Programmiersprachen gibt es Traditionen und \"Ubereink\"unfte, +diese sollten dann beachtet werden. + +Wiederholte Programmabschnitte sollten in Funktionen ausgelagert +werden. Wenn diese nich von globalem Interesse sind, kann man auch mit +\codeterm{lokalen} oder \codeterm{geschachtelten Funktionen} die +Lesbarkeit erh\"ohen. -Literatur zum Programmierstil: z.B. Robert C. Martin: \textit{Clean - Code: A Handbook of Agile Software Craftmanship}, Prentice Hall +\noindent Es lohnt sich auf den eigenen Programmierstil zu achten!\footnote{Literatur zum Programmierstil: z.B. Robert C. Martin: \textit{Clean + Code: A Handbook of Agile Software Craftmanship}, Prentice Hall} From af1faf941c984ebaba2e123db4ca542f6755098c Mon Sep 17 00:00:00 2001 From: Jan Benda Date: Sat, 14 Nov 2015 21:15:25 +0100 Subject: [PATCH 5/6] Improved progrsmming style chapter. --- header.tex | 1 + programmingstyle/code/calculate_sines.m | 4 +- programmingstyle/lecture/programmingstyle.tex | 250 +++++++++++------- 3 files changed, 152 insertions(+), 103 deletions(-) diff --git a/header.tex b/header.tex index 6d15f95..b492b64 100644 --- a/header.tex +++ b/header.tex @@ -171,6 +171,7 @@ \newcommand{\enterm}[1]{``#1''} \newcommand{\determ}[1]{\textit{#1}} \newcommand{\codeterm}[1]{\textit{#1}} +\newcommand{\keycode}[1]{\texttt{#1}} \newcommand{\file}[1]{\texttt{#1}} %%%%% code/matlab commands: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/programmingstyle/code/calculate_sines.m b/programmingstyle/code/calculate_sines.m index 635764d..cd69b76 100644 --- a/programmingstyle/code/calculate_sines.m +++ b/programmingstyle/code/calculate_sines.m @@ -12,7 +12,7 @@ function sines = calculate_sines(x, amplitudes, frequencies) sines = zeros(length(x), length(amplitudes), length(frequencies)); for i = 1:length(amplitudes) - sines(:, i, :) = sines_with_frequencies(x, amplitudes(i), frequencies); + sines(:,i,:) = sines_with_frequencies(x, amplitudes(i), frequencies); end end @@ -27,4 +27,4 @@ end function sine = sinewave(x, amplitude, frequency) sine = sin(2 .* pi .* x *frequency) .* amplitude; -end \ No newline at end of file +end diff --git a/programmingstyle/lecture/programmingstyle.tex b/programmingstyle/lecture/programmingstyle.tex index e977ace..03be2a6 100644 --- a/programmingstyle/lecture/programmingstyle.tex +++ b/programmingstyle/lecture/programmingstyle.tex @@ -8,8 +8,8 @@ machen. Programme sollten so geschrieben und strukturiert sein, dass es sowohl einem Au{\ss}enstehenden als auch einem selbst, nach ein paar Monaten, leicht f\"allt den Programmablauf nachzuvollziehen und zu -verstehen. Saubere Programmierung zahlt sich auch f\"ur den Sch\"opfer -eines Programmes aus. +verstehen. Saubere Programmierung zahlt sich aber in erster Linie +f\"ur den Verfasser eines Programmes aus. Guter Programmierstil greift auf unterschiedlichen Ebenen an: \begin{enumerate} @@ -22,49 +22,48 @@ Guter Programmierstil greift auf unterschiedlichen Ebenen an: \item Auslagerung von Funktionalit\"at in eigene Funktionen. \end{enumerate} -\section{Struktur von Programmen, Organisation von m-Files im Dateisystem} +\section{Organisation von m-Files im Dateisystem} In der Einf\"uhrung zu Funktionen und Skripten wurde schon einmal ein -typisches Programmlayout vorgestellt (Abbildung -\ref{programlayoutfig}). Hier wurde vorgeschlagen ein Skript als -Kontrollskript zu verwenden. Dieses kontrolliert den weiteren -Programmablauf, ruft Funktionen auf, \"ubergibt Argumente und nimmt -R\"uckgabewerte entgegen. Eine solche Struktur macht es einfach den -Ablauf zu verstehen. Es bleibt aber die Frage, wie man das -Kontrollskript unter den anderen \codeterm{m-files} als solches -erkennt. Um dieses zu erleichtern gilt es zwei Dinge zu beachten: -1. Wie werden Programme im Dateisystem organisiert? 2. Wie werden -Programme benannt? +typisches Programmlayout vorgestellt (\figref{programlayoutfig}). Hier +wurde vorgeschlagen ein Skript als Kontrollskript zu verwenden. Dieses +kontrolliert den weiteren Programmablauf, ruft Funktionen auf, +\"ubergibt Argumente und nimmt R\"uckgabewerte entgegen. Eine solche +Struktur macht es einfach den Ablauf zu verstehen. Es bleibt aber die +Frage, wie man das Kontrollskript unter den anderen \codeterm{m-files} +als solches erkennt. Um dieses zu erleichtern gilt es zwei Dinge zu +beachten: (i) Wie werden Programme im Dateisystem organisiert? (ii) Wie +werden Programme benannt? Es hilft ungemein, wenn zusammengeh\"orige Skripte und Funktionen im gleichen Ordner auf der Festplatte zu finden sind. Es bietet sich also -an f\"ur jede Analyse einen eigenen Ordner anzulegen und in diesem die +an, f\"ur jede Analyse einen eigenen Ordner anzulegen und in diesem die zugeh\"origen \codeterm{m-files} abzulegen. Auf eine tiefere Schachtelung in weitere Unterordner kann in der Regel verzichtet -werden. \matlab{} erzeugt einen ``MATLAB'' Ordner im eingenen -``Documents'' (Linux) oder ``Eigene Dokumente'' (Windows) Ordner. Es -bietet sich an diesen als Wurzelverzeichnis f\"ur eigene Arbeiten zu +werden. \matlab{} erzeugt einen ``MATLAB'' Ordner im eigenen +\file{Documents} (Linux) oder \file{Eigene Dokumente} (Windows) Ordner. Es +bietet sich an, diesen Ordner als Wurzelverzeichnis f\"ur eigene Arbeiten zu verwenden. Nat\"urlich kann auch jeder andere Ort gew\"ahlen -werden. In dem Beispiel in Abbildung \ref{fileorganizationfig} wird +werden. In dem Beispiel in \figref{fileorganizationfig} wird innerhalb dieses Ordners f\"ur jedes Projekt ein eigener Unterordner -erstellt in welchem widerum f\"ur jedes Problem, jede Analyse ein +erstellt, in welchem widerum f\"ur jedes Problem, jede Analyse ein weitere Unterodner erstellt wird. In diesen liegen sowohl die -ben\"otigten m-files also auch die Resultate der Analyse (Abbildungen, -Dateien). Zu bemerken sind noch zwei weitere Dinge. Im Projektordner +ben\"otigten \codeterm{m-files} also auch die Resultate der Analyse (Abbildungen, +Daten-Dateien). Zu bemerken sind noch zwei weitere Dinge. Im Projektordner existiert ein Skript (analysis.m), das dazu gedacht ist, alle Analysen aufzurufen. Des Weiteren gitb es parallel zu den Projektordnern einen -``functions'' Ordner in dem Funktionen liegen, die in mehr als einem +\file{functions}-Ordner in dem Funktionen liegen, die in mehr als einem Projekt oder einer Analyse gebraucht werden. -Wenn man sich dieses Layout anschaut f\"allt auf, dass es sehr +Beim Betrachten dieses Layouts f\"allt auf, dass es sehr wahrscheinlich ist, dass bestimmte Namen f\"ur Funktionen und Skripte mehrfach verwendet werden. Es ist nicht verwunderlich, wenn eine -``load\_data.m'' Funktion in jeder Analyse vorkommt. In der Regel wird -dies nicht zu Konflikten f\"uhren, da \matlab{} zuforderst im -aktuellen Ordner nach passenden Dateien sucht (mehr Information in Box -\ref{matlabpathbox}). +\file{load\_data.m} Funktion in jeder Analyse vorkommt. In der Regel +wird dies nicht zu Konflikten f\"uhren, da \matlab{} zuerst im +aktuellen Ordner nach passenden Dateien sucht (mehr Information zum +\matlab-Suchpfad in Box~\ref{matlabpathbox}). -\begin{figure} +\begin{figure}[tp] \includegraphics[width=0.75\textwidth]{program_organization} \titlecaption{\label{fileorganizationfig} M\"ogliche Oganisation von Programmcode im Dateisystem.}{ F\"ur jedes Projekt werden @@ -74,7 +73,7 @@ aktuellen Ordner nach passenden Dateien sucht (mehr Information in Box \end{figure} -\begin{ibox}[t]{\label{matlabpathbox}Der \matlab{} Suchpfad} +\begin{ibox}[tp]{\label{matlabpathbox}Der \matlab{} Suchpfad} Der Suchpfad definiert, wo \matlab{} nach Skripten und Funktionen sucht. Wird eine Funktion aufgerufen wird zun\"achst im aktuellen Arbeitsverzeichnis einem Treffer gesucht. Schl\"agt diese Suche @@ -109,14 +108,24 @@ aktuellen Ordner nach passenden Dateien sucht (mehr Information in Box \matlab{} sucht Funktionen und Skripte ausschlie{\ss}lich anhand der Namen. Dabei spielt die Gro{\ss}- und Kleinschreibung eine Rolle. Das -hei{\ss}t, dass die Namen ``test\_funktion.m'' und ``Test\_funktion.m'' -zwei unterschiedliche Funktionen benennen k\"onnen. Diese Art -Variation des Namens ist nat\"urlich nicht sinnvoll. Sie tr\"agt keine -Information \"uber den Unterschied der beiden Funktionen. Auch sagt -der Name nahezu nichts \"uber den Zweck der Funktion aus. Die -Namensgebung f\"allt mitunter nicht leicht, es lohnt sich aber -ausdruckstarke Namen zu finden. Ausdrucksstark bedeutet, dass sich aus -dem Namen ein R\"uckschluss auf den Zweck ziehen lassen sollte. +hei{\ss}t, dass die beiden Dateien \file{test\_funktion.m} und +\file{Test\_funktion.m} zwei unterschiedliche Funktionen benennen +k\"onnen. Diese Art der Variation des Namens ist nat\"urlich nicht +sinnvoll. Sie tr\"agt keine Information \"uber den Unterschied der +beiden Funktionen. Auch sagt der Name nahezu nichts \"uber den Zweck +der Funktion aus. + +Die Namensgebung f\"allt mitunter nicht leicht --- manchmal ist es +sogar der schwierigste Aspekt des Programmierens! Ausdrucksstarke +Namen zu finden lohnt sich aber. Ausdrucksstark bedeutet, dass sich +aus dem Namen ein R\"uckschluss auf den Zweck ziehen lassen sollte. + +\begin{important} + Die Namen von Funktionen und Skripte sollten m\"oglichst viel \"uber + die Funktionsweise oder den Zweck aussagen (\file{firingrates.m} + statt \file{uebung.m}). Gute Namen f\"ur Funktionen und Skripte sind + die beste Dokumentation. +\end{important} \matlab{} macht keine weiteren Vorgaben, was die Namen angeht. Allerdings folgt die Benennung der vordefinierten Funktionen @@ -131,12 +140,12 @@ gewissen Mustern: Wertes in einen Text) benannt. \end{itemize} -Andere \"ubliche Muster sind der \emph{camelCase} bei dem die +Andere \"ubliche Muster sind der \emph{camelCase}, bei dem die Anf\"ange zusammengesetzter Worte jeweils gro{\ss} geschrieben werden oder auch die Verwendung von Unterstrichen zur Trennung von -Namenskomponenten. Eine Funktion, die die Anzahl Aktionspotentiale -berechnet k\"onnte etwa \codeterm{spikeCount.m} oder auch -\codeterm{spike\_count.m} benannt werden. Leerzeichen, Sonderzeichen +Namenskomponenten. Eine Funktion, die die Anzahl von +Aktionspotentialen bestimmt k\"onnte etwa \file{spikeCount.m} oder +\file{spike\_count.m} benannt werden. Leerzeichen, Sonderzeichen oder Anf\"ange mit Zahlen sind in Namen nicht erlaubt. @@ -146,15 +155,26 @@ F\"ur die Bennennung von Variablen und Konstanten gelten die gleichen Regeln wie f\"ur die Namen von Funktionen und Skripten. Die Maxime von gutem Programmierstil ist: \emph{``Programmcode muss lesbar sein.''}. Dabei helfen gute Namen ungemein. Auch wenn es schwer -f\"allt passende Namen zu finden, die nicht zu lang werden sollte man -sich auch da M\"uhe geben. +f\"allt passende und nicht zu lange Namen zu finden, sollte einer gute +Namensgebung ernst genommen werden. -Bei den Funktionen und Skripten fragt man danach, welchen Zweck sie -erf\"ullen, bei Variablen fragt man nach dem Inhalt. Eine Varaible die -die mittlere Anzahl Aktionspotentiale speichert k\"onnte also -\codeterm{average\_spike\_count} hei{\ss}en. Wenn die Variable nicht nur -einen sondern mehrere Werte aufnimmt, dann ist der Plural angebracht -(\codeterm{average\_spike\_counts}). +W\"ahrend die Namen von Funktionen und Skripten ihren Zweck +beschreiben, sollten die Namen von Variablen ihren Inhalt +beschreiben. Eine Variable, die die mittlere Anzahl von +Aktionspotentialen speichert, k\"onnte also +\codeterm{average\_spike\_count} hei{\ss}en. Wenn die Variable nicht +nur einen sondern mehrere Werte aufnimmt, dann ist der Plural +angebracht (\codeterm{average\_spike\_counts}). + +Die Laufvariablen von \code{for}-Schleifen werden oft nur \code{i}, +\code{j} oder \code{k} benannt und sollten aber die einzige Ausnahme +bzgl. ausdrucksstarker Namensgebung bleiben. + +\begin{important} + Die Namen von Variablen sollten m\"oglichst viel \"uber ihren Inhalt + aussagen (\code{spike\_count} statt \code{x}). Gute Namen + f\"ur Variablen sind die beste Dokumentation. +\end{important} \section{Codestil} @@ -163,19 +183,21 @@ Die Lesbarkeit von Programmen wird sehr durch den Codestil beeinflusst. Ein Programm, in dem z.B. Schleifenk\"orper nicht (oder zuf\"allig) einger\"uckt sind ist deutlich schwerer zu lesen und zu verstehen, als eines, in dem eine konsistente Einr\"uckung vorgenommen -wurde. +wurde. Mit der Tastenkombination \keycode{Ctrl-I} % XXX Oder wie war das? XXX +kann ein markierter +Bereich im \matlab{} Editor automatisch richtig einger\"uckt werden. -Gerne werden Leerzeilen eingef\"ugt um Abschnitte im Programm zu -trennen. Das ist v\"ollig ok, wenn es konsistent und sparsam benutzt -wird. Hier sollte eine Leerzeile ausreichen. Zu gro{\ss}e Abst\"ande -f\"uhren dazu, dass das Programm nicht mehr auf eine Seite passt und man -leicht den \"Uberblick verliert. +Sparsam und konsistent eingef\"ugte einzelne Leerzeilen sind +hervorragend geeignet, um logische Abschnitte eines Programm zu +trennen. Zu viele Leerzeilen haben den Nachteil, dass das Programm +nicht mehr auf eine Seite passt und dadurch leichter der \"Uberblick +verlorgen geht. Die beiden folgenden Listings \ref{chaoticcode} und \ref{cleancode} zeigen die Implementation des random-walk einmal eher chaotisch und -einmal aufger\"aumt. +einmal aufger\"aumt und \"ubersichtlich. -\begin{lstlisting}[label=chaoticcode, caption={Random-walk Implementation unaufgr\"aumt.}] +\begin{lstlisting}[label=chaoticcode, caption={Un\"ubersichtliche Implementation des Random-walk.}] num_runs = 10; max_steps = 1000; @@ -198,7 +220,7 @@ end end \end{lstlisting} -\begin{lstlisting}[label=cleancode, caption={Random-walk Implementation etwas ordentlicher.}] +\begin{lstlisting}[label=cleancode, caption={\"Ubersichtliche Implementation des Random-walk.}] num_runs = 10; max_steps = 1000; positions = zeros(max_steps, num_runs); @@ -217,64 +239,89 @@ end \section{Verwendung von Kommentaren} -Kommentare k\"onnen ebenfalls sehr zum Verst\"andnis beitragen. Bei -allen vordefinierten \matlab{} Funktionen findet sich am Anfang eine -Kommentarblock, der den Zweck der Funktion, die verschiedenen -M\"oglichkeiten des Funktionsaufrufs und die Argumente und -R\"uckgabewerte beschreibt. Auch in eingenen Funktionen, vor allem -wenn auch andere Personen sie benutzen sollen, sind diese Kommentare -hilfreich. H\"aufig werden kurze Kommentare eingesetzt um Abschnitte -im Programm zu trennen. Hierbei sollte man auch sparsam sein. Jede -Zeile zu erkl\"aren kann in der Entwicklungsphase eines Programms sehr -hilfreich sein, bl\"aht aber den Code auf und bei der Verwendung guter -Variablennamen sind viel Zeilen weitestgehend selbsterkl\"arend. +Kommentarzeilen werden in \matlab{} mit dem Prozentzeichen \cide{\%} +gekennzeichnet. Gezielt und sparsam eingesetzte Kommentare sind f\"ur +das Verst\"andnis eines Programms sehr n\"utzlich. Am wichtigsten +sind kurze Kommentare, die den Zweck und das Ziel eines Abschnitts im +Programm erl\"autern (z.B. \code{\% compute mean firing rate over all + trials}). + +Zu viele Kommentare k\"onnen in der Entwicklungsphase eines Programms +sehr hilfreich sein, bl\"ahen aber den Code auf. Durch die Verwendung +guter Variablen- und Funktionsnamen sollten die meisten Zeilen sowieso +weitestgehend selbsterkl\"arend sein. + +Die beste Dokumentation ist der Code selbst. Gut geschriebener Code +mit ausdrucksstarken Variablen- und Funktionsnamen ben\"otigt keine +Kommentare, um den Zweck einzelner Zeilen zu erkl\"aren. z.B. ist\\ +\code{ x = x + 2; \% add two to x}\\ +ein v\"ollig unn\"otiger Kommentar. \begin{important} \begin{itemize} - \item Kommentare sind gut und wichtig aber: Sie m\"ussen richtig + \item Kommentare sollen die Absicht eines Programmabschnitts beschreiben. + \item Kommentare sind gut und wichtig --- sie m\"ussen aber richtig sein! - \item Ein Kommentar, der l\"ugt, ist schlimmer als gar kein Kommentar! - \item Kommentare m\"ussen gepflegt werden, sonst sind sie mehr als - wertlos! + \item Ein falscher Kommentar ist schlimmer als gar kein Kommentar! + \item Kommentare m\"ussen gepflegt werden, sonst sind sie wertlos! \end{itemize} \end{important} - + +\section{Dokumentation von Funktionen} + +Bei allen vordefinierten \matlab{} Funktionen findet sich am Anfang +eine Kommentarblock, der den Zweck der Funktion, die verschiedenen +M\"oglichkeiten des Funktionsaufrufs und die Argumente und +R\"uckgabewerte beschreibt. Auch in eingenen Funktionen sind diese +Kommentare sehr hilfreich. Siehe Listing~\ref{localfunctions} f\"ur +ein Beispiel einer gut Dokumentierten Funktion. + +\begin{important} + Funktionen m\"ussen unbedingt kommentiert werde! + \begin{itemize} + \item In wenigen Zeilen kurz den Zweck der Funktion beschreiben. + \item F\"ur jedes Funktionsargument die Bedeutung, der erwartete + Datentyp (Zahl, Vektor, Matrix, etc.), und eventuell die Einheit, + in der die Zahlen erwartet werden (z.B. Sekunden). + \item Ebenso m\"ussen die R\"uckgabewerte beschrieben werden. + \end{itemize} +\end{important} + \section{Auslagerung von Aufgaben in Funktionen} -Kommentare oder Leerzeilen werden benutzt um Abschnitte des Codes -abzutrennen und nazudeuten, dass ab da etwas inhaltlich anderes -gemacht wird. Wenn man im Zuge ist, eine solche inhaltliche Trennung -einzuf\"ugen muss man sich immer fragen, ob dieser Teil des Programms -nicht in eine eigene Funktion ausgelagert werden sollte. Fast immer -kann man das bejahen. +Kommentare oder Leerzeilen werden benutzt, um logische Abschnitte des +Codes abzutrennen und kurz zu erkl\"aren. Wenn eine +solche inhaltliche Trennung einzuf\"ugt wird, sollte man sich immer fragen, +ob dieser Teil des Programms nicht in eine eigene Funktion ausgelagert +werden sollte. Fast immer kann dies bejaht werden. -Abschnitte nicht auszulagern f\"uhrt zu sehr langen m-Files, die -leicht un\"ubersichtlich sind. Man nennt sie -\codeterm{Spaghetticode}. Es ist h\"ochste Zeit \"uber Auslagerung in -Funktionen nachzudenken. +Abschnitte nicht auszulagern f\"uhrt zu sehr langen +\codeterm{m-Files}, die leicht un\"ubersichtlich werden. Diese Art von +Code wird \codeterm{Spaghetticode} genannt. Es ist h\"ochste Zeit +\"uber Auslagerung in Funktionen nachzudenken. \begin{important} - Wann sollte man Programmteile in eigene Funktionen auslagern? + Wann sollten Programmteile in eigene Funktionen ausgelagert werden? \begin{itemize} - \item Wenn man innerhalb einer Funktion, eines Skripts mehr als zwei - Einr\"uckungsebenen hat. - \item Wenn man wiederholte Strukturen im Code hat. - \item Wenn man versucht ist, diese mit Copy and Paste zu erzeugen. + \item Wenn innerhalb einer Funktion oder eines Skripts mehr als zwei + Einr\"uckungsebenen gebraucht werden. + \item Wenn sich Strukturen im Code mehr als einmal wiederholten. + \item Wenn man versucht ist, wiederholte Strukturen mit Copy and Paste zu erzeugen. \end{itemize} \end{important} \subsection{Lokale Funktionen und geschachtelte Funktionen} -Eine M\"oglichkeit Spaghetticode zu vermeiden ist das Auslagern von -Funktionalit\"at in eigene Funktionen. Dies f\"uhrt dazu, dass man -eine F\"ulle von Dateien erzeugt, die die \"Ubersichtlichkeit nicht -unbedingt erh\"ohen. Wenn die auszulagernde Funktionalit\"at an vielen -Stellen ben\"otigt werden k\"onnte ist es dennoch sinnvol dies zu -tun. Wenn nicht, dann bietet \matlab{} die M\"oglichkeit sogenannte -\codeterm{lokale Funktionen} oder auch \codeterm{geschachtelte - Funktionen} (\enterm{nested functions}) zu erstellen (Listing -\ref{localfunctions} zeigt ein Beispiel f\"ur eine lokale Funktion). +Das Auslagern von Funktionalit\"at in eigene Funktionen f\"uhrt +dazu, dass eine F\"ulle von Dateien erzeugt wird, die die +\"Ubersichtlichkeit nicht unbedingt erh\"oht. Wenn die auszulagernde +Funktionalit\"at an vielen Stellen ben\"otigt wird ist es +dennoch sinnvol dies zu tun. Wenn nicht, dann bietet \matlab{} die +M\"oglichkeit sogenannte \codeterm{lokale Funktionen} oder auch +\codeterm{geschachtelte Funktionen} (\enterm{nested functions}) zu +erstellen. Listing \ref{localfunctions} zeigt ein Beispiel f\"ur eine +lokale Funktion. \lstinputlisting[label=localfunctions, caption={\codeterm{Lokale Funktionen} erh\"ohen die Lesbarkeit sind aber nur innerhalb der definierenden Datei verf\"ugbar.}]{calculate_sines.m} @@ -288,6 +335,7 @@ ist das anders. Diese werden innerhalb eines Funktionsk\"orpers ``Mutterfunktion'' zugreifen und diese auch ver\"andern. Folglich sollten sie nur mit Bedacht eingesetzt werden. + \section{Besonderheiten bei Skripten} Ein \"ahnliches Problem wurde schon bei der Einf\"uhrung der Skripte @@ -302,7 +350,7 @@ aussieht. \begin{important} Es empfiehlt sich zu Beginn eines Skriptes alle Variablen im \codeterm{Workspace} zu l\"oschen (\code{clear}). Meist ist auch - ein \code{close all} angebracht. + ein \code{close all}, um alle Figures zu schlie{\ss}en, angebracht. Am Ende eines Skriptes sollte der \codeterm{Workspace} mithilfe von \code{clear} wieder von all den Variablen ges\"aubert werden, die @@ -319,9 +367,9 @@ machen Programmiersprachen gibt es Traditionen und \"Ubereink\"unfte, diese sollten dann beachtet werden. Wiederholte Programmabschnitte sollten in Funktionen ausgelagert -werden. Wenn diese nich von globalem Interesse sind, kann man auch mit +werden. Wenn diese nich von globalem Interesse sind, kann mit \codeterm{lokalen} oder \codeterm{geschachtelten Funktionen} die -Lesbarkeit erh\"ohen. +\"Ubersichtlichkeit erh\"oht werden. \noindent Es lohnt sich auf den eigenen Programmierstil zu achten!\footnote{Literatur zum Programmierstil: z.B. Robert C. Martin: \textit{Clean Code: A Handbook of Agile Software Craftmanship}, Prentice Hall} From 87496d5f3d3ce2f27808b9ea4787f6d32aecdebf Mon Sep 17 00:00:00 2001 From: Jan Grewe Date: Sun, 15 Nov 2015 11:44:45 +0100 Subject: [PATCH 6/6] further typo fixes --- programmingstyle/code/calculate_sines.m | 6 +- programmingstyle/lecture/programmingstyle.tex | 65 ++++++++++--------- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/programmingstyle/code/calculate_sines.m b/programmingstyle/code/calculate_sines.m index cd69b76..05ad1ca 100644 --- a/programmingstyle/code/calculate_sines.m +++ b/programmingstyle/code/calculate_sines.m @@ -2,9 +2,9 @@ function sines = calculate_sines(x, amplitudes, frequencies) % Function calculates sinewaves with all combinations of % given amplitudes and frequencies. % Arguments: x, a vector of radiants for which the sine should be - % computed - % amplitudes, a vector of amplitudes - % frequencies, a vector of frequencies + % computed. + % amplitudes, a vector of amplitudes. + % frequencies, a vector of frequencies. % % Returns: a 3-D Matrix of sinewaves, 2nd dimension represents % the amplitudes, 3rd the frequencies. diff --git a/programmingstyle/lecture/programmingstyle.tex b/programmingstyle/lecture/programmingstyle.tex index 03be2a6..0807c9d 100644 --- a/programmingstyle/lecture/programmingstyle.tex +++ b/programmingstyle/lecture/programmingstyle.tex @@ -37,23 +37,24 @@ werden Programme benannt? Es hilft ungemein, wenn zusammengeh\"orige Skripte und Funktionen im gleichen Ordner auf der Festplatte zu finden sind. Es bietet sich also -an, f\"ur jede Analyse einen eigenen Ordner anzulegen und in diesem die -zugeh\"origen \codeterm{m-files} abzulegen. Auf eine tiefere +an, f\"ur jede Analyse einen eigenen Ordner anzulegen und in diesem +die zugeh\"origen \codeterm{m-files} abzulegen. Auf eine tiefere Schachtelung in weitere Unterordner kann in der Regel verzichtet werden. \matlab{} erzeugt einen ``MATLAB'' Ordner im eigenen -\file{Documents} (Linux) oder \file{Eigene Dokumente} (Windows) Ordner. Es -bietet sich an, diesen Ordner als Wurzelverzeichnis f\"ur eigene Arbeiten zu -verwenden. Nat\"urlich kann auch jeder andere Ort gew\"ahlen -werden. In dem Beispiel in \figref{fileorganizationfig} wird +\file{Documents} (Linux) oder \file{Eigene Dokumente} (Windows) +Ordner. Es bietet sich an, diesen Ordner als Wurzelverzeichnis f\"ur +eigene Arbeiten zu verwenden. Nat\"urlich kann auch jeder andere Ort +gew\"ahlt werden. In dem Beispiel in \figref{fileorganizationfig} wird innerhalb dieses Ordners f\"ur jedes Projekt ein eigener Unterordner -erstellt, in welchem widerum f\"ur jedes Problem, jede Analyse ein -weitere Unterodner erstellt wird. In diesen liegen sowohl die -ben\"otigten \codeterm{m-files} also auch die Resultate der Analyse (Abbildungen, -Daten-Dateien). Zu bemerken sind noch zwei weitere Dinge. Im Projektordner -existiert ein Skript (analysis.m), das dazu gedacht ist, alle Analysen -aufzurufen. Des Weiteren gitb es parallel zu den Projektordnern einen -\file{functions}-Ordner in dem Funktionen liegen, die in mehr als einem -Projekt oder einer Analyse gebraucht werden. +erstellt, in welchem wiederum f\"ur jedes Problem, jede Analyse ein +weiterer Unterodner erstellt wird. In diesen liegen sowohl die +ben\"otigten \codeterm{m-files} also auch die Resultate der Analyse +(Abbildungen, Daten-Dateien). Zu bemerken sind noch zwei weitere +Dinge. Im Projektordner existiert ein Skript (analysis.m), das dazu +gedacht ist, alle Analysen aufzurufen. Des Weiteren gibt es parallel +zu den Projektordnern einen \file{functions}-Ordner in dem Funktionen +liegen, die in mehr als einem Projekt oder einer Analyse gebraucht +werden. Beim Betrachten dieses Layouts f\"allt auf, dass es sehr wahrscheinlich ist, dass bestimmte Namen f\"ur Funktionen und Skripte @@ -65,7 +66,7 @@ aktuellen Ordner nach passenden Dateien sucht (mehr Information zum \begin{figure}[tp] \includegraphics[width=0.75\textwidth]{program_organization} - \titlecaption{\label{fileorganizationfig} M\"ogliche Oganisation von + \titlecaption{\label{fileorganizationfig} M\"ogliche Organisation von Programmcode im Dateisystem.}{ F\"ur jedes Projekt werden Unterordner f\"ur die einzelnen Analysen angelegt. Auf Ebene des Projektes k\"onnte es ein Skript (hier ``analysis.m'') geben, @@ -106,8 +107,8 @@ aktuellen Ordner nach passenden Dateien sucht (mehr Information zum \section{Namensgebung von Funktionen und Skripten} -\matlab{} sucht Funktionen und Skripte ausschlie{\ss}lich anhand der -Namen. Dabei spielt die Gro{\ss}- und Kleinschreibung eine Rolle. Das +\matlab{} sucht Funktionen und Skripte ausschlie{\ss}lich anhand des +Namens. Dabei spielt die Gro{\ss}- und Kleinschreibung eine Rolle. Das hei{\ss}t, dass die beiden Dateien \file{test\_funktion.m} und \file{Test\_funktion.m} zwei unterschiedliche Funktionen benennen k\"onnen. Diese Art der Variation des Namens ist nat\"urlich nicht @@ -127,9 +128,10 @@ aus dem Namen ein R\"uckschluss auf den Zweck ziehen lassen sollte. die beste Dokumentation. \end{important} -\matlab{} macht keine weiteren Vorgaben, was die Namen -angeht. Allerdings folgt die Benennung der vordefinierten Funktionen -gewissen Mustern: +In Namen verbietet \matlab{} verbietet Leerzeichen, Sonderzeichen und +Umlaute. Namen d\"urfen auch nicht mit Zahlen anfangen. Es mach f\"ur +die Namensgebung selbst keine weiteren Vorgaben. Allerdings folgt die +Benennung der in \matlab{} vordefinierten Funktionen gewissen Mustern: \begin{itemize} \item Namen werden immer klein geschrieben. \item Es werden gerne Abk\"urzungen eingesetzt (z.B. \code{xcorr} @@ -145,8 +147,7 @@ Anf\"ange zusammengesetzter Worte jeweils gro{\ss} geschrieben werden oder auch die Verwendung von Unterstrichen zur Trennung von Namenskomponenten. Eine Funktion, die die Anzahl von Aktionspotentialen bestimmt k\"onnte etwa \file{spikeCount.m} oder -\file{spike\_count.m} benannt werden. Leerzeichen, Sonderzeichen -oder Anf\"ange mit Zahlen sind in Namen nicht erlaubt. +\file{spike\_count.m} benannt werden. \section{Namensgebung von Variablen und Konstanten} @@ -183,9 +184,9 @@ Die Lesbarkeit von Programmen wird sehr durch den Codestil beeinflusst. Ein Programm, in dem z.B. Schleifenk\"orper nicht (oder zuf\"allig) einger\"uckt sind ist deutlich schwerer zu lesen und zu verstehen, als eines, in dem eine konsistente Einr\"uckung vorgenommen -wurde. Mit der Tastenkombination \keycode{Ctrl-I} % XXX Oder wie war das? XXX -kann ein markierter -Bereich im \matlab{} Editor automatisch richtig einger\"uckt werden. +wurde. Mit der Tastenkombination \keycode{Ctrl-I} (\keycode{Strg-I} +auf der deutschen Tastatur) kann ein markierter Bereich im \matlab{} +Editor automatisch richtig einger\"uckt werden. Sparsam und konsistent eingef\"ugte einzelne Leerzeilen sind hervorragend geeignet, um logische Abschnitte eines Programm zu @@ -220,6 +221,8 @@ end end \end{lstlisting} +\clearpage + \begin{lstlisting}[label=cleancode, caption={\"Ubersichtliche Implementation des Random-walk.}] num_runs = 10; max_steps = 1000; @@ -246,10 +249,10 @@ sind kurze Kommentare, die den Zweck und das Ziel eines Abschnitts im Programm erl\"autern (z.B. \code{\% compute mean firing rate over all trials}). -Zu viele Kommentare k\"onnen in der Entwicklungsphase eines Programms -sehr hilfreich sein, bl\"ahen aber den Code auf. Durch die Verwendung -guter Variablen- und Funktionsnamen sollten die meisten Zeilen sowieso -weitestgehend selbsterkl\"arend sein. +Viele und h\"aufige Kommentare k\"onnen in der Entwicklungsphase eines +Programms sehr hilfreich sein, bl\"ahen aber den Code auf. Durch die +Verwendung guter Variablen- und Funktionsnamen sollten die meisten +Zeilen sowieso weitestgehend selbsterkl\"arend sein. Die beste Dokumentation ist der Code selbst. Gut geschriebener Code mit ausdrucksstarken Variablen- und Funktionsnamen ben\"otigt keine @@ -317,7 +320,7 @@ Das Auslagern von Funktionalit\"at in eigene Funktionen f\"uhrt dazu, dass eine F\"ulle von Dateien erzeugt wird, die die \"Ubersichtlichkeit nicht unbedingt erh\"oht. Wenn die auszulagernde Funktionalit\"at an vielen Stellen ben\"otigt wird ist es -dennoch sinnvol dies zu tun. Wenn nicht, dann bietet \matlab{} die +dennoch sinnvoll dies zu tun. Wenn nicht, dann bietet \matlab{} die M\"oglichkeit sogenannte \codeterm{lokale Funktionen} oder auch \codeterm{geschachtelte Funktionen} (\enterm{nested functions}) zu erstellen. Listing \ref{localfunctions} zeigt ein Beispiel f\"ur eine @@ -367,7 +370,7 @@ machen Programmiersprachen gibt es Traditionen und \"Ubereink\"unfte, diese sollten dann beachtet werden. Wiederholte Programmabschnitte sollten in Funktionen ausgelagert -werden. Wenn diese nich von globalem Interesse sind, kann mit +werden. Wenn diese nicht von globalem Interesse sind, kann mit \codeterm{lokalen} oder \codeterm{geschachtelten Funktionen} die \"Ubersichtlichkeit erh\"oht werden.