\documentclass[aspectratio=169]{beamer}
\usetheme{metropolis}
\usepackage{lmodern}
\usepackage[czech]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{graphicx}
\usepackage{wrapfig}
\usepackage{color}
\usepackage{mathtools}
\usepackage{hyperref}
\usepackage{epstopdf}
\usepackage{amsmath}
\usepackage{minted}
\hypersetup{
    colorlinks,
    citecolor=black,
    filecolor=black,
    linkcolor=black,
    urlcolor=black
}
\usepackage{pdflscape}

\title{Kdy se kód čte jako kniha?}
\author{Kar(t)el Kočí}
\date{29.2.2020}

\begin{document}

\frame{\titlepage}

\begin{frame}[fragile]
	\frametitle{Je čitelnost důležitá?}
	Proč se vlastně zabývat čitelností kódu?
	\begin{itemize}
		\item protože kód píšeme jednou, ale čteme mnohem mnohem vícekrát
		\item protože čitelný kód je verifikovatelný kód
		\item protože čitelný kód je rozšiřitelný kód
		\item protože nikdo vám nepřispěje i když to je open-source pokud to nepřečte
		\item protože zkrátíte review proces
		\item protože vás budou mít rádi jak aktuální i budoucí kolegové
		\item protože vás bude mít rádo vaše budoucí já
	\end{itemize}
\end{frame}

\begin{frame}[fragile]
	\frametitle{Základní koncepty}
	\begin{itemize}
		\item Kód má nejenom fungovat, ale hlavně sdělovat myšlenku jak má fungovat
		\item Každý a i prázdný znak sděluje myšlenku
		\item Segmentace do celků
		\item Naznačování důležitosti pomocí pojmenování a omezení přístupu
		\item Exaktní a trefné pojmenování
		\item Dodržování stylu jazyka
	\end{itemize}
\end{frame}

\begin{frame}[fragile]
	\frametitle{Pojmenujte nepojmenované}
	\begin{minted}[frame=lines]{sh}
configure() {
	sed -i "s/@$1@/$2/g" "$3"
	dbg "Applied '$1=$2' on $3"
}
	\end{minted}
	\begin{minted}[frame=lines]{sh}
configure() {
	local variable="$1"
	local value="$2"
	local file="$3"
	sed -i "s/@$variable@/$value/g" "$file"
	dbg "Applied '$variable=$value' on $file"
}
	\end{minted}
\end{frame}

\begin{frame}[fragile]
	\frametitle{Nepřehánějte to ale s vatou}
	\begin{minted}[frame=lines]{sh}
get_home() {
	local user="$1"
	awk -F : -v "user=$user" '$1 == user { print $7 }' /etc/passwd
}
	\end{minted}
	\begin{minted}[frame=lines]{sh}
get_home() {
	awk -F : -v "user=$1" '$1 == user { print $7 }' /etc/passwd
}
	\end{minted}
\end{frame}

\begin{frame}[fragile]
	\frametitle{Nepřipravujte se na třetí světovou}
	\begin{minted}[frame=lines]{sh}
case "$operation" in
	add) prepare_add "$@" ;;
	rem|remove) prepare_rem "$@" ;;
	*) fail "Invalid mode specified:" "$mode" ;;
esac
echo "Beginning operation: $operation"
case "$operation" in
	add) do_add "$@" ;;
	rem|remove) do_rem "$@" ;;
	*) fail "Internal error: Unknown mode:" "$mode" ;;
esac
	\end{minted}
\end{frame}

\begin{frame}[fragile]
	\frametitle{Jmenujme obecně a exaktně}
	\begin{minted}[frame=lines]{c}
char *read_file(const char *path);
	\end{minted}
	je lepší než:
	\begin{minted}[frame=lines]{c}
char *slurp(const char *path);
	\end{minted}
	Protože Perl..
\end{frame}

\begin{frame}[fragile]
	\frametitle{Čtenář není kompilátor aneb char není int8\_t}
	\begin{minted}[frame=lines]{c}
char *receive_message(socket_t);
	\end{minted}
	\begin{minted}[frame=lines]{c}
void receive_message(socket_t, uint8_t **data, size_t *len);
	\end{minted}
\end{frame}

\begin{frame}[fragile]
	\frametitle{Pořadí funkcí}
	\begin{minted}[frame=lines]{sh}
_compile() {
	...
}
compile_tools() { _compile tools/compile toolchain/compile; }
compile_target() { _compile target/compile; }
compile_packages() { _compile package/compile; }
compile() {
	compile_tools
	compile_target
	compile_packages
}
	\end{minted}
	Protože knihu také nečteme od konce
\end{frame}

\begin{frame}[fragile]
	\frametitle{Segmenty je lepší pojmenovat}
	\begin{minted}[frame=lines]{sh}
