From b2102c05f88a5d7479575f1259d2a0850c46d832 Mon Sep 17 00:00:00 2001 From: dakkar Date: Tue, 9 Sep 2008 12:52:53 +0000 Subject: best practices git-svn-id: svn://luxion/repos/best-practices@369 fcb26f47-9200-0410-b104-b98ab5b095f3 --- pbp.content.tex | 293 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pbp.handout.tex | 4 + pbp.slides.tex | 2 + 3 files changed, 299 insertions(+) create mode 100644 pbp.content.tex create mode 100644 pbp.handout.tex create mode 100644 pbp.slides.tex diff --git a/pbp.content.tex b/pbp.content.tex new file mode 100644 index 0000000..e6c9da3 --- /dev/null +++ b/pbp.content.tex @@ -0,0 +1,293 @@ +\usepackage[latin1]{inputenc} +\usepackage[italian]{babel} +\usepackage[T1]{fontenc} +\usepackage{times} +\usepackage{colortbl} +\usepackage{textcomp} +\usepackage{listings} +\usepackage{tikz} + +\colorlet{p}{black!20} + +\lstset{extendedchars,numbers=left,numberstyle=\tiny ,numbersep=5pt,language=Perl,showspaces=false,frame=single,framerule=0pt,backgroundcolor=\color{p},basicstyle=\small\ttfamily ,upquote=true,keepspaces=true} + +\mode +{ +\usetheme[hideothersubsections]{Goettingen} +%\usecolortheme{beaver} +\usecolortheme{rose} +\setbeamertemplate{sections/subsections in toc}[ball] +} +\mode
{\usepackage{fullpage}} +\mode{\setbeamercolor{background canvas}{bg=black!5}} + +\newcommand{\Perl}{\textsf{Perl}} +\newcommand{\perl}{\texttt{perl}} + +\title{\Perl\ --- best practices} +\author[perl.it]{perl.it \url{http://www.perl.it/}} +\date[IPW2008]{Italian Perl Workshop 2008} + +\begin{document} + +\begin{frame} +\titlepage +\end{frame} + +\begin{frame}\frametitle{Grazie a Damian Conway} +Questo intervento è ispirato a ``Perl Best Practices'', di Damian Conway, edizioni O'Reilly +\end{frame} + +\begin{frame}\frametitle{Obiettivi} +\begin{itemize} +\item Robustezza +\item Efficienza +\item Manutenibilità +\end{itemize} +\end{frame} + +\begin{frame}\frametitle{Per gli impazienti} +{\huge Scrivi sempre codice come se la persona che lo deve mantenere fosse un violento psicopatico che sa dove abiti} +\end{frame} + +\begin{frame}[fragile]\frametitle{Spaziatura} +\begin{lstlisting} +my@result=(1,2,3); +for my$result(@results){print_sep;print($result)} +while(my_func $param,$param2){ +my$stuff=$x->{$keys[($x-$y)/2]}; +if($stuff<$target){$x=$y}else{$y=$x} +\end{lstlisting} +\end{frame} + +\begin{frame}[fragile]\frametitle{Spaziatura} +\begin{lstlisting} +my @result = ( + 1, + 2, + 3, +); + +for my $result (@results) { + print_sep(); + print $result; +} + +while (my_func($param,$param2)) { + my $stuff = $x->{ $keys[ ($x-$y)/2 ] }; + if ($stuff < $target) { + $x = $y; + } + else { + $y = $x; + } +} +\end{lstlisting} +\end{frame} + +\begin{frame}[fragile]\frametitle{Nomi} +\begin{itemize} +\item date nomi comprensibili e non ambigui (\lstinline|$totale_finora|, \lstinline|$utente_attuale|, \lstinline|&è_valido|) +\item non abbiate paura dei nomi lunghi +\item separate con \lstinline|_| e non CamelCase +\item hash al genitivo singolare, array al nominativo plurale +\item non abbreviate troppo +\item cominciate i ``nomi privati'' con \lstinline|_| +\end{itemize} +\end{frame} + +\begin{frame}[fragile]\frametitle{Valori} +\begin{itemize} +\item usate \lstinline|'virgolette semplici'| tranne quando \lstinline|"dovete $interpolare\n"| %$ +\item non abbiate paura di \lstinline|q()| e \lstinline|qq()| +\item in particolare, \lstinline|q[]|, \lstinline|q[ ]|, \lstinline|q[,]|, \lstinline|qq[\t]| +\item usate ``here-doc'' per blocchi di testo +\end{itemize} +\end{frame} + +\begin{frame}[fragile]\frametitle{Variabili} +\begin{itemize} +\item dichiarate sempre le variabili con \lstinline|my| +\item non usate \lstinline|local| se non sapete \emph{esattamente} perché +\item non toccate le variabili globali speciali (in particolare \lstinline|@ARGV|) +\item \lstinline|use English '-no_match_vars'| +\item \emph{usate} \lstinline|local| su \lstinline|$_| e altre variabili ``punteggiatura'' %$ +\item \lstinline|$array[-1]|, non \lstinline|$array[$#array]| %$ +\end{itemize} +\end{frame} + +\begin{frame}[fragile]\frametitle{Controlli di flusso} +\begin{itemize} +\item usate \lstinline|if| posposto solo per semplici istruzioni, tipicamente controlli nei cicli: \lstinline|next CICLO if !mi_serve($elemento);| %$ +\item usate ancora meno gli altri controlli posposti (\lstinline|unless|, \lstinline|while|, \lstinline|for|) +\item evitate il \lstinline|for(init;cond;step)| alla C +\item date sempre un nome alla variabile di iterazione: \lstinline|for my $persona_attuale (@persone) { ... }| %$ +\item usate \lstinline|map| per trasformare le liste (ma non in-place!) +\item usate \lstinline|grep| e \lstinline|List::Util::first| per estrarre elementi +\item usate \emph{dispatch tables} invece che cascate di \lstinline|if| +\end{itemize} +\end{frame} + +\begin{frame}[fragile]\frametitle{Dispatch tables} +\begin{lstlisting} +{ +my %comandi=( + start => \&avvia_processo_di_calcolo, + stop => \&termina_processo_di_calcolo, + status => \&esamina_stato_processo, +); + +sub esegui_comando { + my ($comando)=@_; + if (exists $comandi{$comando}) { + $comandi{$comando}->(); + } + else { + carp qq{Comando "$comando" ignoto.\n}; + } +} +} +\end{lstlisting} +\end{frame} + +\begin{frame}[fragile]\frametitle{Controlli di flusso (2)} +\begin{itemize} +\item usate i comandi di controllo cicli (\lstinline|next|, \lstinline|last|, \lstinline|continue|, \lstinline|redo|) +\item etichettate sempre i cicli in cui usate quei comandi: + \begin{lstlisting} + CLIENTE: + while (my $cliente_corrente = + $clienti->next()) { + next CLIENTE + if ! $cliente_corrente->attivo; + usa_cliente($cliente_corrente); + } + \end{lstlisting} +\end{itemize} +\end{frame} + +\begin{frame}[fragile]\frametitle{Documentazione e commenti} +\begin{itemize} +\item usate POD per la documentazione utente +\item usate i commenti per la documentazione interna +\item spiegate gli algoritmi +\item annotate i trucchi e le finezze +\item ``incremento il contatore'' non è documentazione +\end{itemize} +\end{frame} + +\begin{frame}[fragile]\frametitle{Funzioni predefinite} +\begin{itemize} +\item studiate la ``Orcish manoeuvre'' e la ``Schwartzian transform'' +\item \lstinline|reverse| è molto utile (\lstinline|for my $countdown (reverse 0..100) { ... }|) %$ +\item spacchettare dati: \begin{itemize} + \item \lstinline|unpack| se lunghezza fissa + \item \lstinline|split| se lunghezza variabile + \item \lstinline|Text::CSV_XS| se più complicati + \end{itemize} +\item è quasi sempre possibile evitare \lstinline|eval 'stringa'| +\item usate \lstinline|glob('*')|, non \lstinline|<*>| +\item studiate e usate \lstinline|Scalar::Util|, \lstinline|List::Util|, \lstinline|List::MoreUtils| +\end{itemize} +\end{frame} + +\begin{frame}[fragile]\frametitle{Subroutine} +\begin{itemize} +\item \lstinline|fai_qualcosa(@argomenti)|, non \lstinline|&fai_qualcosa @argomenti| +\item per prima cosa, spacchettate \lstinline|@_| +\item se la sub prende più di un paio di argomenti, passateli per hash +\item attenti al contesto nei vostri \lstinline|return| +\item \lstinline|return;| garantisce che il risultato sia falso, anche in contesto lista +\item mettete sempre un qualche \lstinline|return| alla fine delle sub +\end{itemize} +\end{frame} + +\begin{frame}[fragile]\frametitle{I/O} +\begin{itemize} +\item \lstinline|open my $fh,'<',$nomefile| \lstinline|or croak qq{Impossibile aprire "$nomefile": $!};| invece che \lstinline|open FH,$nomefile;| %$ +\item<2> filehandle lessicali +\item<2> \lstinline|open| a 3 argomenti +\item<2> controllate sempre il valore di ritorno +\end{itemize} +\end{frame} + +\begin{frame}[fragile]\frametitle{I/O (2)} +\begin{itemize} +\item \lstinline|while (my $line=<$fh>)|, non \lstinline|for| +\item evitate il più possibile di caricare l'intero file in memoria +\item se proprio dovete, usate \lstinline|File::Slurp| +\item \lstinline|print {$logfile} $messaggio|, non \lstinline|print $logfile $messaggio| +\item studiate \lstinline|IO::Handle| e famiglia +\end{itemize} +\end{frame} + +\begin{frame}[fragile]\frametitle{References} +\begin{itemize} +\item non usate \emph{mai} reference simboliche (\lstinline|"${nome}_tipo"=5|) %$ +\item \lstinline|$list_ref->[$indice]|, non \lstinline|$$list_ref[$indice]| %$ +\item \lstinline|@{$hoa{$chiave}}|, non \lstinline|@$hoa{$chiave}| +\end{itemize} +\end{frame} + +\begin{frame}[fragile]\frametitle{Espressioni regolari} +\begin{itemize} +\item usate sempre \lstinline|/xms| +\item \lstinline|\A| e \lstinline|\z| per inizio e fine \emph{stringa} +\item \lstinline|^| e \lstinline|$| per inizio e fine \emph{riga} %$ +\item \lstinline|m{...}smx|, non \lstinline|/.../| +\item \lstinline|\p{Uppercase}\p{Alphabetic}|, non \lstinline|[A-Z][a-zA-Z]| +\item attenti alla differenza tra \lstinline|.*| e \lstinline|.*?| +\item \lstinline|my ($nome,$valore) =| \lstinline|($linea=~m{\A (\w+) \s*=\s* (.*?) \z}smx)|, non \lstinline|$linea=~m{^(\w+)\s*=\s*(.*?)$};| \lstinline|my ($nome,$valore)=($1,$2)| %$ +\item studiate \lstinline|Regexp::Common| +\end{itemize} +\end{frame} + +\begin{frame}[fragile]\frametitle{Eccezioni} +\begin{itemize} +\item lanciate eccezioni, non impostate flag o valori di ritorno +\item studiate \lstinline|autodie| +\item studiate \lstinline|Exception::Class| o simili +\item usate \lstinline|Carp| +\end{itemize} +\end{frame} + +\begin{frame}[fragile]\frametitle{Oggetti} +\begin{itemize} +\item usate \lstinline|Moose| +\item non usate oggetti dove non servono +\item usateli \emph{sempre} dove servono +\item \lstinline|$oggetto->metodo(@args)|, non \lstinline|metodo $oggetto @args| +\item evitate \lstinline|AUTOLOAD| +\end{itemize} +\end{frame} + +\begin{frame}[fragile]\frametitle{Moduli} +\begin{itemize} +\item non ripetete mai il codice: fattorizzate \emph{sempre} +\item nascondete le implementazioni dentro moduli +\item attenti ai nomi che esportate +\item evitate di esporre variabili o altro stato globale +\item non scrivete moduli: usate quelli in CPAN +\end{itemize} +\end{frame} + +\begin{frame}[fragile]\frametitle{Varie} +\begin{itemize} +\item scrivete test, e usateli +\item usate un debugger +\item usate un sistema di controllo delle versioni +\item non fate ottimizzazioni alla cieca -- misurate i tempi (\lstinline|Benchmark|, \lstinline|Devel::NYTProf|) +\item non fate ottimizzazioni alla cieca -- misurate l'occupazione di memoria (\lstinline|Devel::Size|) +\end{itemize} +\end{frame} + +\end{document} + +% - +% Local Variables: +% mode: outline-minor +% outline-regexp: "\\(. -+ \\)\\|\\\\part\\|\\\\section\\|\\\\subsection" +% coding: iso-8859-1 +% tex-command: "pdflatex" +% tex-main-file: "pbp.slides.tex" +% End: diff --git a/pbp.handout.tex b/pbp.handout.tex new file mode 100644 index 0000000..52de307 --- /dev/null +++ b/pbp.handout.tex @@ -0,0 +1,4 @@ +\documentclass[handout,xcolor=table]{beamer} +\usepackage{pgfpages} +\pgfpagesuselayout{2 on 1}[a4paper,border shrink=5mm] +\input{pbp.content.tex} diff --git a/pbp.slides.tex b/pbp.slides.tex new file mode 100644 index 0000000..33f800c --- /dev/null +++ b/pbp.slides.tex @@ -0,0 +1,2 @@ +\documentclass[xcolor=table]{beamer} +\input{pbp.content.tex} -- cgit v1.2.3