From 402a7bae6eff6a02c621b3d345debd3b38ad8b92 Mon Sep 17 00:00:00 2001 From: Thomas Lambert <t.lambert@uliege.be> Date: Tue, 10 May 2022 11:04:00 +0200 Subject: [PATCH] add(sw dev1): details, examples and ccl --- .../good_practices_slides.tex | 90 +++++++++---- workshops/software_development/latexmkrc | 2 +- .../sections/documentation.tex | 58 +++++--- .../software_development/sections/errors.tex | 3 +- .../software_development/sections/layout.tex | 4 +- .../sections/modularity.tex | 34 +++++ .../sections/naming_conventions.tex | 25 ++-- .../sections/organization.tex | 126 ++++++++++++++++-- 8 files changed, 267 insertions(+), 75 deletions(-) diff --git a/workshops/software_development/good_practices_slides.tex b/workshops/software_development/good_practices_slides.tex index 9703bf2..cbd5808 100644 --- a/workshops/software_development/good_practices_slides.tex +++ b/workshops/software_development/good_practices_slides.tex @@ -200,46 +200,80 @@ sectionstyle=style2 % Resources %\input{sections/resources.tex} -% Bibliography -\begin{frame}[allowframebreaks]{References} - \nocite{*} % Display all references regardless of if they were cited - \printbibliography[heading=none] -\end{frame} - -%% ============================================================================= -%% END -%% ============================================================================= - -\section*{Next session} -\label{sec:next} +\section{Conclusion} +\label{sec:ccl} % ====================================== -\subsection{Contents (maybe)} -\label{sec:next:contents} +\subsection{Key take-away} +\label{sec:ccl:takeaway} \begin{frame}{\insertsectionhead} \framesubtitle{\insertsubsectionhead} - \begin{enumerate} - \item Code quality metrics - \begin{itemize} - \item Nesting levels, cyclomatic complexity, function paths, etc. - \end{itemize} - \item Code versioning (\lst{git}) + \begin{itemize} + \item[\greencheck] Use meaningful names \begin{itemize} - \item Concept - \item \lst{git} in local - \item \lst{git} with a remote (Gitlab) + \item Different naming schemes for different elements \end{itemize} - \item Improve robustness through extensive testing + \pause + \item[\greencheck] \textbf{Use functions} \begin{itemize} - \item Unit testing + \item Don't repeat yourself \end{itemize} - \item Automation of tasks (tests, build, deployment) + \pause + \item[\greencheck] Document properly \begin{itemize} - \item Intro to CI/CD pipelines with Gitlab + \item Comment header for functions + \item In-line comments + \item (Readme if necessary) \end{itemize} - \end{enumerate} + \pause + \item[\greencheck] Good layout = easier to understand + \pause + \item[\greencheck] Add checks and early error detection + \end{itemize} +\end{frame} + +% Bibliography +\begin{frame}[allowframebreaks]{References} + \nocite{*} % Display all references regardless of if they were cited + \printbibliography[heading=none] \end{frame} + +%% ============================================================================= +%% END +%% ============================================================================= + +%\section*{Next session} +%\label{sec:next} +% +%% ====================================== +%\subsection{Contents (maybe)} +%\label{sec:next:contents} +% +%\begin{frame}{\insertsectionhead} +% \framesubtitle{\insertsubsectionhead} +% \begin{enumerate} +% \item Code quality metrics +% \begin{itemize} +% \item Nesting levels, cyclomatic complexity, function paths, etc. +% \end{itemize} +% \item Code versioning (\lst{git}) +% \begin{itemize} +% \item Concept +% \item \lst{git} in local +% \item \lst{git} with a remote (Gitlab) +% \end{itemize} +% \item Improve robustness through extensive testing +% \begin{itemize} +% \item Unit testing +% \end{itemize} +% \item Automation of tasks (tests, build, deployment) +% \begin{itemize} +% \item Intro to CI/CD pipelines with Gitlab +% \end{itemize} +% \end{enumerate} +%\end{frame} + \end{document} diff --git a/workshops/software_development/latexmkrc b/workshops/software_development/latexmkrc index 593e68f..c523ec4 100644 --- a/workshops/software_development/latexmkrc +++ b/workshops/software_development/latexmkrc @@ -11,4 +11,4 @@ $pdf_mode = 4; # 1: use pdflatex, 4: use lualatex, 5 use xelatex $bibtex_use = 2; # Additional files to clean -$clean_ext = 'synctex.gz synctex.gz(busy) run.xml tex.bak bcf fdb_latexmk run tdo %R-blx.bib nav snm' +$clean_ext = 'synctex.gz synctex.gz(busy) run.xml tex.bak bcf fdb_latexmk run tdo %R-blx.bib nav snm vrb' diff --git a/workshops/software_development/sections/documentation.tex b/workshops/software_development/sections/documentation.tex index 238e7ba..d02efeb 100644 --- a/workshops/software_development/sections/documentation.tex +++ b/workshops/software_development/sections/documentation.tex @@ -10,9 +10,10 @@ \begin{itemize} \item Sadly, documentation is often overlooked \item Good practice: \textbf{documentation as you code} + \pause \item Ideal practice: Handbook-first \begin{itemize} - \item For \textit{big} projects + \item More suited for \textit{big} projects \item Clarifies the implementation and the structure of the code \item Speeds-up the development \item Ensures the documentation is written @@ -25,20 +26,27 @@ \item \alert{Code comments}, \lst{Readme} file, User/developer manual, Wiki, ... \end{itemize} \end{itemize} - \note[item]{See \textit{handbook-first} approach for interesting blog posts - and more details.} - \note[item]{Making the documentation transparent \textit{before} dissemination - of the code allows it to be treated as a \textit{single source of thrust}. All + + \note[item]{The more a project grows, the more \textbf{vital} the + documentation becomes. At the same time, beginning the documentation of an + already established project is a massive and complicated task.} + + \note[item]{For students projects and reports, documenting as you go is + probably the simplest and most efficient way to go.} + + \note[item]{The handbook-first approach is particularity interesting for very + large codes, major projects (thesis) or big collaborative efforts. It allows + the documentation to be treated as a \textit{single source of thrust}. All contributors will look into the documentation to understand what the - software does and the reasons it was implemented that way. - No need to look into various chat apps, mails or to rely on our partial - understanding.} + software does and the reasons it was implemented that way. No need to look + into various chat apps, mails or to rely on our partial understanding. This + approach is however hard to implement properly, as it relies on all + developers to follow the rules.} + \note[item]{An excellent documentation increases tremendously the efficiency on collaborative projects. It completely removes back-and-forth communication and misinterpretations based on poor code understanding.} - \note[item]{The more a project grows, the more \textbf{vital} the - documentation becomes. At the same time, beginning the documentation of an - already established project is a massive and complicated task.} + \end{frame} \begin{frame}{\insertsectionhead} @@ -78,12 +86,12 @@ language=matlab, frame=single, ] -function dyn_visc = viscosutherland(temp) -% VISCOSUTHERLAND Sutherland's law for dynamic viscosity +function dynVisc = visco_sutherland(temp) +% VISCO_SUTHERLAND Sutherland's law for dynamic viscosity % Determine the dynamic viscosity of ideal air % using only the temperatrue. % Usage: -% mu = VISCOSUTHERLAND(temp) +% mu = VISCO_SUTHERLAND(temp) \end{lstlisting} \end{itemize} @@ -108,8 +116,8 @@ function dyn_visc = viscosutherland(temp) frame=single, ] % Flip camberline, so the first element is the trailing edge -xc = fliplr(coord(:, 1)); % [m] -yc = fliplr(coord(:, 2)); % [m] +camberX = fliplr(coord(:, 1)); % [m] +camberY = fliplr(coord(:, 2)); % [m] \end{lstlisting} \pause \item Comments can also be used to separate clearly parts of the code (see @@ -121,8 +129,11 @@ yc = fliplr(coord(:, 2)); % [m] frame=single, ] z = x + y % add y to x and put it in z +thrust = 100; % thrust \end{lstlisting} \end{itemize} + \note[item]{Meaningful variable names are self-documenting.} + \note[item]{Add units alongside the variables to avoid silly mistakes!\\ \textit{On September 23, 1999 NASA lost the \$125 million Mars Climate Orbiter spacecraft after a 286-day journey to Mars. Miscalculations due to the use @@ -148,14 +159,21 @@ z = x + y % add y to x and put it in z \item Add any relevant information (references, sources, links, etc.) \item Legal stuff (copyrights, etc.) \end{itemize} + + \note[item]{When the \readme gets too long or too complicated, consider moving + to a "full" documentation (see next slides).} + \note[item]{If your project is on Github, Gitlab, etc., the \readme is the front page of your project. The very first thing a new user will see. Keep that in mind!} + \note[item]{The good practice is to use markdown (a very basic markup language) to format the \readme. This allows the website to format the page properly and display its content in a clear way.} + \note[item]{If the \readme is to be read online, use images or badges to highlight the important features.} + \note[item]{Examples: \begin{itemize} \item \url{https://gitlab.com/thlamb/beamertheme-trigon} @@ -176,10 +194,12 @@ z = x + y % add y to x and put it in z \begin{frame}{\insertsectionhead} \framesubtitle{\insertsubsectionhead} - More suited for very big projects. Usually multiple pages pdf, or an online - wiki (or both). + More suited for \textit{very big} projects. + \begin{itemize} + \item Usually multiple pages pdf, or an online wiki (or both). + \end{itemize} \vfill - + \pause \begin{columns}[T,onlytextwidth] \column{0.45\textwidth} diff --git a/workshops/software_development/sections/errors.tex b/workshops/software_development/sections/errors.tex index 9dc7e33..3a0c15a 100644 --- a/workshops/software_development/sections/errors.tex +++ b/workshops/software_development/sections/errors.tex @@ -21,7 +21,7 @@ validateattributes(alpha, {'numeric'}, {'real', '2d', 'increasing'}, ... mfilename(), 'alpha', 1); -% Ensures that x is either 'string1' or 'string2' +% Ensures that x is either 'student' or 'professor' x = validatestring(x, {'student','professor'}, mfilename())); \end{lstlisting} \end{itemize} @@ -73,6 +73,7 @@ x = validatestring(x, {'student','professor'}, mfilename())); \item if $\mathcal{M} > 0.75$ the flow is no longer incompressible and the equations may be invalid \end{itemize} + \pause \item Write some simple functions that you call periodically in the code to detect issues early on \end{itemize} diff --git a/workshops/software_development/sections/layout.tex b/workshops/software_development/sections/layout.tex index 93715b0..a34f362 100644 --- a/workshops/software_development/sections/layout.tex +++ b/workshops/software_development/sections/layout.tex @@ -13,7 +13,7 @@ \begin{itemize} \item \textbf{Never use TAB, always spaces!} \begin{itemize} - \item Standard is 4 spaces as indentation, 2 if you need conciseness + \item Standard is 4 spaces as indentation \item Tweak editor parameters to replace tabs by spaces \end{itemize} \item Sometime enforced by language (Python, etc.) @@ -29,6 +29,8 @@ \note[item]{Layout also involves deciding between double or single quotes (\lst{"}, \lst{'}).\\ \faExclamationTriangle \, in \matlab they are different things!} + \note[item]{When codes are verbose or have many nested levels, indentations are + sometimes set to 2 spaces to keep the code concise.} \note[item]{You can also decide if you return to the line before opening a parenthesis, etc.} \end{frame} diff --git a/workshops/software_development/sections/modularity.tex b/workshops/software_development/sections/modularity.tex index c542386..1581bd4 100644 --- a/workshops/software_development/sections/modularity.tex +++ b/workshops/software_development/sections/modularity.tex @@ -106,6 +106,7 @@ \item Separate file for functions shared across multiple functions/scripts \end{itemize} + \pause \item Main functions should have a good header comment, local functions should be self explanatory (one line description is enough) \item More abstraction = easier to reuse @@ -181,3 +182,36 @@ projects! \end{frame} + +% ====================================== +\subsection{Matlab packages} +\label{sec:mod:matlab_package} + +\begin{frame}[fragile]{\insertsectionhead} + \framesubtitle{\insertsubsectionhead} + In \matlab, libraries are called \emph{packages}. + \begin{itemize} + \item identified by a \lst{+} before the directory name + \item must be explicitly imported in your script + \begin{lstlisting}[ + language=matlab, + frame=single, + ] +% Import all functions in the package +import mypackage.* +% Import a specific function in the package +import mypackage.myfunction +% Directly call the function without importing +d = mypackage.myfunction(a,b,c); + \end{lstlisting} + \end{itemize} + \note[item]{Importing functions allow you to use them directly without + re-specifying the package name. In this case, it means you can use + myfunction(a,b,c) as if it were a normal function.} + \note[item]{The real advantage of package is that it ensures the functions + name are not conflicting with whatever function you have. If a package has a + function called \lst{plot_data} and your code happens to also have a different + \lst{plot_data}, you can easily pick which one to use without having to modify + the functions.} +\end{frame} + diff --git a/workshops/software_development/sections/naming_conventions.tex b/workshops/software_development/sections/naming_conventions.tex index 896a92a..381fb8c 100644 --- a/workshops/software_development/sections/naming_conventions.tex +++ b/workshops/software_development/sections/naming_conventions.tex @@ -7,7 +7,7 @@ \begin{frame}{\insertsectionhead} \framesubtitle{\insertsubsectionhead} List of rules to name and write the different elements (variables, functions, - constants, etc.) of the code. + files, etc.) of the code. \vfill Advantages: @@ -28,11 +28,11 @@ \framesubtitle{\insertsubsectionhead - Naming schemes} Common naming schemes are: \begin{itemize} - \item \lst{allsmallcaps} (also called flatcase) - \item \lst{ALLCAPS} (also called UPPERFLATCASE) - \item \lst{PascalCase} + \item \lst{flatcase} \item \lst{camelCase} + \item \lst{PascalCase} \item \lst{snake\_case} + \item \lst{UPPERFLATCASE} \item \lst{SCREAMING\_SNAKE\_CASE} \end{itemize} @@ -71,7 +71,7 @@ \subsection{Variables} \begin{frame}[fragile]{\insertsectionhead} \framesubtitle{\insertsubsectionhead} - Variables are in general in \lst{camelCase} or \lst{snake_case}. + Variables are in general in \lst{camelCase} \begin{itemize} \item Longer name if large scope (used in all the code)\\ \item Shorter name for small scope (indices, iterators)\\ @@ -97,7 +97,7 @@ end \begin{itemize} \item Avoid confusing names (singular/plural of the same word)\\ except if lists and arrays (special case): \lst{for point in points} - \item Prefix \lst{n} for number, \lst{i,j,k} for iterators\\ + \item Prefix \lst{n} for number; \lst{i,j,k} for iterators\\ \lst{nBlades}, \lst{nElements}, \lst{iFiles}, \lst{iSpeed} \item Avoid negative booleans (confusion when negating) \begin{itemize} @@ -109,8 +109,8 @@ end \item Avoid using 'special' names that would conflict with an built-in functions \begin{itemize} - \item[\greencheck] \lst{myMean}, \lst{coeffDrag}, \lst{mySum} \item[\redcross] \lst{mean}, \lst{cd}, \lst{sum} + \item[\greencheck] \lst{myMean}, \lst{coeffDrag}, \lst{mySum} \end{itemize} \end{itemize} @@ -137,7 +137,7 @@ end \begin{itemize} \item Should be clearly identified at the beginning of the script/function \item Should never be redefined later on in the code - \item Only think in \lst{SCREAMING_SNAKE_CASE} + \item Only thing in \lst{SCREAMING_SNAKE_CASE} \end{itemize} \column{0.4\textwidth} @@ -196,8 +196,7 @@ DEFAULT_SOLVER = 'linear' \subsection{Functions} \begin{frame}[fragile]{\insertsectionhead} \framesubtitle{\insertsubsectionhead} - Functions are in general in \lst{allsmallcaps}, \lst{snake_case} or - \lst{camelCase}. + Functions are in general \lst{snake_case}. \vfill \begin{columns}[onlytextwidth] \column{0.55\textwidth} @@ -215,13 +214,13 @@ DEFAULT_SOLVER = 'linear' language=python, frame=single, ] -def calcdrag(aoa): +def calc_drag(aoa): ... -def plotpolar(aoa, coeff): +def plot_polar(aoa, coeff): ... -def mean(vect): +def my_mean(vect): ... \end{lstlisting} diff --git a/workshops/software_development/sections/organization.tex b/workshops/software_development/sections/organization.tex index 50c57f9..e130047 100644 --- a/workshops/software_development/sections/organization.tex +++ b/workshops/software_development/sections/organization.tex @@ -39,18 +39,120 @@ \begin{frame}{\insertsectionhead} \framesubtitle{\insertsubsectionhead - Matlab} - \dirtree{% - .1 . - .2 src. - .3 main.m. - .3 utils. - .4 plotresult.m. - .4 sanitizeinput.m. - .3 lib. - .4 +af\_tools. - .2 tests. - .2 README.md. - } + Typical project tree + \begin{columns}[onlytextwidth] + \column{0.4\textwidth} + \dirtree{% + .1 . + .2 data. + .2 doc. + .2 results. + .2 src. + .2 tests. + .2 LICENSE. + .2 Readme.md. + .2 \ldots. + } + + \column{0.6\textwidth} + \begin{itemize} + \item \lst{src} folder is where the code is + \item \lst{doc} folder only for big projects + \item \lst{bin} folder if compiled binaries + \item \lst{scripts} folder if additional scripts + \end{itemize} + \end{columns} + +\end{frame} + +\begin{frame}{\insertsectionhead} + \framesubtitle{\insertsubsectionhead - Matlab} + \begin{columns}[onlytextwidth] + \column{0.45\textwidth} + \dirtree{% + .1 data. + .2 5deg. + .3 20220510-WT-10mps.csv. + .3 20220510-WT-20mps.csv. + .2 10deg. + .3 20220514-WT-10mps.csv. + .3 20220514-WT-20mps.csv. + .2 README.md. + } + + \column{0.55\textwidth} + \begin{itemize} + \item Organize the data when many files + \item Add a small \readme in the folder + \begin{itemize} + \item Link source for the data + \item Explain how they are formatted + \item Explain what they mean + \item Detail how to read it + \end{itemize} + \end{itemize} + \end{columns} + \end{frame} + +\begin{frame}{\insertsectionhead} + \framesubtitle{\insertsubsectionhead - Matlab} + \begin{columns}[onlytextwidth] + \column{0.45\textwidth} + \dirtree{% + .1 src. + .2 main.m. + .2 analyze\_results.m. + .2 utils. + .3 calibrate\_sensors.m. + .3 clean\_wt\_data.m. + .3 remove\_peaks.m. + .2 libs. + .3 +af\_tools. + .3 +wt\_tools. + } + + \column{0.55\textwidth} + \begin{itemize} + \item The files in the root of \lst{src} are the ones the user is supposed + to interact with + \item \lst{utils} is for small functions you wrote specifically for your + code + \item \lst{libs} is for general libraries\\ + also called 'package' in \matlab + \end{itemize} + \end{columns} + +\end{frame} + +{ + \setbeamertemplate{frame footer}{\advancedicon} + \begin{frame}{\insertsectionhead} + \framesubtitle{\insertsubsectionhead - Matlab} + \begin{columns}[onlytextwidth] + \column{0.45\textwidth} + \dirtree{% + .1 tests. + .2 utils. + .3 gen\_random\_data.m. + .2 test\_analyze\_results.m. + .2 test\_calibrate\_sensors.m. + .2 test\_clean\_wt\_data.m. + .2 test\_remove\_peaks.m. + } + + \column{0.55\textwidth} + \begin{itemize} + \item In theory, each independent function should be accompanied by a + specific test function. That verifies its execution. + \item In the \lst{test} directory, \lst{utils} is for specific very + basic utilities used in the tests. + \item In \matlab, using \lstmat{runstests('tests')} will run all + functions starting with \lst{test\_} in the \lst{tests} directory. + \end{itemize} + \end{columns} + + \end{frame} +} % TODO: Add a Python example -- GitLab