##############################################
print_help() {
...
##############################################
operation_add() {
...
	\end{minted}
	\begin{minted}[frame=lines]{sh}
#Argument parsing ############################
print_help() {
...
# Operation ADD ##############################
operation_add() {
...
	\end{minted}
\end{frame}

\begin{frame}[fragile]
	\frametitle{Segmenty je lepší zapouzdřit}
	\begin{minted}[frame=lines]{C}
struct config *parse_args(int argc, const char **argv) {
	...
}

int main(int argc, const char **argv) {
	struct config *conf = parse_args(argc, argv);
	...
}
	\end{minted}
\end{frame}

\begin{frame}[fragile]
	\frametitle{Omezte definiční obor}
	\begin{minted}[frame=lines]{C}
char *scan_file(const char *fpath, const char *regexp) {
	FILE *file;
	regex_t preg;
	regcomp(&preg, regexp, 0);
	...
	file = fopen(fpath, "r");
	...
	fclose(file);
	return result;
}
	\end{minted}
\end{frame}

\begin{frame}[fragile]
	\frametitle{Nejlepší kód není třeba dokumentovat?}
	\begin{minted}[frame=lines]{C}
# Parse arguments
struct conf *parse_arguments(argc, argv);
# Load configuration
load_config(conf);
# Invoke appropriate handler
switch (conf->operation) {
	\end{minted}
	Ano, ale to neplatí o API!
	\begin{minted}[frame=lines]{C}
int pop_int(stack_t, int flags);
const char *pop_string(stack_t, int flags);
	\end{minted}
\end{frame}

\begin{frame}[fragile]
	\frametitle{Dokumentujte globální proměnné}
	\begin{minted}[frame=lines]{sh}
# Possible values:
# running: container is running
# stopped: container is stopped
# none: container does not exists
STATE="none"
update_state() { STATE="$(container status)"; }
access() {
	case "$STATE" in
		running) container sh ;;
		*) fail "Can't access container in state: $STATE" ;;
	esac
}
	\end{minted}
\end{frame}

\begin{frame}[fragile]
	\frametitle{Duplicitní dokumentace a změny}
	S několika úrovněmi dokumentace je snadné aby se neshodovali.
	\begin{itemize}
		\item Implementační na úrovni funkce
		\item Implementační na úrovni API
		\item Na rozhraní jazyků
		\item Vývojářská
		\item Uživatelská
	\end{itemize}

	Jak tomu předejít?
	\begin{itemize}
		\item Nechte si drobečky (This is user level function, don't forget to update user's docs)
		\item Dokumentujte na nejvyšší vrstvě a odkazujte se (This function is documented in API doc)
		\item Navažte testy na dokumentaci (Testy dokumentovaného chování)
		\item Kopejte kolegy do všech částí těla pokud dokumentaci ignorují
	\end{itemize}
\end{frame}

\begin{frame}[fragile]
	\frametitle{Deduplikujte kód}
	\begin{minted}[frame=lines]{c}
	uing8_t hight = bytes[i] >> 4;
	hexastring[2*i] = hight < 10 ? val + '0' : val + 'a';
	uing8_t low = bytes[i] & 0xf;
	hexastring[2*i + 1] = low < 10 ? low + '0' : low + 'a';
	\end{minted}
	\begin{minted}[frame=lines]{sh}
#define VAL2HEX(VAL) ((VAL) < 10 ? (VAL) + '0' : (VAL) + 'a')
	hexastring[2*i] = VAL2HEX(bytes[i] >> 4);
	hexastring[2*i + 1] = VAL2HEX(bytes[i] & 0xf);
#undef VAL2HEX
	\end{minted}
\end{frame}

\begin{frame}[fragile]
	\frametitle{Zalamujeme argumenty}
	\begin{minted}[frame=lines]{c}
struct wait_id id = event_run_util(events, result_callback, NULL,
		&result_data, 0, NULL, -1, -1, "cp", "-f", old, new,
		(const char *)NULL);
	\end{minted}
	\begin{minted}[frame=lines]{c}
struct wait_id id = run_util(events,
		result_callback, NULL, &result_data,
		0, NULL,
		-1, -1,
		"cp", "-f", old, new, (const char *)NULL);
	\end{minted}
\end{frame}

\begin{frame}[fragile]
	\frametitle{Použijme popisnější argumenty}
	\begin{minted}[frame=lines]{sh}
lxc launch images:alpine/3.11 myalpine -e -n default \
	-p default -s default
	\end{minted}
	\begin{minted}[frame=lines]{sh}
lxc launch images:alpine/3.11 myalpine \
	--ephemeral \
	--network default \
	--profile default \
	--storage default
	\end{minted}
\end{frame}

\begin{frame}[fragile]
	\frametitle{Magické konstanty a jejich konstantnost}
	\begin{minted}[frame=lines]{c}
#define TOKEN_BITS 64
#define TOKEN_BYTES 8
bool verify(uint8_t *token) {
	uint64_t value = *token;
	return value % 42;
	\end{minted}

	\begin{minted}[frame=lines]{c}
#define TOKEN_BYTES 8
#define TOKEN_BITS (TOKEN_BYTES * 8)
#if TOKEN_BYTES != 8
#error Function verify() is implemented to work only with 8 bytes tokens
#endif
bool verify(uint8_t *token) {
	\end{minted}
\end{frame}


\begin{frame}
	\Large A jaké máte tipy pro zlepšení čitelnosti kódu vy?

	\Large Děkuji za pozornost.

	\url{git.cynerd.cz}
\end{frame}

\end{document}
