├── requirements.txt
├── latex
├── build
│ └── .gitignore
├── readme.md
├── figures
│ ├── logos
│ │ ├── bmbf.pdf
│ │ ├── dfg.pdf
│ │ ├── tum.pdf
│ │ ├── cluster.pdf
│ │ └── lmu_logo.pdf
│ ├── patterns
│ │ └── behavioral
│ │ │ └── ModulePath.png
│ └── paradigms
│ │ └── dp
│ │ └── modin_architecture.png
├── code
│ ├── paradigms
│ │ ├── fp
│ │ │ ├── sum_head_recursion.py
│ │ │ ├── generators.py
│ │ │ ├── sum_loop.py
│ │ │ ├── sum_tail_recursion.py
│ │ │ ├── sum_map_reduce.py
│ │ │ ├── higher_order.py
│ │ │ ├── memoization.py
│ │ │ ├── referential_transparency.py
│ │ │ ├── higher_order_2.py
│ │ │ └── subtypes.py
│ │ ├── dp
│ │ │ ├── linqtoroot.cs
│ │ │ ├── fast.yaml
│ │ │ ├── belle2_steering_file.py
│ │ │ ├── _root_dataframe.py
│ │ │ └── dataframes.py
│ │ ├── lp
│ │ │ └── siblings.pl
│ │ └── oop
│ │ │ ├── class_abstract.py
│ │ │ ├── class_inheritance.py
│ │ │ └── class_rectangle.py
│ └── patterns
│ │ ├── behavioral
│ │ ├── template_method_bad.py
│ │ ├── template_method.py
│ │ ├── strategy.py
│ │ └── belle2_steering_file.py
│ │ ├── creational
│ │ ├── builder_bad_2.py
│ │ ├── builder_best.py
│ │ ├── builder_good.py
│ │ ├── builder_bad.py
│ │ ├── uncertainties_bad.py
│ │ └── uncertainties_good.py
│ │ ├── intro
│ │ └── classmethod.py
│ │ └── structural
│ │ └── adapter.py
├── Makefile
├── header
│ ├── meta_paradigms.tex
│ ├── meta_patterns.tex
│ ├── general.tex
│ ├── packages.tex
│ ├── commands
│ │ ├── commands.tex
│ │ ├── pshortcuts.tex
│ │ ├── dashedxarrow.tex
│ │ ├── mcommands.tex
│ │ └── mshortcuts.tex
│ ├── footnote.tex
│ ├── layout.tex
│ └── beamer_struct.tex
├── input
│ ├── patterns
│ │ ├── closing.tex
│ │ ├── anti.tex
│ │ ├── title.tex
│ │ ├── parallel.tex
│ │ ├── careful.tex
│ │ ├── creational.tex
│ │ ├── structural.tex
│ │ ├── behavioral.tex
│ │ └── intro.tex
│ └── paradigms
│ │ ├── closing.tex
│ │ ├── misc.tex
│ │ ├── oovsfp.tex
│ │ ├── title.tex
│ │ ├── declarative.tex
│ │ ├── oo.tex
│ │ ├── structure.tex
│ │ └── fp.tex
├── programming_paradigms.tex
└── software_patterns.tex
├── codespell.txt
├── timing.ods
├── software_patterns_280920.pdf
├── readme_assets
├── binder_ready.png
├── colab-button.png
└── binder_loading.png
├── programming_paradigms_280920.pdf
├── software_patterns_280920_handout.pdf
├── programming_paradigms_280920_handout.pdf
├── .github
├── dependabot.yml
└── workflows
│ └── workflow.yml
├── CITATION.cff
├── .pre-commit-config.yaml
├── .gitignore
├── readme.md
├── exercises
├── paradigms.ipynb
└── patterns.ipynb
└── license.md
/requirements.txt:
--------------------------------------------------------------------------------
1 | jupyter
2 | matplotlib
3 |
--------------------------------------------------------------------------------
/latex/build/.gitignore:
--------------------------------------------------------------------------------
1 | # track folder
2 | *
3 |
--------------------------------------------------------------------------------
/codespell.txt:
--------------------------------------------------------------------------------
1 | hist
2 | emiss
3 | Emiss
4 | whis
5 | datas
6 |
--------------------------------------------------------------------------------
/latex/readme.md:
--------------------------------------------------------------------------------
1 | Compile with
2 |
3 | xelatex -shell-escape -output-directory build
4 |
--------------------------------------------------------------------------------
/timing.ods:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klieret/icsc-paradigms-and-patterns/HEAD/timing.ods
--------------------------------------------------------------------------------
/latex/figures/logos/bmbf.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klieret/icsc-paradigms-and-patterns/HEAD/latex/figures/logos/bmbf.pdf
--------------------------------------------------------------------------------
/latex/figures/logos/dfg.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klieret/icsc-paradigms-and-patterns/HEAD/latex/figures/logos/dfg.pdf
--------------------------------------------------------------------------------
/latex/figures/logos/tum.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klieret/icsc-paradigms-and-patterns/HEAD/latex/figures/logos/tum.pdf
--------------------------------------------------------------------------------
/software_patterns_280920.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klieret/icsc-paradigms-and-patterns/HEAD/software_patterns_280920.pdf
--------------------------------------------------------------------------------
/latex/code/paradigms/fp/sum_head_recursion.py:
--------------------------------------------------------------------------------
1 | def sum_squares_to(n):
2 | return 0 if n == 0 else n^2 + sum_squares_to(n-1)
3 |
--------------------------------------------------------------------------------
/latex/figures/logos/cluster.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klieret/icsc-paradigms-and-patterns/HEAD/latex/figures/logos/cluster.pdf
--------------------------------------------------------------------------------
/readme_assets/binder_ready.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klieret/icsc-paradigms-and-patterns/HEAD/readme_assets/binder_ready.png
--------------------------------------------------------------------------------
/readme_assets/colab-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klieret/icsc-paradigms-and-patterns/HEAD/readme_assets/colab-button.png
--------------------------------------------------------------------------------
/latex/figures/logos/lmu_logo.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klieret/icsc-paradigms-and-patterns/HEAD/latex/figures/logos/lmu_logo.pdf
--------------------------------------------------------------------------------
/programming_paradigms_280920.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klieret/icsc-paradigms-and-patterns/HEAD/programming_paradigms_280920.pdf
--------------------------------------------------------------------------------
/readme_assets/binder_loading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klieret/icsc-paradigms-and-patterns/HEAD/readme_assets/binder_loading.png
--------------------------------------------------------------------------------
/software_patterns_280920_handout.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klieret/icsc-paradigms-and-patterns/HEAD/software_patterns_280920_handout.pdf
--------------------------------------------------------------------------------
/latex/code/paradigms/fp/generators.py:
--------------------------------------------------------------------------------
1 | %time a = range(int(1e8))
2 | >>> Wall time: 7.63 µs
3 |
4 | %time b = list(a)
5 | >>> Wall time: 2.33 s
6 |
--------------------------------------------------------------------------------
/programming_paradigms_280920_handout.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klieret/icsc-paradigms-and-patterns/HEAD/programming_paradigms_280920_handout.pdf
--------------------------------------------------------------------------------
/latex/code/paradigms/fp/sum_loop.py:
--------------------------------------------------------------------------------
1 | def sum_squares_to(n):
2 | result = 0
3 | for i in range(n+1):
4 | result += i^2
5 | return result
6 |
--------------------------------------------------------------------------------
/latex/code/paradigms/fp/sum_tail_recursion.py:
--------------------------------------------------------------------------------
1 | def sum_squares_to(n, partial_sum=0):
2 | return partial_sum if n == 0 else sum_squares_to(n-1, partial_sum + n^2)
3 |
--------------------------------------------------------------------------------
/latex/figures/patterns/behavioral/ModulePath.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klieret/icsc-paradigms-and-patterns/HEAD/latex/figures/patterns/behavioral/ModulePath.png
--------------------------------------------------------------------------------
/latex/figures/paradigms/dp/modin_architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klieret/icsc-paradigms-and-patterns/HEAD/latex/figures/paradigms/dp/modin_architecture.png
--------------------------------------------------------------------------------
/latex/code/paradigms/dp/linqtoroot.cs:
--------------------------------------------------------------------------------
1 | events
2 | .Select(e => e.Data.eventWeight)
3 | .FuturePlot("event_weights", "Sample EventWeights",100, 0.0, 1000.0)
4 | .Save(hdir);
5 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | # Maintain dependencies for GitHub Actions
4 | - package-ecosystem: "github-actions"
5 | directory: "/"
6 | schedule:
7 | interval: "weekly"
8 |
--------------------------------------------------------------------------------
/latex/Makefile:
--------------------------------------------------------------------------------
1 | all:
2 | mkdir -p build && xelatex --output-directory build -shell-escape software_patterns.tex
3 | mkdir -p build && xelatex --output-directory build -shell-escape programming_paradigms.tex
4 |
--------------------------------------------------------------------------------
/latex/code/paradigms/fp/sum_map_reduce.py:
--------------------------------------------------------------------------------
1 | from functools import map, reduce
2 |
3 |
4 | def sum_squares_to(n):
5 | return reduce(
6 | lambda x, y: x+y,
7 | map(lambda x: x**2, range(n+1))
8 | )
9 |
--------------------------------------------------------------------------------
/latex/code/paradigms/dp/fast.yaml:
--------------------------------------------------------------------------------
1 | stages:
2 | - BasicVars: Define
3 | - DiMuons: cms_hep_tutorial.DiObjectMass
4 | - NumberMuons: fast_carpenter.BinnedDataframe
5 | - EventSelection: CutFlow
6 | - DiMuonMass: BinnedDataframe
7 |
--------------------------------------------------------------------------------
/latex/code/paradigms/fp/higher_order.py:
--------------------------------------------------------------------------------
1 | def map(function, iterator):
2 | """ Our own version of map (returns a list rather than a generator) """
3 | return [function(item) for item in iterator]
4 |
5 |
6 | map(lambda x: x**2, [1, 2, 3])
7 | >>> [1, 4, 9]
8 |
--------------------------------------------------------------------------------
/latex/code/paradigms/fp/memoization.py:
--------------------------------------------------------------------------------
1 | import time
2 | from functools import lru_cache
3 |
4 |
5 | @lru_cache()
6 | def expensive(x):
7 | time.sleep(1)
8 | return x+42
9 |
10 |
11 | %time expensive(2)
12 | >>> Wall time: 1 s
13 |
14 | % time expensive(2)
15 | >>> Wall time: 6.2 µs
16 |
--------------------------------------------------------------------------------
/latex/header/meta_paradigms.tex:
--------------------------------------------------------------------------------
1 | % META DATA
2 | %
3 | \title{Programming Paradigms}
4 | \subtitle{\ \relax}
5 | \author{Kilian Lieret}
6 | \newcommand*{\coauthors}{}
7 | \institute{Ludwig-Maximilian University}
8 | %\date{28 September 2020}
9 | %
10 | %
11 | %\newcommand{\clusterking}{{\protect\color{red}test}}
12 | %
13 |
--------------------------------------------------------------------------------
/latex/header/meta_patterns.tex:
--------------------------------------------------------------------------------
1 | % META DATA
2 | %
3 | \title{Software Design Patterns}
4 | \subtitle{\ \relax}
5 | \author{Kilian Lieret}
6 | \newcommand*{\coauthors}{}
7 | \institute{Ludwig-Maximilian University}
8 | %\date{29 September 2020}
9 | %
10 | %
11 | %\newcommand{\clusterking}{{\protect\color{red}test}}
12 | %
13 |
--------------------------------------------------------------------------------
/CITATION.cff:
--------------------------------------------------------------------------------
1 | cff-version: 1.1.0
2 | message: "Please cite as below"
3 | version: lmu-patterns-2021
4 | authors:
5 | - family-names: Lieret
6 | given-names: Kilian
7 | orcid: https://orcid.org/0000-0003-2792-7511
8 | title: "Programming Paradigms and Patterns"
9 | doi: 10.5281/zenodo.4432319
10 | date-released: 2021-01-11
11 |
--------------------------------------------------------------------------------
/latex/code/patterns/behavioral/template_method_bad.py:
--------------------------------------------------------------------------------
1 | class MLModel():
2 | def load_data(...)
3 | def prepare_features(...)
4 |
5 | def train(...):
6 | if self.model == "BDT":
7 | # train BDT
8 | elif self.model == "RandomForest":
9 | # train random forest
10 | elif ...
11 |
12 | def validate(...)
13 | ...
14 |
--------------------------------------------------------------------------------
/latex/code/patterns/creational/builder_bad_2.py:
--------------------------------------------------------------------------------
1 | class Data:
2 | def __init__(
3 | self,
4 | data: array,
5 | data_error: array
6 | mc_components: List[array],
7 | mc_errors: List[array],
8 | mc_float_normalization: List[bool],
9 | mc_color: List[string],
10 | ...
11 | )
12 |
--------------------------------------------------------------------------------
/latex/code/patterns/creational/builder_best.py:
--------------------------------------------------------------------------------
1 | class Data:
2 | pass
3 |
4 | class Builder:
5 | def __init__(...)
6 |
7 | def add_mc_component(...)
8 |
9 | def create(...) -> Data
10 |
11 |
12 | builder = Builder(...)
13 | builder.add_mc_component(...)
14 | ...
15 | builder.add_mc_component(...)
16 | data = builder.create()
17 |
--------------------------------------------------------------------------------
/latex/code/patterns/creational/builder_good.py:
--------------------------------------------------------------------------------
1 | class Data:
2 | def __init__(self, data: array, data_error: array)
3 | pass
4 |
5 | def add_mc_component(self, data, errors, floating=False, color="black", ...):
6 | pass
7 |
8 |
9 | data = Data(...)
10 | data.add_mc_component(...)
11 | ...
12 | data.add_mc_component(...)
13 |
--------------------------------------------------------------------------------
/latex/code/paradigms/fp/referential_transparency.py:
--------------------------------------------------------------------------------
1 | def f1(x):
2 | return x**2
3 |
4 |
5 | def f2(x):
6 | print(x)
7 | return x**2
8 |
9 |
10 | y = 0
11 |
12 |
13 | def f3(x):
14 | global y
15 | y += 1
16 | return x + y
17 |
18 |
19 | def f4():
20 | return int(input()) + 1
21 |
22 |
23 | def f5(lst: List):
24 | lst[0] = 3
25 | return lst
26 |
--------------------------------------------------------------------------------
/latex/code/patterns/intro/classmethod.py:
--------------------------------------------------------------------------------
1 | class Class:
2 | def method(self):
3 | # needs to be called from INSTANCE and can access instance attributes
4 | @classmethod
5 | def classmethod(cls):
6 | # no access to instance attributes
7 |
8 | # This won't work:
9 | Class.method() # <-- needs an instance, e.g. Class(...).method()
10 |
11 | # But this does:
12 | Class.classmethod()
13 |
--------------------------------------------------------------------------------
/latex/code/patterns/creational/builder_bad.py:
--------------------------------------------------------------------------------
1 | class Data:
2 | def __init__(
3 | self,
4 | data: array,
5 | data_error: array
6 | mc_components: List[array],
7 | mc_errors: List[array],
8 | mc_float_normalization: List[bool],
9 | mc_color: List[string],
10 | ...
11 | )
12 |
13 | def fit(...)
14 |
15 | def plot(...)
16 |
--------------------------------------------------------------------------------
/latex/code/paradigms/fp/higher_order_2.py:
--------------------------------------------------------------------------------
1 | def get_map_function(function):
2 | """ Takes a function f and returns the function map(f, *) """
3 | def _map_function(iterator):
4 | return map(function, iterator)
5 |
6 | return _map_function
7 |
8 |
9 | mf1 = get_map_function(lambda x: x**2)
10 | mf2 = get_map_function(lambda x: x+1)
11 |
12 | mf2(mf1([1, 2, 3]))
13 | >>> [2, 5, 10]
14 |
--------------------------------------------------------------------------------
/latex/code/paradigms/lp/siblings.pl:
--------------------------------------------------------------------------------
1 | % X, Y are siblings if they share a parent
2 | sibling(X, Y) :- parent_child(Z, X), parent_child(Z, Y).
3 |
4 | % Father, mother implies parent
5 | parent_child(X, Y) :- father_child(X, Y).
6 | parent_child(X, Y) :- mother_child(X, Y).
7 |
8 | % Introduce some people
9 | father_child(tom, sally).
10 | father_child(tom, erica).
11 |
12 | % Ask:
13 | ?- sibling(sally, erica).
14 | Yes
15 |
--------------------------------------------------------------------------------
/latex/code/paradigms/oop/class_abstract.py:
--------------------------------------------------------------------------------
1 | from abc import ABC, abstractmethod
2 |
3 |
4 | class Shape(ABC):
5 | @abstractmethod
6 | def calculate_area(self):
7 | pass
8 |
9 | @abstractmethod
10 | def draw(self):
11 | pass
12 |
13 |
14 | class Rectangle(Shape):
15 | def __init__(self, ...):
16 | ...
17 |
18 | def calculate_area(self):
19 | # concrete implementation here
20 |
--------------------------------------------------------------------------------
/latex/code/patterns/behavioral/template_method.py:
--------------------------------------------------------------------------------
1 | class MLModel(ABC): # <-- abstract class
2 | def load_data(...)
3 | def prepare_features(...)
4 |
5 | @abstractmethod
6 | def train(...):
7 | pass
8 |
9 | def validate(...)
10 | ...
11 |
12 |
13 | class BDT(MLModel): # <-- concrete class
14 | def train(...):
15 | # Implementation
16 |
17 |
18 | class RandomForest(MLModel):
19 | def train(...):
20 | # Implementation
21 |
--------------------------------------------------------------------------------
/latex/input/patterns/closing.tex:
--------------------------------------------------------------------------------
1 | \begin{frame}{Outlook}{\relax}
2 | \bigskip
3 | Discussion on mattermost: \href{https://mattermost.web.cern.ch/csc/channels/software-design}{\hhl{mattermost.web.cern.ch/csc/channels/software-design}}
4 |
5 | \bigskip
6 | Get the exercises at \hhl{\href{https://github.com/klieret/icsc-paradigms-and-patterns}{github.com/klieret/icsc-paradigms-and-patterns}}
7 |
8 | \bigskip
9 | \end{frame}
10 |
--------------------------------------------------------------------------------
/latex/code/paradigms/oop/class_inheritance.py:
--------------------------------------------------------------------------------
1 | class Person:
2 | def __init__(self, name):
3 | self.name = name
4 |
5 | def greet(self):
6 | print(f"Hello, I'm {self.name}")
7 |
8 |
9 | class Child(Person):
10 | def __init__(self, name, school):
11 | super().__init__(name)
12 | self.school = school
13 |
14 | def learn(self):
15 | print(f"I'm learning a lot at {self.school}")
16 |
17 |
18 | c1 = Child("john", "iCSC20")
19 | c1.greet()
20 | c1.learn()
21 |
--------------------------------------------------------------------------------
/latex/code/patterns/creational/uncertainties_bad.py:
--------------------------------------------------------------------------------
1 | class Uncertainty:
2 | def __init__(self, absolute_errors=None, relative_error=None,
3 | data=None, config=None, ...):
4 | if config is not None:
5 | # load from config
6 | elif absolute_errors is not None:
7 | # add absolute errors
8 | elif relative_errors is not None and data is not None:
9 | # add relative errors
10 | ...
11 |
12 |
13 | instance = Uncertainty(config="path/to/my/config")
14 |
--------------------------------------------------------------------------------
/latex/header/general.tex:
--------------------------------------------------------------------------------
1 | % ----------- GENERAL STUFF -----------------
2 | \documentclass%
3 | [%
4 | 9pt,
5 | ngerman,
6 | table,
7 | xcolor={usenames,dvipsnames},
8 | \ifhandout handout \else \fi
9 | ]%
10 | {beamer}
11 |
12 | % Available font sizes are 8pt, 9pt, 10pt, 11pt, 12pt, 14pt, 17pt, 20pt. Default font size is 11pt (which corresponds to 22pt at the full screen mode).
13 |
14 | %\usepackage[utf8]{inputenc} using xelatex
15 | \usepackage[english]{babel}
16 | \usepackage{csquotes}
17 |
18 | \RequirePackage{ragged2e} % not sure if needed
19 |
--------------------------------------------------------------------------------
/latex/code/patterns/creational/uncertainties_good.py:
--------------------------------------------------------------------------------
1 | class Uncertainty:
2 | def __init__(self, absolute_errors):
3 | # construct from absolute errors
4 |
5 | @classmethod # <-- doesn't need instance to be called (cf. first slide)
6 | def from_config(cls, config):
7 | # get absolute errors from config file
8 | return cls(absolute_errors)
9 |
10 | @classmethod
11 | def relative_errors(cls, data, relative_errors):
12 | return cls(data * relative_errors)
13 |
14 |
15 | instance = Uncertainty.from_config("path/to/my/config")
16 |
--------------------------------------------------------------------------------
/latex/code/paradigms/fp/subtypes.py:
--------------------------------------------------------------------------------
1 | # OOP:
2 |
3 | class Animal:
4 | def walk(self): ...
5 | def talk(self):
6 | print("Hi, I'm ", self.name)
7 |
8 | class Dog(Animal): # <-- can also walk
9 | def talk(self): # <-- talks differently (override super method)
10 | print("Woof woof, I'm ", self.name)
11 |
12 |
13 | # FP
14 | # ... define Dog a subtype of Animal ...
15 |
16 | def talk(a: Animal):
17 | print("Hi, I'm ", a.name)
18 |
19 |
20 | def walk(a: Animal): # <-- can also be called on Dog
21 | ...
22 |
23 | def talk(a: Dog): # <-- dogs talk differently
24 | print("Woof woof, I'm ", a.name)
25 |
--------------------------------------------------------------------------------
/latex/code/patterns/behavioral/strategy.py:
--------------------------------------------------------------------------------
1 | class MyAnalysis():
2 | def __init__(self, ml_model: MLModel, fitter: Fitter)
3 | self.ml_model = ml_model
4 | self.fitter = fitter
5 |
6 | def fit(...):
7 | self.fitter.fit(...)
8 |
9 | def train(...):
10 | self.ml_model.train(...)
11 |
12 | class MLModel(ABC):
13 | @abstractmethod
14 | def train(...)
15 |
16 | class RandomForest(MLModel):
17 | def train(...):
18 | # Implementation
19 |
20 |
21 | my_analysis = MyAnalysis(RandomForest(...), KernelDensityEstimator(...))
22 | my_analysis.train(...)
23 | my_analysis.fit(...)
24 |
--------------------------------------------------------------------------------
/latex/code/paradigms/dp/belle2_steering_file.py:
--------------------------------------------------------------------------------
1 | path = create_path()
2 |
3 | # Load data
4 | inputMdstList("default", "/path/to/input/file", path=path)
5 |
6 | # Get final state particles
7 |
8 | # Fill 'pi+:loose' particle list with all particles that have pion ID > 0.01:
9 | fillParticleList("pi+:loose", "piid > 0.01", path=path)
10 | # Fill 'mu+:loose' particle list with all particles that have muon ID > 0.01:
11 | fillParticleList("mu+:loose", "piid > 0.01", path=path)
12 |
13 | # Reconstruct decay
14 | # Fill 'K_S0:pipi' particle list with combinations of our pions and muons
15 | reconstructDecay(
16 | "K_S0:pipi -> pi+:loose pi-:loose", "0.4 < M < 0.6", path=path
17 | )
18 |
--------------------------------------------------------------------------------
/latex/code/paradigms/oop/class_rectangle.py:
--------------------------------------------------------------------------------
1 | class Rectangle:
2 | def __init__(self, width, height): # <-- constructor
3 | # 'self' represents the instance of the class
4 | self.width = width # <-- attribute = internal variable
5 | self.height = height
6 |
7 | def calculate_area(self): # <-- method (function of class)
8 | return self.width * self.height
9 |
10 |
11 | r1 = Rectangle(1, 2) # <-- object (instance of the class)
12 | print(r1.calculate_area()) # <-- call method of object
13 | print(r1.width) # <-- get attribute of object
14 | r1.width = 5 # <-- set attribute of object
15 |
--------------------------------------------------------------------------------
/latex/input/paradigms/closing.tex:
--------------------------------------------------------------------------------
1 | \section{Outlook}
2 |
3 | \begin{frame}{Outlook}
4 | Next lecture: \hhl{Software design patterns}
5 | \begin{itemize}
6 | \item Focus on OOP
7 | \item Introduce some \enquote{golden rules} of OOP
8 | \item \hhl{Patterns}: Reusable solutions to common problems
9 | \end{itemize}
10 |
11 | \bigskip
12 | Discussion on mattermost: \href{https://mattermost.web.cern.ch/csc/channels/programming-paradigms}{\hhl{mattermost.web.cern.ch/csc/channels/programming-paradigms}}
13 |
14 | \bigskip
15 | Get the exercises at \hhl{\href{https://github.com/klieret/icsc-paradigms-and-patterns}{github.com/klieret/icsc-paradigms-and-patterns}}
16 | \end{frame}
17 |
--------------------------------------------------------------------------------
/latex/code/paradigms/dp/_root_dataframe.py:
--------------------------------------------------------------------------------
1 | import ROOT
2 |
3 |
4 | def fill_tree(treeName, fileName):
5 | tdf = ROOT.ROOT.RDataFrame(10)
6 | tdf.Define("data", "(double) tdfentry_")\
7 | .Define("theory", "tdfentry_ + 0.1")\
8 | .Define("error", "0.1").Snapshot(treeName, fileName)
9 |
10 | # We prepare an input tree to run on
11 | fileName = "df001_introduction_py.root"
12 | treeName = "myTree"
13 | fill_tree(treeName, fileName)
14 |
15 | rdf = ROOT.ROOT.RDataFrame(treeName, fileName)
16 |
17 | print(rdf)
18 |
19 | rdf = rdf.Filter("!(data==theory & error==0.)").Define("sqd", "pow(data-theory, 2) / pow(error, 2)")
20 | chi2 = rdf.Sum("sqd").GetValue()
21 |
22 | print(chi2)
23 |
--------------------------------------------------------------------------------
/latex/code/patterns/structural/adapter.py:
--------------------------------------------------------------------------------
1 | class OurMLModel(ABC):
2 | """ Our interface """
3 | @abstractmethod
4 | def train(...):
5 | pass
6 |
7 |
8 | class TheirMLModel(ABC):
9 | """ Their interface """
10 | @abstractmethod
11 | def training(...) # <-- this method should be called train
12 | pass
13 |
14 |
15 | class ModelAdapter(OurMLModel): # <-- implements our interface
16 | def __init__(self, model: TheirMLModel):
17 | self._model = model # <-- our adapter holds the foreign model
18 |
19 | def train(...): # <-- and defines a different interface for it
20 | self._model.training(...)
21 |
22 |
23 | # Their model with our interface:
24 | model = ModelAdapter(TheirMLModel(...)) # (actually need TheirConcreteMLModel)
25 |
--------------------------------------------------------------------------------
/latex/input/paradigms/misc.tex:
--------------------------------------------------------------------------------
1 | \subsection{Others}
2 |
3 |
4 | \frame{\tableofcontents[currentsection, currentsubsection]}
5 |
6 |
7 | \begin{frame}{Other paradigms}
8 | \begin{itemize}
9 | \item \hhl{Logic programming} (LP) (subset of declarative programming): Automatic reasoning by applying inference rules
10 | \begin{itemize}
11 | \item LP languages: \proglang{Prolog}, \proglang{Datalog}
12 | \item LP can be made available with libraries, e.g., for \proglang{Python}: \texttt{Pyke} (inspired by \proglang{prolog}), \texttt{pyDatalog} (inspired by \proglang{Datalog})
13 | \item Example:
14 | \inputminted[]{prolog}{code/paradigms/lp/siblings.pl}
15 | \end{itemize}
16 | \item \hhl{Symbolic programming}
17 | \item \hhl{Differentiable programming}
18 | \end{itemize}
19 | \end{frame}
20 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/pre-commit/pre-commit-hooks
3 | rev: v4.6.0
4 | hooks:
5 | - id: check-added-large-files
6 | - id: check-case-conflict
7 | - id: detect-private-key
8 | - id: end-of-file-fixer
9 | - id: trailing-whitespace
10 | - id: check-merge-conflict
11 | - repo: https://github.com/codespell-project/codespell
12 | rev: 'v2.3.0'
13 | hooks:
14 | - id: codespell
15 | args: ["-I", "codespell.txt"]
16 | exclude: '.*\.sty|license\.md'
17 | - repo: https://github.com/jonasbb/pre-commit-latex-hooks
18 | rev: v1.4.3
19 | hooks:
20 | - id: american-eg-ie
21 | - id: cleveref-capitalization
22 | - id: csquotes
23 | - id: no-space-in-cite
24 |
25 | ci:
26 | autoupdate_schedule: quarterly
27 |
--------------------------------------------------------------------------------
/latex/code/paradigms/dp/dataframes.py:
--------------------------------------------------------------------------------
1 | # "Chi2 distance" using plain python
2 | def chi2(data, theory, error):
3 | err_sum = 0
4 | for i in range(len(data)):
5 | if data[i] == theory[i] and error[i] == 0:
6 | continue
7 | err_sum += (data[i] - theory[i])**2 / (error[i]**2)
8 | return err_sum
9 |
10 |
11 | # Using DataFrames: Table contains columns experiment, theory, error
12 |
13 | # ROOT RDataFrame example:
14 | chi2 = ROOT.ROOT.RDataFrame(...) # initialize
15 | .Filter("!(data==theory & error==0.)") # filter rows
16 | .Define("sqd", "pow(data-theory, 2) / pow(error, 2)") # new col
17 | .Sum("sqd").GetValue() # sum it up
18 |
19 | # Pandas example:
20 | df = pd.DataFrame(...) # initialize
21 | _df = df.query("~(data==theory & error==0)") # filter
22 | chi2 = (_df["data"] - _df["theory"]).pow(2) / _df["error"].pow(2).sum()
23 |
--------------------------------------------------------------------------------
/latex/code/patterns/behavioral/belle2_steering_file.py:
--------------------------------------------------------------------------------
1 | # Create path to add modules (=Command objects) to
2 | path = create_path()
3 |
4 | # Load data (convenience function that adds a "DataLoader" module to the path)
5 | inputMdstList("default", "/path/to/input/file", path=path)
6 |
7 | # Get final state particles
8 |
9 | # Fill 'pi+:loose' particle list with all particles that have pion ID > 0.01:
10 | fillParticleList("pi+:loose", "piid > 0.01", path=path)
11 | # Fill 'mu+:loose' particle list with all particles that have muon ID > 0.01:
12 | fillParticleList("mu+:loose", "piid > 0.01", path=path)
13 |
14 | # Reconstruct decay
15 | # Fill 'K_S0:pipi' particle list with combinations of our pions and muons
16 | reconstructDecay(
17 | "K_S0:pipi -> pi+:loose pi-:loose", "0.4 < M < 0.6", path=path
18 | )
19 |
20 | # Process path = call execute() on all Command objects
21 | process(my_path)
22 |
--------------------------------------------------------------------------------
/.github/workflows/workflow.yml:
--------------------------------------------------------------------------------
1 | name: Build LaTeX document
2 | on: [push]
3 | jobs:
4 | build_latex:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - name: Set up Git repository
8 | uses: actions/checkout@v6
9 | - name: Compile LaTeX document
10 | uses: xu-cheng/latex-action@v3
11 | with:
12 | root_file: |
13 | programming_paradigms.tex
14 | software_patterns.tex
15 | latexmk_use_xelatex: true
16 | args: -f -pdf -interaction=nonstopmode -shell-escape -output-directory=build
17 | working_directory: latex
18 | extra_system_packages: "py-pygments"
19 | - name: Upload PDF as artifact
20 | uses: actions/upload-artifact@v4
21 | with:
22 | name: PDF
23 | path: |
24 | latex/build/programming_paradigms.pdf
25 | latex/build/software_patterns.pdf
26 |
--------------------------------------------------------------------------------
/latex/programming_paradigms.tex:
--------------------------------------------------------------------------------
1 | \newif\ifhandout
2 | \newif\ifexamples
3 | \handoutfalse
4 | \examplestrue
5 | %
6 | \input{header/general.tex}
7 | \input{header/meta_paradigms.tex}
8 | \input{header/packages.tex}
9 | \input{header/layout.tex}
10 | \input{header/beamer_struct.tex}
11 | \input{header/commands/commands.tex}
12 | \input{header/commands/pshortcuts.tex}
13 | \input{header/commands/mshortcuts.tex}
14 | \input{header/commands/mcommands.tex}
15 | \input{header/commands/dashedxarrow.tex}
16 | \input{header/footnote.tex}
17 | %\usemintedstyle{rainbow_dash}
18 | \begin{document}
19 | %
20 | \input{input/paradigms/title.tex}
21 | \input{input/paradigms/structure.tex}
22 | \section[Paradigms]{Programming Paradigms}
23 | \input{input/paradigms/oo.tex}
24 | \input{input/paradigms/fp.tex}
25 | \input{input/paradigms/oovsfp.tex}
26 | \input{input/paradigms/declarative.tex}
27 | \input{input/paradigms/misc.tex}
28 | \input{input/paradigms/closing.tex}
29 | \end{document}
30 |
--------------------------------------------------------------------------------
/latex/software_patterns.tex:
--------------------------------------------------------------------------------
1 | \newif\ifhandout
2 | \newif\ifexamples
3 | \handoutfalse
4 | \examplestrue
5 | %
6 | \input{header/general.tex}
7 | \input{header/meta_patterns.tex}
8 | \input{header/packages.tex}
9 | \input{header/layout.tex}
10 | \input{header/beamer_struct.tex}
11 | \input{header/commands/commands.tex}
12 | \input{header/commands/pshortcuts.tex}
13 | \input{header/commands/mshortcuts.tex}
14 | \input{header/commands/mcommands.tex}
15 | \input{header/commands/dashedxarrow.tex}
16 | \input{header/footnote.tex}
17 | %\usemintedstyle{rainbow_dash}
18 | \begin{document}
19 | %
20 | \input{input/patterns/title.tex}
21 | \input{input/patterns/intro.tex}
22 | \input{input/patterns/creational.tex}
23 | \input{input/patterns/structural.tex}
24 | \input{input/patterns/behavioral.tex}
25 | \input{input/patterns/parallel.tex}
26 | \input{input/patterns/anti.tex}
27 | \input{input/patterns/careful.tex}
28 | \input{input/patterns/closing.tex}
29 | %
30 | %
31 | \end{document}
32 |
--------------------------------------------------------------------------------
/latex/input/patterns/anti.tex:
--------------------------------------------------------------------------------
1 | \subsection{Antipatterns}
2 |
3 | \frame{\tableofcontents[currentsection, currentsubsection]}
4 |
5 | \begin{frame}{Anti-patterns}
6 | \begin{itemize}[<+->]
7 | \item \hhl{God object}, \hhl{The blob}: One massive class containing all functionality
8 | \item \hhl{Object orgy}: Not using data encapsulation \srem{(not distinguishing between public and private members)}; some objects modify the internals of others more than their own \srem{($\lra$ it is not clear \enquote{who is doing what to whom})}
9 | \item \hhl{Not using polymorphism}: Having many parallel sections of identical \texttt{if} statements rather than using classes and subclasses
10 | \item \hhl{Misusing (multiple) inheritance}: Some inherited methods do not make sense for subclass; violations of the Liskov substitution principle
11 | \item \hhl{Overgeneralization}/\hhl{inner platform effect}: A system so general and customizable that it reproduces your development platform
12 | \end{itemize}
13 | \end{frame}
14 |
--------------------------------------------------------------------------------
/latex/header/packages.tex:
--------------------------------------------------------------------------------
1 | \usepackage{graphicx}
2 |
3 | \usepackage{url}
4 |
5 | %\usepackage{caption} % improved spacing between figure and caption
6 |
7 | \usepackage{booktabs}
8 |
9 | % showboxes: show the box (good for drafting)
10 | % overlay: go on top
11 | % absolute: absolute positioning
12 | \usepackage[absolute, overlay]{textpos}
13 | \setlength{\TPHorizModule}{1cm}
14 | \setlength{\TPVertModule}{1cm}
15 |
16 | % https://tex.stackexchange.com/questions/12703/how-to-create-fixed-width-table-columns-with-text-raggedright-centered-raggedlef
17 | %\usepackage{array}
18 | %\newcolumntype{C}[1]{>{\centering\let\newline\\\arraybackslash\hspace{0pt}}m{#1}}
19 |
20 |
21 | % https://tex.stackexchange.com/questions/5017/center-column-with-specifying-width-in-table-tabular-enviroment
22 | \usepackage{array}
23 | \newcolumntype{x}[1]{>{\centering\arraybackslash\hspace{0pt}}p{#1}}
24 |
25 | \usepackage{amsmath}
26 |
27 | % required by dashedxarrow!
28 | \usepackage{amsfonts}
29 |
30 | %\usepackage{mathtools}
31 | \usepackage{hanging} % for footnote configuration in layout.tex
32 |
33 |
34 |
35 | %\usepackage[perpage]{footmisc}
36 |
37 | % for sout
38 | \usepackage[normalem]{ulem}
39 |
40 | \usepackage[]{tikz-uml}
41 |
--------------------------------------------------------------------------------
/latex/header/commands/commands.tex:
--------------------------------------------------------------------------------
1 | % Functions
2 | % Definitions that are more complex than an alias
3 | % ###################################################
4 |
5 | % Changemargin
6 | \newenvironment{changemargin}[2]{
7 | \begin{list}{}{
8 | \setlength{\topsep}{0pt}
9 | \setlength{\leftmargin}{#1}
10 | \setlength{\rightmargin}{#2}
11 | \setlength{\listparindent}{\parindent}
12 | \setlength{\itemindent}{\parindent}
13 | \setlength{\parsep}{\parskip}
14 | }
15 | \item[]
16 | }{\end{list}}
17 |
18 |
19 | % An arrow and text that keeps the indentation
20 | \newcommand\lrapar[1]{
21 | \normalsize
22 | \begin{itemize}
23 | \item[$\longrightarrow$] #1
24 | \end{itemize}
25 | }
26 |
27 | \newcommand\Lrapar[1]{
28 | \normalsize
29 | \begin{itemize}
30 | \item[$\Longrightarrow$] {\normalsize #1}
31 | \end{itemize}
32 | }
33 |
34 | %\newcommand{\specialitem}[2]{%
35 | % {
36 | % \usebeamercolor{structure}
37 | % \color{fg}
38 | % % by using the negative spacing we're forcing the
39 | % % item to be aligned by the text, without taking
40 | % % into account the dimensions of the number
41 | % %\hspace{-0.5em}\makebox[1em]{\footnotesize #1.}#2%
42 | % {\footnotesize #1.} #2%
43 | % }
44 | %}
45 |
46 |
47 | %\newcommand{\vcenteredinclude}[1]{\begingroup
48 | % \setbox0=\hbox{#1}%
49 | % \parbox{\wd0}{\box0}\endgroup}
50 |
51 | %\newenvironment{python}{
52 |
--------------------------------------------------------------------------------
/latex/input/paradigms/oovsfp.tex:
--------------------------------------------------------------------------------
1 | \subsection{OOP vs FP}
2 |
3 | \begin{frame}[t]{Object oriented vs functional programming}
4 | Some key aspects to keep in mind:
5 | \begin{itemize}[<+->]
6 | \item $\text{FP} \neq \text{OOP} - \text{classes}$
7 | \item FP is \stress{not} the opposite of OOP: Both paradigms take opposite stances in several aspects: declarative vs imperative, mutable vs immutable, \dots{} $\Longrightarrow$ Not everything can be classified into one of these categories
8 | \item Rather: Two different \hhl{ways to think} and to approach problems \srem{$\longrightarrow$ see caveats at the beginning}
9 | \end{itemize}
10 |
11 | \only<+->{
12 | \medskip
13 | In a multi-paradigm language, you can use the best of both worlds!
14 | \begin{itemize}[<+->]
15 | \item \hhl{OOP} has its classical use cases where there is strong coupling between data and methods and the bookkeeping is in the focus (especially of "real-world" objects)
16 | \item \hhl{FP} instead focuses on algorithms and \emph{doing} things
17 | \item Some people advocate \hhl{\enquote{OOP in the large, FP in the small}} \srem{(using OOP as the high level interface, using FP techniques for implementing the logic)}
18 | \end{itemize}
19 | }
20 |
21 | \only<+->{
22 | For example:
23 | \begin{itemize}
24 | \item Many complicated class structures implementing \hhl{manipulations} can be made more flexible with a system of high level functions, anonymous functions etc. \srem{(\texttt{pandas.DataFrame.apply})}
25 | \end{itemize}
26 | }
27 | \end{frame}
28 |
--------------------------------------------------------------------------------
/latex/input/paradigms/title.tex:
--------------------------------------------------------------------------------
1 | \begin{frame}{}
2 | \begin{center}
3 | {
4 | \usebeamercolor[fg]{structure}
5 | %
6 | {
7 | \Large \inserttitle
8 | }\\[0.7ex]
9 | %
10 | {
11 | \large \insertsubtitle
12 | }
13 | }\\[2ex]
14 | %
15 | Kilian Lieret\textsuperscript{1,2}\\[2ex]
16 | {
17 | \small
18 | Feedback \& review:\\[0ex]
19 | Sebastien Ponce\textsuperscript{3},
20 | Enric Tejedor\textsuperscript{3}
21 | }
22 | %
23 | \\[2.5 ex]
24 | {
25 | \footnotesize
26 | \textsuperscript{1}Ludwig-Maximilian University\\%[0ex]
27 | \textsuperscript{2}Excellence Cluster Origins\\%[0ex]
28 | \vspace{-0.5ex}\textsuperscript{3}CERN
29 | }\\[2.5ex]
30 | %
31 | \insertdate
32 | \end{center}
33 | \vspace{6ex}
34 | \centering
35 | % we use minipages for the vertical centering
36 | %\fbox%
37 | \newcommand\tmp{2.6cm}
38 | \newcommand\tmpp{2.4cm}
39 | \begin{changemargin}{-1cm}{-1cm}
40 | \centering
41 | {
42 | \begin{minipage}{\tmp}
43 | \includegraphics[width=\tmpp]{figures/logos/lmu_logo.pdf}
44 | \end{minipage}
45 | }
46 | %\hspace{0.3cm}
47 | %\fbox%
48 | {
49 | \begin{minipage}{\tmp}
50 | \includegraphics[width=\tmpp]{figures/logos/cluster.pdf}
51 | \end{minipage}
52 | }%\\[2ex]
53 | % \hspace{0.3cm}
54 | %\fbox%
55 | {
56 | \begin{minipage}{\tmp}
57 | \includegraphics[width=\tmpp]{figures/logos/dfg.pdf}
58 | \end{minipage}
59 | }
60 | %\hspace{0.3cm}x
61 | {
62 | \begin{minipage}{\tmp}
63 | \includegraphics[width=\tmpp]{figures/logos/bmbf.pdf}
64 | \end{minipage}
65 | }
66 | \end{changemargin}
67 | \end{frame}
68 |
--------------------------------------------------------------------------------
/latex/input/patterns/title.tex:
--------------------------------------------------------------------------------
1 | \begin{frame}{}
2 | \begin{center}
3 | {
4 | \usebeamercolor[fg]{structure}
5 | %
6 | {
7 | \Large \inserttitle
8 | }\\[0.7ex]
9 | %
10 | {
11 | \large \insertsubtitle
12 | }
13 | }\\[2ex]
14 | %
15 | Kilian Lieret\textsuperscript{1,2}\\[2ex]
16 | {
17 | \small
18 | Feedback \& review:\\[0ex]
19 | Sebastien Ponce\textsuperscript{3},
20 | Enric Tejedor\textsuperscript{3}
21 | }
22 | \\[2.5 ex]
23 | {
24 | \footnotesize
25 | \textsuperscript{1}Ludwig-Maximilian University\\%[0ex]
26 | \textsuperscript{2}Excellence Cluster Origins\\%[0ex]
27 | \vspace{-0.5ex}\textsuperscript{3}CERN
28 | }\\[2.5ex]
29 |
30 | %
31 | \insertdate
32 | \end{center}
33 | \vspace{6ex}
34 | \centering
35 | % we use minipages for the vertical centering
36 | %\fbox%
37 | \newcommand\tmp{2.6cm}
38 | \newcommand\tmpp{2.4cm}
39 | \begin{changemargin}{-1cm}{-1cm}
40 | \centering
41 | {
42 | \begin{minipage}{\tmp}
43 | \includegraphics[width=\tmpp]{figures/logos/lmu_logo.pdf}
44 | \end{minipage}
45 | }
46 | %\hspace{0.3cm}
47 | %\fbox%
48 | {
49 | \begin{minipage}{\tmp}
50 | \includegraphics[width=\tmpp]{figures/logos/cluster.pdf}
51 | \end{minipage}
52 | }%\\[2ex]
53 | % \hspace{0.3cm}
54 | %\fbox%
55 | {
56 | \begin{minipage}{\tmp}
57 | \includegraphics[width=\tmpp]{figures/logos/dfg.pdf}
58 | \end{minipage}
59 | }
60 | %\hspace{0.3cm}x
61 | {
62 | \begin{minipage}{\tmp}
63 | \includegraphics[width=\tmpp]{figures/logos/bmbf.pdf}
64 | \end{minipage}
65 | }
66 | \end{changemargin}
67 | \end{frame}
68 |
--------------------------------------------------------------------------------
/latex/input/patterns/parallel.tex:
--------------------------------------------------------------------------------
1 | \subsection{Concurrency Patterns}
2 |
3 | \frame{\tableofcontents[currentsection, currentsubsection]}
4 |
5 | \begin{frame}{Concurrency Patterns}
6 | \begin{quote}
7 | Concurrency patterns need their own lecture, so this will only quickly mention basic concepts.
8 | \end{quote}
9 |
10 | \bigskip
11 | Use cases:
12 | \begin{itemize}[]
13 | \item<2-> Manage/synchronize access to \hhl{shared resources} \srem{(e.g., to avoid race conditions when several threads perform read and write operations)}
14 | \item<3-> \hhl{Scheduling} tasks in parallel
15 | % \begin{itemize}
16 | % \item {Thread pool}
17 | % \item {Compute kernel}
18 | % \item \dots
19 | % \end{itemize}
20 | \item<4-> (A)synchronous \hhl{event handling}
21 | \end{itemize}
22 | \end{frame}
23 |
24 | \begin{frame}{Concurrency Patterns II}
25 | Advanced example: \hhl{Active object} pattern
26 |
27 | \begin{itemize}[<+->]
28 | \item Want to decouple method calling from method execution
29 | \item Can request a calculation early and check later whether the result is available
30 | \end{itemize}
31 |
32 | \bigskip
33 | The pattern consists of multiple components:
34 | \begin{itemize}[<+->]
35 | \item The \hhl{client} calls a method of a \hhl{proxy}, which (immediately) returns a \hhl{future} object \srem{(can be used to check if results are available and get them)}
36 | \item At the same time the proxy turns the method call into a \hhl{request} object and adds it to a \hhl{request queue}
37 | \item A \hhl{scheduler} takes requests from the request queue and executes it \srem{(on some thread)}
38 | \item Once the request is executed, the result is added to the future object
39 | \item Only when the client accesses the future \srem{(wants to get the result value)}, the client thread waits \srem{(if the result is already available by that time, no waiting/blocking occurs)}
40 | \end{itemize}
41 | \end{frame}
42 |
--------------------------------------------------------------------------------
/latex/header/footnote.tex:
--------------------------------------------------------------------------------
1 | % https://tex.stackexchange.com/questions/70666
2 | % -----------------------------------------------------
3 |
4 | % hide footnote:
5 |
6 | %\makeatletter
7 | %\def\beamer@autobreakframebox{%
8 | % \global\setbox\beamer@splitbox=\box\voidb@x%
9 | % \ifbeamer@autobreak%
10 | % % Ok, frame was overful -> split it!
11 | % \setbox\@tempboxa=\vsplit\beamer@framebox to\beamer@autobreakfactor\textheight%
12 | % \global\setbox\beamer@splitbox=\box\beamer@framebox%
13 | % \@tempdima=\ht\beamer@splitbox%
14 | % \ifdim\@tempdima<\beamer@autobreaklastheight%
15 | % \global\beamer@autobreaklastheight=\@tempdima\relax%
16 | % \else%
17 | % \setbox\@tempboxa=\vbox{\unvbox\@tempboxa\unvbox\beamer@splitbox}%
18 | % \global\setbox\beamer@splitbox=\box\voidb@x%
19 | % \fi%
20 | % \setbox\beamer@framebox=\vbox to\textheight{\unvbox\@tempboxa%
21 | % \vskip\beamer@framebottomskipautobreak%
22 | % \ifvoid\beamer@splitbox%
23 | % \ifvoid\beamer@footins%
24 | % \else%
25 | % \begingroup
26 | % \usebeamercolor*[fg]{footnote}%
27 | %% \footnoterule%
28 | % \unvbox \beamer@footins%
29 | % \global\setbox\beamer@footins=\box\voidb@x%
30 | % \endgroup
31 | % \fi%
32 | % \fi%
33 | % \beamer@exitcode%
34 | % }%
35 | % \else%
36 | % \setbox\beamer@framebox=\vbox to\textheight{\unvbox\beamer@framebox%
37 | % \vskip\beamer@framebottomskip%
38 | % \ifvoid\beamer@footins%
39 | % \else%
40 | % \begingroup
41 | % \usebeamercolor*[fg]{footnote}%
42 | %% \footnoterule%
43 | % \unvbox \beamer@footins%
44 | % \global\setbox\beamer@footins=\box\voidb@x%
45 | % \endgroup
46 | % \fi%
47 | % \beamer@exitcode}%
48 | % \global\setbox\beamer@footins=\box\voidb@x%
49 | % \fi%
50 | % }
51 | %\makeatother
52 | %%
53 |
54 | \renewcommand\footnoterule{\relax}
55 |
--------------------------------------------------------------------------------
/latex/header/commands/pshortcuts.tex:
--------------------------------------------------------------------------------
1 | % SMALL DEFINITIONS AND SHORTCUTS
2 | % Everything that is merely an alias and does not take
3 | % arguments and such
4 | % ###################################################
5 |
6 | % Physics
7 |
8 | %\DeclareMathOperator{\Ha}{Ha} % Hadamard operator
9 |
10 | \newcommand*{\Hilbert}{\ensuremath{\mathscr H}}
11 |
12 | % Lagrangian
13 | \newcommand*{\lag}{\mathcal L}
14 |
15 | % for lie brackets & Co
16 | \newcommand*{\rw}{\right>}
17 | \newcommand*{\lw}{\left<}
18 |
19 | % semileptonic decays
20 | \newcommand*\bdtaunu{\ensuremath{B\lra D\tau\bar\nu_\tau}}
21 | \newcommand*\bdellnu{\ensuremath{B\lra D\ell\bar\nu_\ell}}
22 | \newcommand*\bdstaunu{\ensuremath{B\lra D^*\tau\bar\nu_\tau}}
23 | \newcommand*\bdsellnu{\ensuremath{B\lra D^*\ell\bar\nu_\ell}}
24 | \newcommand*\bddstaunu{\ensuremath{B\lra D^{(*)}\tau\bar\nu_\tau}}
25 | \newcommand*\bddsellnu{\ensuremath{B\lra D^{(*)}\ell\bar\nu_\ell}}
26 |
27 |
28 | % Particles
29 |
30 | % note that we need the extra {}, else we would get problems with
31 | % e.g., \lambda_ds = \lambda_D^{*} instead of \lambda_{D^{*}}
32 | \newcommand*\dds{\ensuremath{{D^{(*)}}}}
33 | \newcommand*\ds{\ensuremath{{D^*}}}
34 | %\newcommand*\d{\ensuremath{D}}
35 |
36 | \newcommand*\Rd{\ensuremath{R(D)}}
37 | \newcommand*\Rdds{\ensuremath{R(\dds)}}
38 | \newcommand*\Rds{\ensuremath{R(\ds)}}
39 |
40 | \newcommand*\mays{^{(*)}}
41 | \newcommand*{\lh}{\mathrm{L}}
42 | \newcommand*{\rh}{\mathrm{R}}
43 | \newcommand*{\lhs}{_\mathrm{L}}
44 | \newcommand*{\rhs}{_\mathrm{R}}
45 | \newcommand*{\plh}{\ensuremath{\mathcal P_\lh}}
46 | \newcommand*{\prh}{\ensuremath{\mathcal P_\rh}}
47 |
48 | % Representation in \SUSM
49 | \newcommand*{\surep}[3]{\ensuremath{(\mathbf{#1}, \mathbf{#2})_{#3}}}
50 | \newcommand*{\suf}[2]{\nofrac #1#2}
51 |
52 | \newcommand*{\SUSM}{\ensuremath{\SU 3_C\times \SU 2_W\times \U 1_Y}}
53 |
54 | % variables
55 |
56 | % double braces to avoid double superscript error
57 | \newcommand*{\thl}{{\theta_\ell}}
58 | \newcommand*{\thds}{{\theta_{D^*}}}
59 | \newcommand*{\qtmin}{{q^2_\text{min}}}
60 | \newcommand*{\qtmax}{{q^2_\text{max}}}
61 |
62 | % Operators
63 |
64 | \DeclareMathOperator{\Br}{Br} % Branching Ratio
65 |
--------------------------------------------------------------------------------
/latex/input/patterns/careful.tex:
--------------------------------------------------------------------------------
1 | \section{Discussion}
2 |
3 | \frame{\tableofcontents[currentsection, currentsubsection]}
4 |
5 | \begin{frame}{Common criticism}
6 | %Common criticism% of programming by patterns:
7 | \only<+->{
8 | \begin{quote}
9 | \enquote{Repetitive use of the same patterns and lots of boilerplate indicates lack or abstraction or lacking features of your programming language.}
10 | \end{quote}
11 | }
12 | \begin{itemize}[<+->]
13 | \item \hhl{Example}: If functions are first-level objects \srem{(can be passed around like normal datatypes)}, I do not \srem{(always)} need to define a strategy class hierarchy. \\
14 | However, this could still be considered the same \enquote{pattern} \srem{(only with a simpler implementation)}
15 | \item The \enquote{Patterns} give you \hhl{vocabulary} to describe your problem in an abstract way, even if the implementation details very a lot between languages
16 | \item Lots of pattern boilerplate should make you think about your design and language choices
17 | \item Be aware that the implementation of \srem{(or even the need for)} certain patterns can be very dependent on your language features
18 | \end{itemize}
19 | \end{frame}
20 |
21 | \begin{frame}{Common criticism}
22 | \only<+->{
23 | \begin{quote}
24 | \enquote{Design patterns are used \hhl{excessively} and introduce \hhl{unneeded complexity}.}
25 | \end{quote}
26 | }
27 | %
28 | \begin{itemize}[<+->]
29 | %
30 | \item
31 | Remember the zen of python: simple is better than complex; but complex is better than complicated
32 | %
33 | \item
34 | Do not introduce complexity \srem{(use the design pattern)} if you do not fully understand why you need it.
35 | \item
36 | Some people highlight the KISS \srem{(\underline keep \underline it \underline simple, \underline stupid)} and YAGNI \srem{(\underline you \underline aren't \underline gonna \underline need \underline it)} principle
37 | \end{itemize}
38 | \end{frame}
39 |
40 | \begin{frame}{Common criticism}
41 | \begin{quote}
42 | \enquote{The common design patterns are often the direct results of thinking about good software design; focusing on patterns replaces actual thought with \hhl{cut-and-paste programming}.}
43 | \end{quote}
44 | \begin{itemize}
45 | \item<2-> Take discussion of patterns as a \hhl{mental practice} of thinking about good design; \stress{avoid} simple cut-and-paste
46 | \end{itemize}
47 | \end{frame}
48 |
--------------------------------------------------------------------------------
/latex/header/layout.tex:
--------------------------------------------------------------------------------
1 | % -------------- general
2 |
3 | \renewcommand\arraystretch{1.3}
4 |
5 | \setbeamertemplate{caption}[numbered]
6 |
7 |
8 | % change figure caption prefix
9 | % tex.stackexchange.com/questions/17489
10 | \addto\captionsenglish{\renewcommand{\figurename}{Fig.}}
11 |
12 |
13 | % ------------- color scheme
14 |
15 | \usetheme{Luebeck} % %Luebeck
16 | \usecolortheme{lily} % lily (dark blue black) beaver (red blue gray), dove (all white) % structure(black/white: cool but some kinks) seagull (all gray, heavy titles) orchid (lily with heavy titles) crane, seahorse dolphin crane beaver
17 |
18 | % ----------- misc beamer
19 |
20 | \setbeamercovered{dynamic}
21 | %\setbeamercovered{transparent=50}
22 |
23 | %\setbeamerfont{itemize/enumerate subbody}{size=\normalsize} %to set the body size
24 | %\setbeamerfont{itemize/enumerate subsubbody}{size=\normalsize}
25 |
26 | %\setbeamertemplate{footnote}{%
27 | % \hangpara{2.2ex}{1}%
28 | % \makebox[1.2ex][l]{\insertfootnotemark}%
29 | % \footnotesize\insertfootnotetext\par%
30 | %}
31 |
32 |
33 | % ----------------- Navigation layout -------------------------
34 |
35 | \beamertemplatenavigationsymbolsempty
36 | \setbeamertemplate{navigation symbols}{}
37 |
38 | \setbeamertemplate{headline}{%
39 | \leavevmode%
40 | \hbox{%
41 | \begin{beamercolorbox}[wd=0.4\paperwidth,ht=2.5ex,dp=1.125ex]{section in head/foot}%
42 | \insertsectionnavigationhorizontal{\paperwidth}{}{\hskip0pt plus1filll}%
43 | \end{beamercolorbox}%
44 | \begin{beamercolorbox}[wd=0.6\paperwidth,ht=2.5ex,dp=1.125ex]{subsection in head/foot}%
45 | %\centering%
46 | %\usebeamerfont{subsection in head/foot}% % title
47 | %\insertshorttitle%
48 | \insertsubsectionnavigationhorizontal{\paperwidth}{}{\hskip0pt plus1filll}%
49 | \end{beamercolorbox}%
50 | }%
51 | }
52 |
53 | \setbeamertemplate{footline}%
54 | {%
55 | \leavevmode%
56 | \hbox{%
57 | \begin{beamercolorbox}[wd=.4\paperwidth,ht=2.25ex,dp=1ex,center]{author in head/foot}%
58 | \usebeamerfont{author in head/foot}%
59 | \vfill%
60 | \flushright%
61 | \mbox{\insertauthor\hspace{1.5em}}%
62 | \end{beamercolorbox}%
63 | \begin{beamercolorbox}[wd=.6\paperwidth,ht=2.25ex,dp=1ex,center]{title in head/foot}%
64 | \flushleft \hspace{1em} \insertshorttitle%insertinstitute
65 | \hspace*{25em}%
66 | \insertframenumber{} / \inserttotalframenumber\hspace*{1ex}%
67 | \end{beamercolorbox}%
68 | }%
69 | \vskip0pt%
70 | }
71 |
--------------------------------------------------------------------------------
/latex/header/commands/dashedxarrow.tex:
--------------------------------------------------------------------------------
1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 | % tex.stackexchange.com/questions/136772
3 |
4 | \makeatletter
5 | \newcommand*{\da@rightarrow}{\mathchar"0\hexnumber@\symAMSa 4B }
6 | \newcommand*{\da@leftarrow}{\mathchar"0\hexnumber@\symAMSa 4C }
7 | \newcommand*{\xdashrightarrow}[2][]{%
8 | \mathrel{%
9 | \mathpalette{\da@xarrow{#1}{#2}{}\da@rightarrow{\,}{}}{}%
10 | }%
11 | }
12 | \newcommand{\xdashleftarrow}[2][]{%
13 | \mathrel{%
14 | \mathpalette{\da@xarrow{#1}{#2}\da@leftarrow{}{}{\,}}{}%
15 | }%
16 | }
17 | \newcommand*{\da@xarrow}[7]{%
18 | % #1: below
19 | % #2: above
20 | % #3: arrow left
21 | % #4: arrow right
22 | % #5: space left
23 | % #6: space right
24 | % #7: math style
25 | \sbox0{$\ifx#7\scriptstyle\scriptscriptstyle\else\scriptstyle\fi#5#1#6\m@th$}%
26 | \sbox2{$\ifx#7\scriptstyle\scriptscriptstyle\else\scriptstyle\fi#5#2#6\m@th$}%
27 | \sbox4{$#7\dabar@\m@th$}%
28 | \dimen@=\wd0 %
29 | \ifdim\wd2 >\dimen@
30 | \dimen@=\wd2 %
31 | \fi
32 | \count@=2 %
33 | \def\da@bars{\dabar@\dabar@}%
34 | \@whiledim\count@\wd4<\dimen@\do{%
35 | \advance\count@\@ne
36 | \expandafter\def\expandafter\da@bars\expandafter{%
37 | \da@bars
38 | \dabar@
39 | }%
40 | }%
41 | \mathrel{#3}%
42 | \mathrel{%
43 | \mathop{\da@bars}\limits
44 | \ifx\\#1\\%
45 | \else
46 | _{\copy0}%
47 | \fi
48 | \ifx\\#2\\%
49 | \else
50 | ^{\copy2}%
51 | \fi
52 | }%
53 | \mathrel{#4}%
54 | }
55 | \makeatother
56 |
57 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
58 | % simpler solution that does however only support text above the arrow
59 | % not below...
60 | %https://tex.stackexchange.com/questions/152485/long-dashed-right-arrow
61 | %\makeatletter
62 | %\newcommand{\xleftrightarrow}[2][]{\ext@arrow 3359\leftrightarrowfill@{#1}{#2}}
63 | %\newcommand{\xdashrightarrow}[2][]{\ext@arrow 0359\rightarrowfill@@{#1}{#2}}
64 | %\newcommand{\xdashleftarrow}[2][]{\ext@arrow 3095\leftarrowfill@@{#1}{#2}}
65 | %\newcommand{\xdashleftrightarrow}[2][]{\ext@arrow 3359\leftrightarrowfill@@{#1}{#2}}
66 | %\def\rightarrowfill@@{\arrowfill@@\relax\relbar\rightarrow}
67 | %\def\leftarrowfill@@{\arrowfill@@\leftarrow\relbar\relax}
68 | %\def\leftrightarrowfill@@{\arrowfill@@\leftarrow\relbar\rightarrow}
69 | %\def\arrowfill@@#1#2#3#4{%
70 | % $\m@th\thickmuskip0mu\medmuskip\thickmuskip\thinmuskip\thickmuskip
71 | % \relax#4#1
72 | % \xleaders\hbox{$#4#2$}\hfill
73 | % #3$%
74 | %}
75 | %\makeatother
76 |
--------------------------------------------------------------------------------
/latex/input/patterns/creational.tex:
--------------------------------------------------------------------------------
1 | \subsection{Creational Patterns}
2 |
3 | \frame{\tableofcontents[currentsection, currentsubsection]}
4 |
5 | \begin{frame}[t]{Factory method}
6 | \begin{quote}
7 | If there are multiple ways to instantiate objects of your class, use \hhl{factory methods} rather than adding too much logic to the default constructor.
8 | \end{quote}
9 |
10 | \medskip
11 | \only<2| handout: 1>{
12 | \stress{\badc{Bad:}}
13 | \inputminted{python}{code/patterns/creational/uncertainties_bad.py}
14 | }
15 | \only<3-4| handout: 2>{
16 | \stress{\badc{Good:}}
17 | \inputminted[]{python}{code/patterns/creational/uncertainties_good.py}
18 | }
19 | \only<4| handout: 2>{
20 | Alternatively, you can also have subclasses that provide (implementations to) factory methods.
21 | }
22 | \end{frame}
23 |
24 | \begin{frame}[t]{Builder Pattern}
25 | \begin{quote}
26 | If you build a very complex class, try to instantiate (build) it in several steps.
27 | \end{quote}
28 |
29 | \stress{\badc{Bad:}}
30 | \inputminted{python}{code/patterns/creational/builder_bad.py}
31 | \only<2>{You will probably consider different fits and plots; \hhl{violates Single Responsibility Principle} $\lra$ Rather have \texttt{Fit} and \texttt{Plot} classes}
32 | \end{frame}
33 |
34 | %\begin{frame}[t]{Builder Pattern}
35 | % \begin{quote}
36 | % If you build a very complex class, try to instantiate (build) it in several steps.
37 | % \end{quote}
38 | %
39 | % \stress{\badc{Bad:}}
40 | % \inputminted{python}{code/patterns/creational/builder_bad_2.py}
41 | %
42 | %\end{frame}
43 |
44 | \begin{frame}[t]{Builder Pattern}
45 | \begin{quote}
46 | If you build a very complex class, try to instantiate (build) it in several steps.
47 | \end{quote}
48 |
49 | \stress{\goodc{Better:}}
50 | \inputminted[]{python}{code/patterns/creational/builder_good.py}
51 | \only<2>{
52 | \begin{itemize}
53 | \item What if we have multiple ways to build of the object?
54 | \item Do I want to have the \texttt{add\_mc\_component} method after I start using the data?
55 | \end{itemize}
56 | $\lra$ Have a separate \texttt{Data} and \texttt{Builder} hierarchy.
57 | }
58 | % \only<6| handout: 3>{
59 | % \stress{\goodc{Best:}}
60 | % \inputminted{python}{code/patterns/creational/builder_best.py}
61 | % }
62 | \end{frame}
63 |
64 | \begin{frame}[t]{Builder Pattern}
65 | \begin{quote}
66 | If you build a very complex class, try to instantiate (build) it in several steps.
67 | \end{quote}
68 |
69 | \stress{\goodc{Best:}}
70 | \inputminted{python}{code/patterns/creational/builder_best.py}
71 | And of course I could now create \texttt{AbstractData} and \texttt{AbstractBuilder} etc.
72 | \end{frame}
73 |
--------------------------------------------------------------------------------
/latex/input/patterns/structural.tex:
--------------------------------------------------------------------------------
1 | \subsection{Structural Patterns}
2 |
3 | \frame{\tableofcontents[currentsection, currentsubsection]}
4 |
5 | \begin{frame}[t]{Proxy, Adapter, Facade}
6 | \bigskip
7 | Three patterns that deal with \hhl{interfaces}:
8 |
9 | \bigskip
10 | \begin{itemize}
11 | \item \hhl{Proxy}: Given a \defn{servant} class \srem{(doing the actual work)}, create a new \defn{proxy} class with the same interface in order to \hhl{inject code}.
12 | The client can then use the \texttt{Proxy} instead of using the \texttt{Service} class directly.
13 | \medskip
14 | \begin{center}
15 | \begin{tikzpicture}[scale=0.7, transform shape]
16 | \umlsimpleclass[y=1.3, x=-4]{Client}
17 |
18 | \umlsimpleclass[type=abstract, y=1.3, x=0]{OurInterface}
19 | \umluniassoc{Client}{OurInterface}
20 |
21 | \umlsimpleclass[y=0, x=-1.4]{Service}
22 | \umlsimpleclass[y=0, x=1.5]{Proxy}
23 | \umlaggreg{Proxy}{Service}
24 | \umlinherit{Proxy}{OurInterface}
25 | \umlinherit{Service}{OurInterface}
26 | \end{tikzpicture}
27 | \end{center}
28 | \medskip
29 | \only<2->{
30 | Usage examples:
31 | \begin{itemize}
32 | \item<2-> \hhl{Protection proxy}: Enforce access rights \srem{(always check authorization before method call/attribute access; e.g., in web applications)}
33 | \item<3-> \hhl{Remote proxy}: If the \texttt{Service} is located remotely, the proxy deals with transferring requests and results
34 | \item<4-> Extend the \hhl{Service} class with \hhl{caching} or \hhl{logging}
35 | \item<4-> \dots
36 | \end{itemize}
37 | }
38 | \end{itemize}
39 | \end{frame}
40 |
41 | \begin{frame}{Adapter}
42 | \begin{itemize}
43 | \item<1-> \hhl{Facade}: A class providing a simple interface for complicated operations that involve multiple servant classes
44 |
45 | \bigskip
46 | \item<2-> \hhl{Adapter}: We have a 3rd party class \texttt{ForeignClass} whose interface is incompatible to interface \texttt{OurInterface} $\lra$ Create an \defn{adapter} class as a wrapper
47 | \medskip
48 | \begin{center}
49 | \begin{tikzpicture}[scale=0.7, transform shape]
50 | \umlsimpleclass[y=1.3, x=-0.5]{Client}
51 | \umlsimpleclass[y=0, x=6.5]{ForeignClass}
52 |
53 | \umlsimpleclass[type=abstract, y=1.3, x=3]{OurInterface}
54 | \umluniassoc{Client}{OurInterface}
55 |
56 | \umlsimpleclass[y=0, x=3]{Adapter}
57 | \umlaggreg{Adapter}{ForeignClass}
58 | \umlinherit{Adapter}{OurInterface}
59 | \end{tikzpicture}
60 | \end{center}
61 | \medskip
62 | {\small Usage case example: We want to switch between different machine learning models \srem{(strategy pattern $\lra$ later)}. Our models have a \texttt{train()} method, models from a foreign library have a \texttt{training()} method $\Lra$ create adapter(s) for library}
63 | \end{itemize}
64 | \end{frame}
65 |
66 | \begin{frame}{Adapter}
67 | \inputminted{python}{code/patterns/structural/adapter.py}
68 | \end{frame}
69 |
--------------------------------------------------------------------------------
/latex/header/commands/mcommands.tex:
--------------------------------------------------------------------------------
1 | % Mathematical Functions
2 | % Definitions that are more complex than an alias
3 | % ###################################################
4 |
5 | \newcommand*{\nofrac}[2]{#1/#2}
6 |
7 | % Linear algebra
8 | % ---------------------------------------
9 |
10 | % Small cvec
11 |
12 | % transpose
13 | \newcommand*{\trans}{^\mathrm{T}}
14 |
15 | % Vectors
16 | \newcommand*{\vect}[1]{\boldsymbol{#1}}
17 |
18 | % Wrap environments into commands
19 | \newcommand*{\scvec}[1]{\begin{psmallmatrix}#1\end{psmallmatrix}}
20 | \newcommand*{\cvec}[1]{\begin{pmatrix}#1\end{pmatrix}}
21 | \newcommand*{\pmat}[1]{\begin{pmatrix}#1\end{pmatrix}}
22 | \newcommand*{\mat}[1]{\begin{matrix}#1\end{matrix}}
23 | \newcommand*{\spmat}[1]{\begin{psmallmatrix}#1\end{psmallmatrix}}
24 |
25 | % MISC
26 | % ---------------------------------------
27 |
28 | % Nonbreaking dash for stuff like $n$-dimensional:
29 | \newcommand*{\ndash}{\nobreakdash-\hspace{0pt}}
30 |
31 | % Spacing in Math mode by \back{10}
32 | \newcommand*{\back}[1]{\mspace{-#1mu}}
33 |
34 | %% Restriction of a function
35 | %\newcommand*\restr[2]{{% we make the whole thing an ordinary symbol
36 | % \left.\kern-\nulldelimiterspace % automatically resize the bar with \right
37 | % #1 % the function
38 | % \vphantom{\big|} % pretend it's a little taller at normal size
39 | % \right|_{#2} % this is the delimiter
40 | % }}
41 |
42 |
43 | \newcommand{\xdownarrow}[1]{%
44 | {\left\downarrow\vbox to #1{}\right.\kern-\nulldelimiterspace}
45 | }
46 |
47 | %
48 | % ANALYSIS
49 | % ---------------------------------------
50 |
51 | %\newcommand*\ddiff[2]{\frac{\mathrm{d}#1}{\mathrm{d}#2}}
52 | %\newcommand*\pardiff[2]{\frac{\partial#1}{\partial#2}}
53 | %\newcommand*\vardiff[2]{\frac{\delta#1}{\delta#2}}
54 |
55 |
56 | % SLIGHTLY MORE COMPLICATED STUFF
57 | % --------------------------------
58 |
59 | % Kerning of \defeq
60 | % credit: http://tex.stackexchange.com/questions/4216/how-to-typeset-correctly
61 | % normal
62 | % \newcommand*{\defeq }{:=}
63 | % zentriert (funktioniert nicht bei kleinerer Schriftgröße!!)
64 | % \makeatletter
65 | % \newcommand*{\defeq}{\mathrel{\rlap{%
66 | % \raisebox{0.3ex}{$\m@th\cdot$}}%
67 | % \raisebox{-0.3ex}{$\m@th\cdot$}}%
68 | % =}
69 | % \makeatother
70 | % Für Kleine Punkte (selbe Linienstärke wie "="), einfach
71 | % die beiden "." in den hboxes durch "\scriptsize." ersetzen
72 | \newcommand*{\defeq}{
73 | \mathrel{\vcenter{
74 | \baselineskip0.5ex
75 | \lineskiplimit0pt
76 | \hbox{.}
77 | \hbox{.}
78 | }}
79 | =
80 | }
81 | \newcommand*{\eqdef}{ =
82 | \mathrel{\vcenter{
83 | \baselineskip0.5ex
84 | \lineskiplimit0pt
85 | \hbox{.}
86 | \hbox{.}
87 | }}
88 | }
89 |
--------------------------------------------------------------------------------
/latex/header/beamer_struct.tex:
--------------------------------------------------------------------------------
1 | % GENERAL COLOR DEFINITIONS
2 | % %%%%%%%%%%%%%%%%%%%%%%%%
3 |
4 | \definecolor{bittersweet}{rgb}{1.0, 0.44, 0.37}
5 | \definecolor{cadet}{rgb}{0.33, 0.41, 0.47} % greenish
6 | \definecolor{darkspringgreen}{rgb}{0.09, 0.45, 0.27}
7 |
8 | % TOPICAL MARKUP STYLES
9 | %%%%%%%%%%%%%%%%%%%%%%%
10 |
11 | % General
12 |
13 | \newcommand*{\remarkc}{\color[gray]{0.35}}
14 | \newcommand*{\srem}[1]{{\small{\remarkc #1}}}
15 |
16 | \newcommand*{\hhl}[1]{{\color{purple}#1}}
17 | \newcommand*{\hl}[1]{{\usebeamercolor[fg]{structure}#1}}
18 | \newcommand*{\defn}[1]{\emph{#1}}
19 | \newcommand*{\hldefn}[1]{\hhl{\emph{#1}}}
20 |
21 | \newcommand*{\mauthor}[1]{{\color{PineGreen}#1}}
22 | \newcommand*{\pastcolor}{\color[gray]{0.4}}
23 |
24 | \newcommand{\referencec}{\color{purple}}
25 | \newcommand*{\reference}[2]{{\referencec\href{#1}{#2}}}
26 |
27 | %
28 |
29 | \newcommand*{\proglang}[1]{{\texttt{#1}}}
30 |
31 | % ClusterKinG colors
32 |
33 | \definecolor{ckBlue}{RGB}{14, 85, 156}
34 | \definecolor{ckRed}{RGB}{216, 16, 44}
35 | \definecolor{ckYellow}{RGB}{242, 165, 6}
36 |
37 | \newcommand{\ckBlue}{\color{ckBlue}}
38 | \newcommand{\ckRed}{\color{ckRed}}
39 | \newcommand{\ckYellow}{\color{ckYellow}}
40 | \newcommand{\clusterking}{\ckBlue Cluster\ckRed Kin \ckYellow G}
41 |
42 | % Good and bad
43 |
44 | \newcommand{\badc}[1]{{\color{purple}#1}}
45 | \newcommand{\goodc}[1]{{\color{PineGreen}#1}}
46 |
47 |
48 | % Colors for formulas
49 |
50 | \newcommand*{\hlcolor}{\color{purple}}
51 | \newcommand*{\knownc}{\color{PineGreen}}
52 | \newcommand*{\unknownc}{\color{purple}}
53 | \newcommand*{\measuredc}{\color{RoyalBlue}}
54 | \newcommand*{\calculatedc}{\color{Fuchsia}}
55 |
56 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57 |
58 | % center vertically in line of text
59 | % adapted from tex.stackexchange.com/questions/433/
60 | \newcommand{\vcenteredinclude}[1]{%
61 | \begingroup%
62 | \setbox0=\hbox{#1}%
63 | \parbox{\wd0}{\box0}%
64 | \endgroup
65 | }
66 |
67 | \newcommand*{\figurereference}[2]{%
68 | \vcenteredinclude{%
69 | {\tiny [\reference{#1}{#2}]}%
70 | }%
71 | }
72 |
73 | \newcommand*{\stress}[1]{\textbf{#1}}
74 |
75 |
76 | \newcommand\todo[1]{{\color{red} #1}}
77 | \newcommand\ecite[1]{\textsuperscript{\cite{#1}}}
78 |
79 | %%%%
80 |
81 | \newcommand{\jiraOpen}[1]{
82 | {
83 | \color{purple}
84 | \href{https://agira.desy.de/browse/#1}{#1}
85 | }
86 | }
87 | \newcommand{\jiraClosed}[1]{
88 | {
89 | \color{purple}
90 | \sout{\href{https://agira.desy.de/browse/#1}{#1}}
91 | }
92 | }
93 | \newcommand{\commit}[1]{
94 | {
95 | \small
96 | \color{RoyalBlue}
97 | \href{https://stash.desy.de/projects/B2/repos/software/commits/#1}{\texttt{#1}}
98 | }
99 | }
100 | \newcommand{\pr}[1]{
101 | {
102 | \small
103 | \color{bittersweet}
104 | \href{https://stash.desy.de/projects/B2/repos/software/pull-requests/#1/overview}{PR#1}
105 | }
106 | }
107 |
108 | % ------------
109 |
110 | % -------- minted
111 |
112 | \usepackage[outputdir=build]{minted}
113 | \setminted[python]{
114 | mathescape,
115 | linenos,
116 | numbersep=5pt,
117 | gobble=0,
118 | frame=lines,
119 | fontsize=\small,
120 | framesep=2mm,
121 | tabsize=4
122 | }
123 |
--------------------------------------------------------------------------------
/latex/header/commands/mshortcuts.tex:
--------------------------------------------------------------------------------
1 | % SMALL DEFINITIONS AND SHORTCUTS
2 | % ###################################################
3 | % Everything that is merely an alias and does not take
4 | % arguments and such
5 |
6 | % Math Operators & Co
7 | % ---------------------------------------
8 |
9 | % MISC
10 |
11 | \newcommand*{\const}{\mathrm{const}}
12 | \newcommand*{\ub}[1]{\underbrace{#1}}
13 | \newcommand*{\ol}[1]{\overline{#1}}
14 |
15 | % Linear Algebra
16 |
17 | \DeclareMathOperator{\id}{id}
18 | \DeclareMathOperator{\tr}{tr}
19 | \def\transp{^t}
20 | \DeclareMathOperator{\diag}{diag}
21 | %\newcommand*{\vec}[1]{\mathbf{#1}}
22 |
23 | % Lie Algebras & Co
24 |
25 | \DeclareMathOperator{\ad}{ad}
26 | \DeclareMathOperator{\Ad}{Ad}
27 | \newcommand*{\gfrak}{\ensuremath{\mathfrak g}}
28 |
29 | % Symmetry groups
30 |
31 | \newcommand*{\SU}[1]{\ensuremath{\mathsf{SU(#1)}}}
32 | \newcommand*{\SO}[1]{\ensuremath{\mathsf{SO(#1)}}}
33 | \newcommand*{\su}[1]{\ensuremath{\mathfrak{su}(#1)}}
34 | %\newcommand*{\U}[1]{\ensuremath{\mathsf{U(#1)}}}
35 | \newcommand*{\GL}[1]{\ensuremath{\mathsf{GL} (#1)}}
36 |
37 | % Probability
38 | \DeclareMathOperator{\Var}{Var}
39 |
40 | % Vector Analysis
41 |
42 | \DeclareMathOperator{\rot}{rot}
43 |
44 | % Functional Analysis
45 |
46 | %\DeclareMathOperator{\res}{res}
47 | %\DeclareMathOperator{\Res}{Res}
48 | %\DeclareMathOperator{\ord}{ord}
49 | %\DeclareMathOperator{\Ord}{Ord}
50 |
51 | % Complex numbers
52 | % Re and Im are already defined :(
53 | \let\Re\relax
54 | \let\Im\relax
55 | \DeclareMathOperator{\Re}{Re}
56 | \DeclareMathOperator{\Im}{Im}
57 | \newcommand*{\ii}{\mathrm{i}}
58 |
59 | \newcommand*{\e}{\mathrm{e}}
60 |
61 | % Kerning of \divides
62 | % \newcommand*{\divides}{\mspace{2mu}|\mspace{2mu}}
63 |
64 | % analysis
65 | \newcommand*{\dd}{\mathop{}\!\mathrm d}
66 | \newcommand*{\dis}{\mathrm d}
67 |
68 | % ...
69 |
70 | \newcommand*{\Order}[1]{\ensuremath{\mathcal O\left(#1\right)}}
71 | \newcommand*{\order}[1]{\ensuremath{\mathcal o\left(#1\right)}}
72 |
73 |
74 | % mathbbs
75 | % ---------------------------------------
76 |
77 | \newcommand*{\Cbb}{\ensuremath{\mathbb C}}
78 | \newcommand*{\Rbb}{\ensuremath{\mathbb R}}
79 | \newcommand*{\Zbb}{\ensuremath{\mathbb Z}}
80 | \newcommand*{\Nbb}{\ensuremath{\mathbb N}}
81 | \newcommand*{\obb}{\ensuremath{\mathbbm 1}}
82 |
83 | % arrows
84 | % ---------------------------------------
85 |
86 | \newcommand*{\lra}{\ensuremath{\longrightarrow}}
87 | \newcommand*{\lla}{\ensuremath{\longleftarrow}}
88 | \newcommand*{\llra}{\ensuremath{\longleftrightarrow}}
89 |
90 | \newcommand*{\qlra}{\ensuremath{\quad\longrightarrow\quad}}
91 | \newcommand*{\qlla}{\ensuremath{\quad\longleftarrow\quad}}
92 | \newcommand*{\qllra}{\ensuremath{\quad\longleftrightarrow\quad}}
93 |
94 | \newcommand*{\qqlra}{\ensuremath{\qquad\longrightarrow\qquad}}
95 | \newcommand*{\qqlla}{\ensuremath{\qquad\longleftarrow\qquad}}
96 | \newcommand*{\qqllra}{\ensuremath{\qquad\longleftrightarrow\qquad}}
97 |
98 | \newcommand*{\Lra}{\ensuremath{\Longrightarrow}}
99 | \newcommand*{\Lla}{\ensuremath{\Longleftarrow}}
100 | \newcommand*{\Llra}{\ensuremath{\Longleftrightarrow}}
101 |
102 | \newcommand*{\qLra}{\ensuremath{\quad\Longrightarrow\quad}}
103 | \newcommand*{\qLla}{\ensuremath{\quad\Longleftarrow\quad}}
104 | \newcommand*{\qLlra}{\ensuremath{\quad\Longleftrightarrow\quad}}
105 |
106 | \newcommand*{\qqLra}{\ensuremath{\qquad\Longrightarrow\qquad}}
107 | \newcommand*{\qqLla}{\ensuremath{\qquad\Longleftarrow\qquad}}
108 | \newcommand*{\qqLlra}{\ensuremath{\qquad\Longleftrightarrow\qquad}}
109 |
110 | \newcommand*{\quiff}{\ensuremath{\quad\Longleftrightarrow\quad}}
111 | \newcommand*{\qquiff}{\ensuremath{\qquad\Longleftrightarrow\qquad}}
112 |
113 | \newcommand*{\lmt}{\ensuremath{\longmapsto}}
114 |
115 | \newcommand*{\quand}{\quad\text{and}\quad}
116 | \newcommand*{\qquand}{\qquad\text{and}\qquad}
117 |
--------------------------------------------------------------------------------
/latex/input/paradigms/declarative.tex:
--------------------------------------------------------------------------------
1 | \subsection[Declarative vs Imperative]{Declarative vs Imperative Programming}
2 |
3 | \frame{\tableofcontents[currentsection, currentsubsection]}
4 |
5 | \begin{frame}[t]{Declarative vs imperative programming}
6 |
7 | \bigskip
8 | \only<1->{\hhl{Declarative programming}:
9 | \begin{itemize}
10 | \item Program describes \hl{logic} rather than \hl{control flow}
11 | \item Program describes \hl{\enquote{what}} rather than \hl{\enquote{how}}
12 | %\item Focus on \hl{description} rather than \hl{implementation}
13 | \item Aims for correspondence with mathematical logic
14 | \item \hl{FP} is usually considered a subcategory
15 | \end{itemize}
16 | }
17 |
18 | \only<2>{
19 | \medskip
20 | Opposite: \hhl{imperative programming}:
21 | \begin{itemize}
22 | \item Algorithms as a sequence of steps
23 | \item Often used synonymously: \hhl{procedural programming} \srem{(emphasizing the concept of using procedure calls (functions) to structure the program in a modular fashion)}
24 | \item \hl{OOP} is usually considered a subcategory
25 | \end{itemize}
26 | }
27 | \end{frame}
28 |
29 | \begin{frame}{Examples}
30 | \enquote{Pure} declarative languages:
31 | \begin{itemize}
32 | \item \proglang{SQL} \srem{(Structured Query Language -- language to interact with databases)}:
33 | %
34 | \begin{center}
35 | \mintinline{SQL}{SELECT * FROM Customers WHERE Country='Mexico';}
36 | \end{center}
37 | \item \hhl{Markup languages}, like \proglang{HTML}, \proglang{CSS} \srem{(Cascading Style Sheets -- language to describe styling of e.g., HTML pages)}, \dots
38 | %
39 | \begin{center}
40 | \mintinline{HTML}{
This is a Blue Heading
41 | }
42 | \end{center}
43 | \item Functional programming languages like \proglang{Haskell} \srem{(even though they allow some \enquote{encapsulated} imperative parts)}
44 | \item \dots
45 | \end{itemize}
46 | \end{frame}
47 | %
48 | \begin{frame}{Powerful backends I}
49 | Idea:
50 | \begin{itemize}
51 | \item Split up your code into \hhl{application/analysis specific code} \srem{(describing the problem)} and a \hhl{backend/library} \srem{(implementing solution strategies)}
52 | \item The application specific code starts to \emph{feel} very \hhl{declarative}
53 | \item The backend can use different strategies depending on the nature/scale of the problem
54 | \end{itemize}
55 | \end{frame}
56 | %
57 | \begin{frame}{Powerful backends II}
58 | Example:
59 | \inputminted{python}{code/paradigms/dp/dataframes.py}
60 | \end{frame}
61 | %
62 | %
63 | \begin{frame}{Powerful backends III}
64 | \begin{itemize}
65 | \item We might want even more of our backend, e.g., delayed or distributed execution
66 | \item \texttt{pandas} can also be viewed as a \enquote{declarative language} describing the problem $\lra$ have a more sophisticated backend handle all operations $\lra$ \hhl{\texttt{modin pandas}}
67 |
68 | \includegraphics[width=8cm, trim=0cm 2.5cm 0cm 2.5cm, clip]{figures/paradigms/dp/modin_architecture.png}
69 | %
70 | % \item \proglang{ROOT} can also do dataframes: \texttt{RDataFrame}
71 | \end{itemize}
72 | \end{frame}
73 | %
74 | \begin{frame}{Powerful backends IV}
75 | Belle II steering file:
76 | \inputminted{python}{code/paradigms/dp/belle2_steering_file.py}
77 | %Many new things coming specifically for HEP, e.g., LINQToROOT
78 | \end{frame}
79 | %
80 | \begin{frame}{Powerful backends V}
81 | Many more high level tools available:
82 | \smallskip
83 | \begin{itemize}
84 | \item LINQtoROOT: Uses \proglang{C\#} with \proglang{LINQ} \srem{(\proglang{SQL} like)} queries to describe problem
85 | \inputminted[fontsize=\small]{csharp}{code/paradigms/dp/linqtoroot.cs}
86 | \item The FAST HEP toolkit: Uses yaml config files to describe problem; using pandas, numpy, etc. in the backend
87 | \inputminted[fontsize=\small]{yaml}{code/paradigms/dp/fast.yaml}
88 | \item Many more\dots
89 | \end{itemize}
90 | \end{frame}
91 |
--------------------------------------------------------------------------------
/latex/input/paradigms/oo.tex:
--------------------------------------------------------------------------------
1 |
2 | \frame{\tableofcontents[currentsection, currentsubsection]}
3 |
4 | \subsection[Object Oriented]{Object Oriented Programming}
5 |
6 | \frame{\tableofcontents[currentsection, currentsubsection]}
7 |
8 | \begin{frame}{OOP: Idea}
9 |
10 | \begin{itemize}
11 | \item Before OOP: Two \stress{separate} entities: \emph{data} and \emph{functions} (logic)
12 | \item Inspiration: In the {real world}, {objects} have a \enquote{state} (data) and \enquote{behaviors} (functions)
13 | \end{itemize}
14 |
15 | \begin{block}{OOP}
16 | \begin{itemize}
17 | \item \stress{Think} in terms of \hldefn{objects} that contain data and offer \hldefn{methods} (functions that operate on objects) $\lra$ Data and functions form a unit
18 | \item \stress{Focus} on object structure rather than manipulation logic
19 | \item \stress{Organize} your code in \hldefn{classes} (blueprints for objects): Every object is \defn{instance} of its class
20 | \end{itemize}
21 | \end{block}
22 | %idea, ..., formal definition, history?
23 | \end{frame}
24 |
25 | \begin{frame}[t]{A basic class in python}
26 | \only<1| handout:0>{\inputminted[lastline=4]{python}{code/paradigms/oop/class_rectangle.py}}
27 | \only<2| handout:0>{\inputminted[lastline=8]{python}{code/paradigms/oop/class_rectangle.py}}
28 | \only<3>{\inputminted[]{python}{code/paradigms/oop/class_rectangle.py}}
29 | \end{frame}
30 |
31 | \begin{frame}[fragile]{Encapsulation and data hiding}
32 | % data hiding provides security and avoids data corruption
33 | %Remember: ... separate interface from implementation ... $\lra$ hide internals
34 |
35 | \begin{itemize}
36 | \item \hl{Do not expose object internals that may change in the future} $\lra$ Make certain attributes and methods \hhl{private} (\defn{data hiding})
37 | \item Rephrased: Separate \hhl{interface} (won't be touched because it's used by others) from \hhl{implementation} (might change)
38 | \item In some languages this is \enquote{enforced} (e.g., using the \verb|private| keyword), in others it is denoted by naming conventions (e.g., leading underscore)
39 | \end{itemize}
40 | \end{frame}
41 |
42 | \begin{frame}[t]{Subclasses and Inheritance}
43 | \only<1->{\hldefn{Subclasses} are specializations of a class
44 | \begin{itemize}
45 | \item inherit attributes/methods of their superclass
46 | \item can introduce new attributes/methods
47 | \item can override methods of superclass
48 | \end{itemize}
49 | }
50 | \only<2| handout:0>{\inputminted[fontsize=\footnotesize, lastline=6]{python}{code/paradigms/oop/class_inheritance.py}}
51 | \only<3>{\inputminted[fontsize=\footnotesize]{python}{code/paradigms/oop/class_inheritance.py}}
52 | \end{frame}
53 |
54 | \begin{frame}[t]{Abstract methods}
55 | \begin{columns}[t]
56 | \column{0.5\textwidth}
57 | \begin{itemize}
58 | \item An \hldefn{abstract method} is a method that has to be implemented by a subclass
59 | \item<2-> An \hldefn{abstract class} (\hldefn{abstract type}) is a class that cannot be instantiated directly but it might have \hldefn{concrete subclasses} that can
60 | \item<3-> Use abstract classes to \hl{enforce interfaces} for the concrete classes
61 | \end{itemize}
62 | \column{0.5\textwidth}
63 | \only<1| handout:0>{\inputminted[fontsize=\small, lastline=11]{python}{code/paradigms/oop/class_abstract.py}}
64 | \only<2->{\inputminted[fontsize=\small]{python}{code/paradigms/oop/class_abstract.py}}
65 | \end{columns}
66 | \end{frame}
67 |
68 | %\begin{frame}{Class methods, class variables}
69 | % Since this almost only has relevance for using creator patterns, it might be moved to lecture 2
70 | % \begin{itemize}
71 | % \item class methods only have access to class variables and other class methods
72 | % \item important use case: to provide other constructors
73 | % \end{itemize}
74 | %\end{frame}
75 |
76 | \begin{frame}{Strengths and Weaknesses}
77 |
78 | \begin{block}{Strengths}
79 | \only<+->{}
80 | \begin{itemize}
81 | \item<+-> \hhl{Easy to read} and understand if done well (very natural way of thinking if classes model real world objects)
82 | \item<+-> Natural way to \hhl{structure large projects} (e.g., taking classes as components)
83 | \item<+-> Very \hhl{wide spread} way of thinking
84 | \item<+-> Especially applicable to problems that center around data and bookkeeping with logic that is strongly tied to the data
85 | \end{itemize}
86 | \end{block}
87 | \begin{block}{Weaknesses}
88 | \begin{itemize}
89 | \item<+-> Wrong abstractions can lead to less \hhl{code reusability}
90 | \item<+-> \hhl{Lasagna code}: Too many layers of classes can be hard to understand
91 | \item<+-> Can be hard to \hhl{parallelize} if many entangled and interdependent classes with shared mutable states are involved \srem{($\lra$ if required, should be design requirement from the start; \defn{parallel patterns} address some difficulties)}
92 | \end{itemize}
93 | \end{block}
94 | \end{frame}
95 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .~lock*
2 | exam.md
3 | **/.ipynb_checkpoints/**
4 |
5 | # Created by https://www.toptal.com/developers/gitignore/api/latex
6 | # Edit at https://www.toptal.com/developers/gitignore?templates=latex
7 |
8 | ### LaTeX ###
9 | ## Core latex/pdflatex auxiliary files:
10 | *.aux
11 | *.lof
12 | *.log
13 | *.lot
14 | *.fls
15 | *.out
16 | *.toc
17 | *.fmt
18 | *.fot
19 | *.cb
20 | *.cb2
21 | .*.lb
22 |
23 | ## Intermediate documents:
24 | *.dvi
25 | *.xdv
26 | *-converted-to.*
27 | # these rules might exclude image files for figures etc.
28 | # *.ps
29 | # *.eps
30 | # *.pdf
31 |
32 | ## Generated if empty string is given at "Please type another file name for output:"
33 | .pdf
34 |
35 | ## Bibliography auxiliary files (bibtex/biblatex/biber):
36 | *.bbl
37 | *.bcf
38 | *.blg
39 | *-blx.aux
40 | *-blx.bib
41 | *.run.xml
42 |
43 | ## Build tool auxiliary files:
44 | *.fdb_latexmk
45 | *.synctex
46 | *.synctex(busy)
47 | *.synctex.gz
48 | *.synctex.gz(busy)
49 | *.pdfsync
50 |
51 | ## Build tool directories for auxiliary files
52 | # latexrun
53 | latex.out/
54 |
55 | ## Auxiliary and intermediate files from other packages:
56 | # algorithms
57 | *.alg
58 | *.loa
59 |
60 | # achemso
61 | acs-*.bib
62 |
63 | # amsthm
64 | *.thm
65 |
66 | # beamer
67 | *.nav
68 | *.pre
69 | *.snm
70 | *.vrb
71 |
72 | # changes
73 | *.soc
74 |
75 | # comment
76 | *.cut
77 |
78 | # cprotect
79 | *.cpt
80 |
81 | # elsarticle (documentclass of Elsevier journals)
82 | *.spl
83 |
84 | # endnotes
85 | *.ent
86 |
87 | # fixme
88 | *.lox
89 |
90 | # feynmf/feynmp
91 | *.mf
92 | *.mp
93 | *.t[1-9]
94 | *.t[1-9][0-9]
95 | *.tfm
96 |
97 | #(r)(e)ledmac/(r)(e)ledpar
98 | *.end
99 | *.?end
100 | *.[1-9]
101 | *.[1-9][0-9]
102 | *.[1-9][0-9][0-9]
103 | *.[1-9]R
104 | *.[1-9][0-9]R
105 | *.[1-9][0-9][0-9]R
106 | *.eledsec[1-9]
107 | *.eledsec[1-9]R
108 | *.eledsec[1-9][0-9]
109 | *.eledsec[1-9][0-9]R
110 | *.eledsec[1-9][0-9][0-9]
111 | *.eledsec[1-9][0-9][0-9]R
112 |
113 | # glossaries
114 | *.acn
115 | *.acr
116 | *.glg
117 | *.glo
118 | *.gls
119 | *.glsdefs
120 | *.lzo
121 | *.lzs
122 |
123 | # uncomment this for glossaries-extra (will ignore makeindex's style files!)
124 | # *.ist
125 |
126 | # gnuplottex
127 | *-gnuplottex-*
128 |
129 | # gregoriotex
130 | *.gaux
131 | *.glog
132 | *.gtex
133 |
134 | # htlatex
135 | *.4ct
136 | *.4tc
137 | *.idv
138 | *.lg
139 | *.trc
140 | *.xref
141 |
142 | # hyperref
143 | *.brf
144 |
145 | # knitr
146 | *-concordance.tex
147 | # TODO Uncomment the next line if you use knitr and want to ignore its generated tikz files
148 | # *.tikz
149 | *-tikzDictionary
150 |
151 | # listings
152 | *.lol
153 |
154 | # luatexja-ruby
155 | *.ltjruby
156 |
157 | # makeidx
158 | *.idx
159 | *.ilg
160 | *.ind
161 |
162 | # minitoc
163 | *.maf
164 | *.mlf
165 | *.mlt
166 | *.mtc[0-9]*
167 | *.slf[0-9]*
168 | *.slt[0-9]*
169 | *.stc[0-9]*
170 |
171 | # minted
172 | _minted*
173 | *.pyg
174 |
175 | # morewrites
176 | *.mw
177 |
178 | # newpax
179 | *.newpax
180 |
181 | # nomencl
182 | *.nlg
183 | *.nlo
184 | *.nls
185 |
186 | # pax
187 | *.pax
188 |
189 | # pdfpcnotes
190 | *.pdfpc
191 |
192 | # sagetex
193 | *.sagetex.sage
194 | *.sagetex.py
195 | *.sagetex.scmd
196 |
197 | # scrwfile
198 | *.wrt
199 |
200 | # sympy
201 | *.sout
202 | *.sympy
203 | sympy-plots-for-*.tex/
204 |
205 | # pdfcomment
206 | *.upa
207 | *.upb
208 |
209 | # pythontex
210 | *.pytxcode
211 | pythontex-files-*/
212 |
213 | # tcolorbox
214 | *.listing
215 |
216 | # thmtools
217 | *.loe
218 |
219 | # TikZ & PGF
220 | *.dpth
221 | *.md5
222 | *.auxlock
223 |
224 | # todonotes
225 | *.tdo
226 |
227 | # vhistory
228 | *.hst
229 | *.ver
230 |
231 | # easy-todo
232 | *.lod
233 |
234 | # xcolor
235 | *.xcp
236 |
237 | # xmpincl
238 | *.xmpi
239 |
240 | # xindy
241 | *.xdy
242 |
243 | # xypic precompiled matrices and outlines
244 | *.xyc
245 | *.xyd
246 |
247 | # endfloat
248 | *.ttt
249 | *.fff
250 |
251 | # Latexian
252 | TSWLatexianTemp*
253 |
254 | ## Editors:
255 | # WinEdt
256 | *.bak
257 | *.sav
258 |
259 | # Texpad
260 | .texpadtmp
261 |
262 | # LyX
263 | *.lyx~
264 |
265 | # Kile
266 | *.backup
267 |
268 | # gummi
269 | .*.swp
270 |
271 | # KBibTeX
272 | *~[0-9]*
273 |
274 | # TeXnicCenter
275 | *.tps
276 |
277 | # auto folder when using emacs and auctex
278 | ./auto/*
279 | *.el
280 |
281 | # expex forward references with \gathertags
282 | *-tags.tex
283 |
284 | # standalone packages
285 | *.sta
286 |
287 | # Makeindex log files
288 | *.lpz
289 |
290 | # xwatermark package
291 | *.xwm
292 |
293 | # REVTeX puts footnotes in the bibliography by default, unless the nofootinbib
294 | # option is specified. Footnotes are the stored in a file with suffix Notes.bib.
295 | # Uncomment the next line to have this generated file ignored.
296 | #*Notes.bib
297 |
298 | ### LaTeX Patch ###
299 | # LIPIcs / OASIcs
300 | *.vtc
301 |
302 | # glossaries
303 | *.glstex
304 |
305 | # End of https://www.toptal.com/developers/gitignore/api/latex
306 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Programming Paradigms and Patterns
2 |
3 | [](https://zenodo.org/badge/latestdoi/240011587)
4 | [](https://results.pre-commit.ci/latest/github/klieret/icsc-paradigms-and-patterns/master)
5 | [](https://github.com/klieret/icsc-paradigms-and-patterns/actions)
6 | [](https://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project)
7 |
8 | This repository contains lecture slides (both as source code and as rendered pdfs)
9 | and exercises.
10 |
11 | The course was first taught in September/October 2020 at the [iCSC 2020](https://indico.cern.ch/event/853710/).
12 |
13 | **Recordings** of the lectures:
14 |
15 | * [Programming Paradigms](https://cds.cern.ch/record/2736118)
16 | * [Software Design Patterns](https://cds.cern.ch/record/2737225)
17 |
18 | **Slides**: The final versions of the rendered slides at the time of the presentation are in the root directory of this repository. There are two versions, one with animations and one without (``*_handout.pdf``).
19 |
20 | **Exercises**: See below.
21 |
22 | ## Getting help
23 |
24 | During the event, there are two channels on CERN mattermost (you might need to create a CERN lightweight account, which is free for everyone):
25 |
26 | * [Programming Paradigms](https://mattermost.web.cern.ch/csc/channels/programming-paradigms)
27 | * [Software Design Patterns](https://mattermost.web.cern.ch/csc/channels/software-design)
28 |
29 | After the event, you can open an issue in this repository.
30 |
31 | ## Running the exercises
32 |
33 | The exercises come with solutions for you to compare to. If you have any questions, please join the exercise discussion slot.
34 |
35 | If you're completely new to this, use option 1 or 2. If you already have python and Jupyter set up on your computer, we recommend option 3. Note that your changes are not saved automatically in the first two options!
36 |
37 | ### Option 1: Using binder
38 |
39 | This means you don't have to install anything, but you can simply use the binder service
40 | to provide you with a Jupyter environment in your browser.
41 | It might be a bit slow to start up, but once it's running you're ready to go!
42 |
43 | Simply click on the following link:
44 |
45 | [](https://mybinder.org/v2/gh/klieret/icsc-paradigms-and-patterns/master)
46 |
47 | You should see something like this:
48 |
49 | 
50 |
51 | After some time (don't worry if it takes 5 minutes) you are brought to the Jupyter server:
52 |
53 | 
54 |
55 | Navigate on ``exercises`` and then click on one of the two notebooks (``patterns.ipynb`` or ``paradigms.ipynb``) to start your training!
56 |
57 | If you've never use Jupyter notebook, you can also do [this training](https://mybinder.org/v2/gh/ipython/ipython-in-depth/master?filepath=binder/Index.ipynb) or take a look at [the documentation](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html). But basically you can execute a cell by hitting ``Shift+Enter`` and add cells with the menu.
58 |
59 | ### Option 2: Google colab
60 |
61 | Simply click the link (you need to log in to your google account though)
62 |
63 | * [Programming Paradigms ](https://colab.research.google.com/github/klieret/icsc-paradigms-and-patterns/blob/master/exercises/paradigms.ipynb)
64 | * [Software Design Patterns ](https://colab.research.google.com/github/klieret/icsc-paradigms-and-patterns/blob/master/exercises/patterns.ipynb)
65 |
66 | If you've never used Google colab, you can also go to [this page](https://colab.research.google.com/notebooks/intro.ipynb) and try it out (but it's very similar to Jupyter notebooks if you're familiar with that).
67 |
68 | ### Option 3: Local run
69 |
70 | You need to have python3 and its package manager pip3.
71 |
72 | Clone the repository
73 |
74 | ```sh
75 | git clone git@github.com:klieret/icsc-paradigms-and-patterns.git
76 | cd icsc-paradigms-and-patterns
77 | ```
78 |
79 | Make sure you have the required python packages:
80 |
81 | ```sh
82 | pip3 install -r requirements.txt
83 | ```
84 |
85 | Then run the Jupyter notebook
86 |
87 | ```sh
88 | jupyter-notebook
89 | ```
90 |
91 | It should open in your browser.
92 |
93 | ## Generating lecture slides from source
94 |
95 | You need to use [XeLaTeX](https://en.wikipedia.org/wiki/XeTeX):
96 |
97 | ```sh
98 | cd latex
99 | mkdir -p build && xelatex --output-directory build -shell-escape software_patterns.tex
100 | mkdir -p build && xelatex --output-directory build -shell-escape programming_paradigms.tex
101 | ```
102 |
103 | The ``-shell-escape`` flag is needed for code highlighting. You might need to install
104 | the pygments package.
105 |
106 | The slides work with overlays (partial reveals of bullet points and other elements).
107 | As this is less practical for studying yourself, take a look at the main ``.tex`` file
108 | and change ``\handoutfalse`` to ``\handouttrue`` if needed.
109 |
110 | ## Developing this further
111 |
112 | We are planning to convert this into a training similar to that of the [Software Carpentry](https://software-carpentry.org/) in order to be included in the [HSF curriculum](https://hepsoftwarefoundation.org/training/curriculum.html). Help is much appreciated.
113 |
114 | If you have any particular comments, feel free to open an issue on github for this repository.
115 |
116 | ## Citation & License
117 |
118 | Licensed as CC BY 4.0, see file ``license.md``. Please use the following zenodo ID to cite this
119 | work:
120 |
121 | [](https://zenodo.org/badge/latestdoi/240011587)
122 |
--------------------------------------------------------------------------------
/latex/input/paradigms/structure.tex:
--------------------------------------------------------------------------------
1 | \section{Overview}
2 |
3 | \begin{frame}{Overview}
4 |
5 | \begin{itemize}
6 | \item Two lecture course:
7 | \begin{itemize}
8 | \item Part 1: Programming Paradigms
9 | \item Part 2: Object oriented design patterns
10 | \end{itemize}
11 | \item All material at: \hhl{\href{https://github.com/klieret/icsc-paradigms-and-patterns}{github.com/klieret/icsc-paradigms-and-patterns}}
12 | \item Feedback \& PRs welcome
13 | \end{itemize}
14 |
15 | \bigskip
16 | \begin{block}{The goal of this course}
17 | \begin{itemize}
18 | \item This course does not try to make you a better programmer
19 | \item But it \stress{does} convey \hl{basic concepts and vocabulary} to make your design decisions more \stress{consciously}
20 | \item Thinking while coding + reflecting your decisions after coding $\lra$ Experience $\lra$ Great code!
21 | \end{itemize}
22 | \end{block}
23 | \end{frame}
24 |
25 |
26 |
27 | \begin{frame}[t]{Programming Paradigms}
28 | \only<+->{\begin{block}{What \stress{is} a programming paradigm?}
29 | \begin{itemize}
30 | \item A \hhl{classification of programming languages} based on their features {\small (but most popular languages support multiple paradigms)}
31 | \item A \hhl{programming style} or way programming/thinking
32 | \item Example: Object Oriented Programming \srem{(thinking in terms of objects which contain data and code)}
33 | \item Many common languages support \srem{(to some extent)} \hhl{multiple paradigms} \srem{(C++, python, \dots)}
34 | \end{itemize}
35 | \end{block}
36 | }
37 | %
38 | \only<+->{\begin{block}{Why should I care?}
39 | \begin{itemize}
40 | \item Discover \hhl{new ways of thinking} $\lra$ challenge your current beliefs about how to code
41 | \item Choose the \hhl{right paradigm for the right problem} or \hhl{pick the best of many worlds}
42 | \end{itemize}
43 | \end{block}
44 | }
45 | %
46 | \end{frame}
47 |
48 | \begin{frame}[t]{Programming Paradigms}
49 | \only<+->{
50 | \begin{block}{Some problems}
51 | \begin{itemize}
52 | \item Too formal definitions can be hard to grasp and sometimes impractical, too loose definitions can be meaningless
53 | \item Comparing different paradigms requires experience and knowledge in both \srem{(if all you [know] is a hammer, everything looks like a nail)}
54 | \item A perfect programmer might write great software using any PP
55 | \end{itemize}
56 | \end{block}
57 | }
58 | %
59 | \only<+->{
60 | \begin{block}{My personal approach}
61 | \begin{itemize}
62 | \item Rather than asking \enquote{How to define paradigm X?}, ask \enquote{How would I approach my problems in X?}.
63 | \item Try out \enquote{academic languages} that enforce a certain paradigm \\\srem{$\lra$ How does it \emph{feel} to program in X}
64 | \item Get back to your daily programming and rethink your design decisions
65 | \end{itemize}
66 | \end{block}
67 | }
68 | %
69 |
70 | \end{frame}
71 |
72 | %\begin{frame}{Lecture 1}{Programming Paradigms}
73 | % % what is a pp?
74 | % \begin{enumerate}
75 | % \setlength{\itemsep}{3ex}
76 | % \item What do we call "good" code/software?
77 | % \item Approaches to writing software
78 | % \item Programming paradigms\vspace{1ex}
79 | % \begin{enumerate}[a]
80 | % \setlength{\itemsep}{1ex}
81 | % \item Object Oriented Programming (OOP)
82 | % \item Functional Programming (FP)
83 | % \item OOP vs FP
84 | % \item Declarative and imperative programming
85 | % \item Other programming paradigms
86 | % \end{enumerate}
87 | % \end{enumerate}
88 | %\end{frame}
89 |
90 | \section{Good code}
91 |
92 | \frame{\tableofcontents[currentsection, currentsubsection]}
93 |
94 | \subsection{Objectives}
95 |
96 | %\frame{\tableofcontents[currentsection, currentsubsection]}
97 |
98 | \begin{frame}{Good code: Objectives}
99 | \begin{block}{Key objectives}{\relax}
100 | \begin{itemize}
101 | \item \hhl{Testability}: Make it easy to \hl{ensure} the software is working correctly
102 | \item \hhl{Maintainability}: Make it easy to \hl{keep} the software working \srem{(debugging, readability, ...)}
103 | \item \hhl{Extendibility}: Make it easy to \hl{add} new functionality
104 | \item \hhl{Flexibility}: Make it easy to \hl{adapt} to new requirements
105 | \item \hhl{Reusability}: Make it easy to \hl{reuse} code in other projects
106 | \end{itemize}
107 | \end{block}
108 |
109 | \bigskip
110 | {\Large $\lra$ How do I achieve all this?}
111 |
112 | \end{frame}
113 |
114 | \subsection{Core concepts}
115 |
116 | \begin{frame}[t]{Modularity}{Perhaps the most important principle of good software}
117 | \hhl{Split up code} into parts, e.g., functions, classes, modules, packages, \dots
118 | % http://aosd.net/importance-of-modularity-in-programming/
119 |
120 | \bigskip
121 | You have done \goodc{\stress{well}} if the parts are
122 | \begin{itemize}
123 | \item independent of each other
124 | \item have clear responsibilities
125 | \end{itemize}
126 |
127 | You have done \badc{\stress{badly}} if the parts
128 | \begin{itemize}
129 | \item are very dependent on each other \srem{(changes in one part require changes in many others)}
130 | \end{itemize}
131 |
132 | \bigskip
133 | \only<2->{This has benefits for almost all of your goals:
134 | \begin{itemize}
135 | \item Easier and more complete \hhl{testability} by using unit tests, better debugging
136 | \item Confidence from unit tests allows for better \hhl{maintainability} and \hhl{flexibility}
137 | \item Allowing to split responsibilities for different \enquote{modules} enhances collaboration and thereby \hhl{maintainability}
138 | \item Code \hhl{reusability} (obvious)
139 | \end{itemize}
140 | }
141 | %high cohesion?
142 |
143 |
144 | \end{frame}
145 |
146 | \begin{frame}{Modularity}{Perhaps the most important principle of good software}
147 | A related principle: \hhl{Isolate what changes!}
148 |
149 | \begin{itemize}
150 | \item Which parts of your code will likely have to change in the future?\\
151 | \lrapar{These parts should be \hhl{isolated} \srem{(you should be able to change them in one place, without having to change anything else)}}
152 | \item This also leads to the concept of a separation of
153 | \begin{itemize}
154 | \item \hhl{interface} \srem{(used by other \enquote{modules}, stays untouched)} and
155 | \item \hhl{implementation} \srem{(only used by the module itself, can change easily)}
156 | \end{itemize}
157 | \end{itemize}
158 | \end{frame}
159 |
160 | \begin{frame}{Complex vs Complicated}
161 | % https://medium.com/informed-choises/meta-1-complex-is-better-than-complicated-the-zen-of-python-3663869f8f40
162 | %
163 | % https://reinout.vanrees.org/weblog/2015/12/21/complex-complicated.html
164 | From the Zen of python:
165 |
166 | \bigskip
167 | \begin{center}
168 | \hhl{Simple} is better than \hhl{complex}.\\
169 | \hhl{Complex} is better than \hhl{complicated}.
170 | \end{center}
171 | \bigskip
172 |
173 | \begin{itemize}
174 | \item The more \defn{complicated} something is, the harder it is to understand
175 | \item The more \defn{complex} something is, the more parts it has
176 | \end{itemize}
177 |
178 | \bigskip
179 | \begin{itemize}
180 | \item Complicated problems might not have simple solutions
181 | \item But it is often still possible to modularize to have several simple components
182 | \end{itemize}
183 |
184 | \bigskip
185 | \begin{itemize}
186 | \item For example, using classes and objects will make your code more \emph{complex}, but still easier to understand
187 | \end{itemize}
188 | \end{frame}
189 |
--------------------------------------------------------------------------------
/latex/input/patterns/behavioral.tex:
--------------------------------------------------------------------------------
1 | \subsection{Behavioral Patterns}
2 |
3 | \frame{\tableofcontents[currentsection, currentsubsection]}
4 |
5 |
6 | \begin{frame}[t]{Template Method}
7 | \stress{\badc{Questionable:}}
8 | \inputminted{python}{code/patterns/behavioral/template_method_bad.py}
9 | \only<2->{
10 | \begin{itemize}
11 | \item What if multiple methods depend on the model? \srem{$\lra$ Need to keep track of more \texttt{if}s everywhere}
12 | \item What if we want to add or remove a model? \srem{$\lra$ Need to make changes in many places $\lra$ \sout{Open/Closed Principle}}, \enquote{divergent change}
13 | \item Depend on all implementations $\lra$ \srem{\sout{Dependency Inversion Principle}}
14 | \end{itemize}
15 | }
16 | \end{frame}
17 |
18 |
19 | \begin{frame}{Template Method}
20 | \begin{itemize}[<+->]
21 | \item \hhl{Use case:} Several different algorithms that only contain minor differences in few places
22 | \item \hhl{Suggestion:} Put shared code in superclass, have subclasses implement or override specific methods
23 |
24 | \begin{center}
25 | \begin{tikzpicture}[scale=0.7, transform shape]
26 | \umlclass[x=0,y=3, type=abstract]{MLModel}{
27 | }{
28 | + preprocess()\\
29 | \emph{+ train()}\\
30 | + validate()
31 | }
32 |
33 | \umlclass[x=-2,y=0]{BDT}{}{+ train()}
34 | \umlinherit{BDT}{MLModel}
35 |
36 | \umlclass[x=2,y=0]{RandomForest}{}{+ train()}
37 | \umlinherit{RandomForest}{MLModel}
38 | \end{tikzpicture}
39 | \end{center}
40 | \item \hhl{Advantages:} Simple and clean with little overhead
41 | \item \hhl{Warnings:}
42 | \begin{itemize}
43 | \item If there are many differences between original classes, we need (to override) many methods $\lra$ increasingly hard to read and maintain
44 | \item If there are multiple \enquote{options} for every method and we want to realize them, the number of subclasses grows exponentially $\lra$ \emph{Strategy pattern}
45 | \item If overriding default methods, the Liskov Substitution Principle can be easily violated
46 | \end{itemize}
47 | \end{itemize}
48 | %
49 |
50 | \end{frame}
51 |
52 | \begin{frame}{Template Method}
53 | \stress{\goodc{Better:}}
54 | \inputminted{python}{code/patterns/behavioral/template_method.py}
55 | \end{frame}
56 |
57 | \begin{frame}{Strategy}
58 | \begin{itemize}[<+->]
59 | %
60 | \item
61 | \hhl{Usage:} Your problem consists of several steps. Each step can be solved with different algorithms (strategies)
62 | %
63 | \item
64 | \hhl{Suggestion:} Create abstract class for each step and concrete subclasses with specific algorithms; original class holds instances of algorithms
65 |
66 | \begin{center}
67 | \begin{tikzpicture}[scale=0.7, transform shape]
68 | \umlclass[x=0,y=3]{MyAnalysis}{
69 | + ml\_model: MLModel\\
70 | + fitter: Fitter
71 | }{
72 | %\dots\\
73 | + train()\\
74 | + fit()\\
75 | %\dots
76 | }
77 |
78 | \umlclass[y=3, x=4, type=abstract]{MLModel}{}{\emph{+ train()}}
79 | \umlaggreg{MyAnalysis}{MLModel}
80 |
81 | \umlclass[x=2,y=0]{BDT}{}{+ train()}
82 | \umlinherit{BDT}{MLModel}
83 |
84 | \umlclass[x=6,y=0]{RandomForest}{}{+ train()}
85 | \umlinherit{RandomForest}{MLModel}
86 |
87 | \umlclass[y=3, x=-4, type=abstract]{Fitter}{}{\emph{+ fit()}}
88 | \umlaggreg{MyAnalysis}{Fitter}
89 |
90 | \umlclass[x=-5,y=0]{KernelDensityFit}{}{+ fit()}
91 | \umlinherit{KernelDensityFit}{Fitter}
92 |
93 | \umlclass[x=-2,y=0]{CrystalBallFit}{}{+ fit()}
94 | \umlinherit{CrystalBallFit}{Fitter}
95 | \end{tikzpicture}
96 | \end{center}
97 | \end{itemize}
98 | \end{frame}
99 |
100 | \begin{frame}{Strategy}
101 | \inputminted{python}{code/patterns/behavioral/strategy.py}
102 | \end{frame}
103 |
104 | \begin{frame}{Strategy}
105 | \begin{itemize}
106 | \item<1-> \hhl{Note}: The main class holds instances of algorithm classes; the algorithm classes use the the \hl{template method} pattern
107 | \item<2-> \hhl{Advantages}:
108 | \begin{itemize}[]
109 | \item \hl{Open/Closed} principle: Easily add new strategies
110 | \item \hl{Dependencies inverted} (\texttt{MyAnalysis} does not depend on the individual implementations)
111 | \item \hl{Small number of subclasses}
112 | \item \hl{Separated implementation} of algorithms from higher level code
113 | \item For compiled languages: Change algorithms at \hl{runtime}
114 | \end{itemize}
115 | \item<3-> \hhl{Warnings}:
116 | \begin{itemize}
117 | \item Might be overkill for very simple problems
118 | \item For maximum performance, avoid virtual calls
119 | \end{itemize}
120 | \item<4-> \hhl{Alternatives}:
121 | \begin{itemize}
122 | \item If your language supports it: Use functions instead of objects \srem{(e.g., provide several \texttt{fit()} functions and pass them to the class)}
123 | \item Use template pattern if there is only one strategy that can be replaced
124 | \end{itemize}
125 | \end{itemize}
126 | \end{frame}
127 |
128 | \begin{frame}[t]{Command}
129 | \begin{quote}
130 | The command pattern turns a \hhl{method call} into a \hhl{standalone object}.
131 | \end{quote}
132 |
133 | \medskip
134 | Rather than directly calling a method, the interface creates a \texttt{Command} object \srem{(describing what we want to execute)} and passing it on to a \texttt{Receiver} that executes it
135 |
136 | \only<2->{
137 | \bigskip
138 | Use cases:
139 | \begin{itemize}
140 | \item<2-> \hhl{Decouple} user interfaces from the backend \srem{(by using \texttt{Command} objects as means of communication)}
141 | \item<3-> Build up a command \hhl{history} with \hhl{undo} functionality
142 | \item<4-> \hhl{Remote execution} of commands
143 | \item<5-> \hhl{Queue} or \hhl{schedule} operations
144 | %\end{itemize}
145 | \end{itemize}
146 | }
147 | \only<6->{
148 | \bigskip
149 | HEP specific use case example (Belle II software framework):
150 | \begin{itemize}
151 | \item<7-> Build up analysis by adding modules \srem{(\texttt{Command} objects)} to a path \srem{(list of modules)}, each implementing a \texttt{event()} method to process one event
152 | \item<8-> After all modules are added, process the path: Loop over all events, calling the \texttt{event()} method of all modules in order
153 | \end{itemize}
154 | }
155 | \end{frame}
156 |
157 | \begin{frame}{Command}
158 | Slightly simplified Belle II steering file:
159 |
160 | \inputminted[fontsize=\small]{python}{code/patterns/behavioral/belle2_steering_file.py}
161 | \end{frame}
162 |
163 | \begin{frame}{Command}
164 | Upon processing path:
165 | %
166 | \begin{center}
167 | \includegraphics[height=3.5cm]{figures/patterns/behavioral/ModulePath.png}
168 | \end{center}
169 |
170 | \bigskip
171 | \begin{itemize}[<+->]
172 | \item Strictly \hhl{declarative} approach \srem{(no for loops or implementation details)}
173 | \item Modules can be implemented in \proglang{python} or \proglang{C++}
174 | \item \hhl{\enquote{Building block}} approach makes steering files extremely easy to write and understand \srem{(even browser based graphical interface for highschoolers: try it at \url{masterclass.ijs.si})}
175 | \end{itemize}
176 | \end{frame}
177 |
178 | %\begin{frame}{Iterator}
179 | %
180 | %\end{frame}
181 |
182 | \begin{frame}{Visitor}
183 | \begin{itemize}
184 | \item
185 | \hhl{Concrete example}: Serialize a collection of instances of different classes \srem{(e.g., provide JSON export for a list of different data objects)}
186 | \item
187 | \hhl{Possible implementation}: Provide a \texttt{to\_json()} method to all classes
188 | \item
189 | \hhl{Potential issue}:
190 | Might soon want to add export for export possibilities: \srem{(\texttt{XML}, \texttt{CSV}, \texttt{YAML}, etc.)}
191 | \Lrapar{more and more unrelated methods need to be added to the data class}
192 | \Lrapar{\hl{\enquote{polluted} interface} \srem{(methods are irrelevant for core functionality)}; people might be wary of \hl{frequent changes} to a well working class}
193 | \item
194 | \hhl{Solution}:
195 | Separate algorithms from the objects they operate on
196 | \medskip
197 | \begin{center}
198 | \begin{tikzpicture}[scale=0.7, transform shape]
199 | \umlclass[x=-2,y=3, type=abstract]{Visitor}{
200 |
201 | }{
202 | + \emph{visit\_element\_a()}\\
203 | + \emph{visit\_element\_b()}
204 | }
205 |
206 | \umlemptyclass[x=-2,y=0]{JSONExport}
207 | \umlinherit{JSONExport}{Visitor}
208 |
209 | \umlclass[y=3,x=5, type=abstract]{Element}{
210 | }{
211 | + \emph{accept(visitor)}\\
212 | }
213 |
214 | \umlclass[y=0,x=3.5]{ElementA}{}{+ accept(visitor)}
215 | \umlVHVinherit{ElementA}{Element}
216 | \umluniassoc[geometry=-|-, anchor1=-160, anchor2=-8]{ElementA}{Visitor}
217 |
218 |
219 | \umlclass[y=0,x=6.5]{ElementB}{}{+ accept(visitor)}
220 | \umlVHVinherit{ElementB}{Element}
221 | \umluniassoc[anchor1=-160, anchor2=-22]{ElementB}{Visitor}
222 | \end{tikzpicture}
223 | \end{center}
224 | \end{itemize}
225 | \end{frame}
226 |
227 | \begin{frame}{Visitor}
228 | \hhl{Use case} \srem{(more formally)}:
229 | \begin{itemize}
230 | \item<2-> Given a heterogeneous family of \texttt{Element} classes
231 | \item<2-> Do not expect significant changes to \texttt{Element} classes
232 | \item<3-> Various unrelated operations need to be performed on a collection of \texttt{Element} objects
233 | \item<3-> We expect frequent additions and changes for the operations
234 | \item<3-> Do not want to frequently change \texttt{Element} classes because of that
235 | \end{itemize}
236 |
237 | \bigskip
238 | \hhl{Advantages of visitor pattern}:
239 | \begin{itemize}
240 | \item<4-> Single responsibility principle: All the operation functionality is in one place
241 | \item<4-> Open/Closed principle: Easy to add new operations
242 | \end{itemize}
243 |
244 | \bigskip
245 | \hhl{Disadvantages of the visitor pattern}:
246 | \begin{itemize}[<+->]
247 | \item<5-> No access to private information of \texttt{Element} classes
248 | \item<6-> Changes to \texttt{Element} classes can require changes to all visitors
249 | \end{itemize}
250 | \end{frame}
251 |
--------------------------------------------------------------------------------
/latex/input/paradigms/fp.tex:
--------------------------------------------------------------------------------
1 | \subsection[Functional]{Functional programming}
2 |
3 | \frame{\tableofcontents[currentsection, currentsubsection]}
4 |
5 | \subsubsection{Definition}
6 |
7 | \begin{frame}{Functional programming}
8 | % https://www.geeksforgeeks.org/functional-programming-paradigm/
9 | % https://en.wikipedia.org/wiki/Functional_programming#Pure_functions
10 | Functional programming
11 | \begin{itemize}
12 | \item<+-> expresses its computations in the style of \hhl{mathematical functions}
13 | \item<+-> emphasizes
14 | \begin{itemize}
15 | \item \hhl{expressions} \srem{(\enquote{is} something: a series of identifiers, literals and operators that reduces to a value)}
16 | \item[over\hspace{-0.7em}]
17 | \item \hhl{statements} \srem{(\enquote{does} something, e.g., stores value, etc.)}
18 | \end{itemize}
19 | $\lra$ \hhl{declarative} nature
20 | \item<+-> Data is \hhl{immutable} \srem{(instead of changing properties, I need to create copies with the changed property)}
21 | \item<+-> Avoids \hhl{side effects} \srem{(expressions should not change or depend on any external state)}
22 | \end{itemize}
23 | %
24 | \end{frame}
25 |
26 | \begin{frame}{Examples}
27 | Languages made for FP (picture book examples):
28 | \begin{itemize}
29 | \item \proglang{Clojure}
30 | \item \proglang{Haskell}
31 | \item \proglang{OCaml}
32 | \item \proglang{F\#}
33 | \item \proglang{Wolfram Language} (Mathematica etc.)
34 | \item \dots
35 | \end{itemize}
36 | %
37 | With emphasis on FP:
38 | \begin{itemize}
39 | \item \proglang{Common Lisp}
40 | \item \proglang{JavaScript}
41 | \item \proglang{R}
42 | \item \dots
43 | \end{itemize}
44 | %
45 | Not designed for, but offering strong support for FP:
46 | \begin{itemize}
47 | \item \proglang{C++} \srem{(from \proglang{C++11} on)}
48 | \item \proglang{Perl}
49 | \item \proglang{Python} (?) \srem{($\lra$ You might also want to check out the \proglang{coconut} language)}
50 | \item \dots
51 | \end{itemize}
52 | \end{frame}
53 |
54 | %\begin{frame}[t]{Referential transparency}
55 | % \only<+->{
56 | % No side effects implies referential transparency:
57 | %
58 | % \medskip
59 | % \begin{center}
60 | % An expression is \hhl{referential transparent} if it can be replaced with its value without changing the outcome of the program.
61 | % \end{center}
62 | % }
63 | %
64 | % Which of the following functions are referential transparent?
65 | %% \only<+->{
66 | %% \bigskip
67 | %% In particular for functions: \hhl{$x = y$ $\Lra$ $f(x) = f(y)$}.
68 | %% }
69 | % \only<+>{
70 | % \inputminted[]{python}{code/paradigms/fp/referential_transparency.py}
71 | % }
72 | %\end{frame}
73 |
74 | \begin{frame}[t]{Pure functions}
75 | % https://en.wikipedia.org/wiki/Pure_function
76 | \only<+->{
77 | A function is called pure if
78 | \begin{enumerate}
79 | \item Same arguments $\Lra$ same return value \srem{($x=y\ \Lra\ f(x)=f(y)$)}
80 | \item The evaluation has no side effects \srem{(no change in non-local variables, ...)}
81 | \end{enumerate}
82 | }
83 |
84 | \bigskip
85 | \only<2->{Which of the following functions are pure?}
86 | %
87 | \begin{columns}[t]
88 | \column{0.5\textwidth}
89 | \only<2->{
90 | \inputminted[lastline=15]{python}{code/paradigms/fp/referential_transparency.py}
91 | }
92 | \column{0.5\textwidth}
93 | \only<2->{
94 | \inputminted[firstline=18]{python}{code/paradigms/fp/referential_transparency.py}
95 | }
96 | \only<3->{
97 | \bigskip
98 | \stress{Answer}: \texttt{f1} is pure; \texttt{f2}, \texttt{f3}, \texttt{f5} violate rule 2; \texttt{f4}, \texttt{f3} violate rule 1.
99 | }
100 | \end{columns}
101 |
102 | \end{frame}
103 |
104 | \begin{frame}[t]{Non strict evaluation}{}
105 | \begin{itemize}
106 | \item Some functional programming languages use \hldefn{non-strict evaluation}: The arguments of a function are \emph{only} evaluated once the function is called.
107 |
108 | \only<2->{
109 | \medskip
110 | Example: \mintinline{python}{print(sqrt(sin(a**2)))}
111 |
112 | \medskip
113 | In a \hhl{strict} language \srem{(e.g., \proglang{Python}, \proglang{C++})}, we evaluate inside out:
114 | %
115 | \begin{equation*}
116 | a\lmt a^2\lmt \sin{a^2} \lmt \sqrt{\sin{a^2}}
117 | \end{equation*}
118 | %
119 | In a \hhl{non-strict} language, the evaluation of the inner part is \stress{deferred}, until it is actually needed.
120 | }
121 | \item<3->
122 | \medskip
123 | But \proglang{Python} actually has something similar in the concept of \hhl{\texttt{generators}}:
124 | \inputminted[]{python}{code/paradigms/fp/generators.py}
125 |
126 | %
127 | \item<4-> This allows for \hhl{infinite data structures} \srem{(which can be more practical than it sounds)}
128 | \end{itemize}
129 | \end{frame}
130 |
131 | \begin{frame}[t]{Memoization}
132 | \begin{itemize}
133 | \item<+-> Non strict evaluation together with \hldefn{sharing} (avoid repeated evaluation of the same expression) is called \hldefn{lazy evaluation}
134 | %
135 | \item<+-> Generally, functional programming can get cheap performance boosts by very simple \hldefn{memoization}: Storing the results of expensive \stress{pure} function calls in a cache
136 |
137 | %\medskip
138 | \only<+->{\inputminted[]{python}{code/paradigms/fp/memoization.py}}
139 | \end{itemize}
140 | \end{frame}
141 |
142 | \begin{frame}[t]{Higher order functions}
143 | A \hldefn{higher order function} does one of the following:
144 | \begin{itemize}
145 | \item returns a function
146 | \item takes a function as an argument
147 | \end{itemize}
148 | Opposite: \hldefn{first-order function}.
149 |
150 | \medskip
151 | \srem{Mathematical examples (usually called \defn{operators} or \defn{functionals}): differential operator, integration, \dots}
152 |
153 | \only<2->{\medskip
154 | Higher level functions are the FP answer to template methods in OOP \srem{(\enquote{configuring} object behavior by overriding methods in subclasses)}.
155 | }
156 |
157 | \only<3->{
158 | \medskip
159 | Classic example of a higher order function: \texttt{map} \srem{(applies function to all elements in list)}:
160 | \inputminted[lastline=8]{python}{code/paradigms/fp/higher_order.py}
161 | }
162 | \end{frame}
163 |
164 | \begin{frame}[t]{Higher order functions II}
165 | \bigskip
166 | A function that also returns a function:
167 |
168 | \only<1| handout:0>{
169 | \inputminted[lastline=12]{python}{code/paradigms/fp/higher_order_2.py}
170 | }
171 | \only<2>{
172 | \inputminted[]{python}{code/paradigms/fp/higher_order_2.py}
173 | }
174 | \end{frame}
175 |
176 | \begin{frame}{Type systems}
177 | \hhl{Types:}
178 | \begin{itemize}
179 | \item In OOP, \hhl{type} and \hhl{class} are often used interchangeably
180 | %\footnote{though one might use \defn{type} for abstract interfaces, vs \defn{class} for implementations}
181 | \srem{(e.g., \texttt{"abc"} is of type \defn{string} = is an instance of the \texttt{str} class)}
182 | \item In FP we talk about \defn{type}s
183 | \item Complex types can be built from built in types \\
184 | \srem{(e.g., \mintinline{python}{List[Tuple[str, int]]}, we can also use \texttt{struct}s)}
185 | \item In many languages, types of variables, arguments, etc. have to be declared \srem{(e.g., \mintinline{python}{def len(List[float]) -> int})}
186 | \item Real FP languages usually have very powerful \hhl{type systems}%; FP languages can be both
187 | \end{itemize}
188 |
189 | % \medskip
190 | % \hhl{Subtype polymorphism:}
191 | % \begin{itemize}
192 | % \item Types can have subtypes \srem{(e.g., \mintinline{python}{List[int]} as a subtype of \mintinline{python}{List[Number]]})}; any function for the type works on the subtype \srem{(e.g., \mintinline{python}{def sum(List[Number) -> int} now works on \mintinline{python}{List[Int]} as well as \mintinline{python}{List[float]})}
193 | % \item The type specifies which functions can be applied \srem{(this was done by defining \emph{methods} in FP)}; subtyping becomes similar to inheritance
194 | % \end{itemize}
195 | \end{frame}
196 |
197 | \begin{frame}[t]{Polymorphism}
198 | % contrast this with subtype polymorphism which is the standard OOP polymorphism
199 | % Category: Generic programming
200 |
201 | In FP, the type system allows to bring back some OOP thinking but is more flexible. Usually you can do some of the following:
202 |
203 | \only<2->{
204 | \bigskip
205 | \hhl{Single/multiple dispatch/ad hoc polymorphism:}
206 | \begin{itemize}
207 | \item Can \hhl{overload} function definitions \srem{(e.g., define \mintinline{python}{def print(i: int)} differently from \mintinline{python}{def print(string: str)})}
208 | \item The right function is resolved based on the type at compile- or runtime
209 | \end{itemize}
210 | }
211 |
212 | \only<3->{
213 | \medskip
214 | \hhl{Parametric polymorphism:}
215 | \begin{itemize}
216 | \item Parameterize types in function signatures \srem{(e.g., \mintinline{python}{def first(List[a]) -> a}; \texttt{a} represents an arbitrary type)}
217 | \end{itemize}
218 | }
219 |
220 | \only<4->{
221 | \medskip
222 | \hhl{Type classes:}
223 | \begin{itemize}
224 | \item Define a \enquote{type} by what functions it has to support \srem{(e.g., define \texttt{Duck} as anything that allows me to call the \texttt{quack} function on it)}
225 | \item Similar to a class with only abstract methods (=\emph{interface}) and no encapsulated data
226 | \end{itemize}
227 | }
228 | \end{frame}
229 | %
230 | %
231 | \begin{frame}[t]{Looping in functional programming}
232 | \only<1->{Let's consider a function that calculates $\sum_{i=0}^N i^2$:}
233 | %
234 | \only<+->{\inputminted[]{python}{code/paradigms/fp/sum_loop.py}}
235 |
236 |
237 | \only<+->{
238 | \bigskip
239 | This is a function, but does not follow the FP paradigm:
240 | \begin{itemize}
241 | \item More statements \srem{(assignments, loops, \dots)} than expressions
242 | \item The for loop segment is not free of side effects \srem{(value of \texttt{result} changes)}
243 | \item Repeated reassignments of \texttt{result} are frowned upon \srem{(or impossible)}
244 | \end{itemize}
245 | }
246 | \only<+->{
247 | \bigskip
248 | How to change this?
249 | \only<+->{$\lra$ Use \hhl{recursion}
250 | %
251 | \inputminted[]{python}{code/paradigms/fp/sum_head_recursion.py}
252 | }
253 | }
254 | %Tail recursions $\lra$ Compiler optimization
255 | \end{frame}
256 |
257 | \begin{frame}[t]{Looping in functional programming}
258 | \only<1->{
259 | The previous example is called a \hhl{head recursion} \srem{(recursion before computation)}; using a \hhl{tail recursion} \srem{(recursion after computation)} is preferable due to better compiler optimization:
260 | }
261 | %
262 | \only<+->{
263 | \inputminted[fontsize=\small]{python}{code/paradigms/fp/sum_tail_recursion.py}
264 | }
265 | \only<+->{
266 | \bigskip
267 | Another FP way is to use the higher level functions \hhl{\texttt{map}} and \hhl{\texttt{reduce}} together with anonymous functions (\hhl{lambda}):
268 | \inputminted[fontsize=\small]{python}{code/paradigms/fp/sum_map_reduce.py}
269 | \srem{This also opens the door for concurrency ($\lra$ parallel versions of \texttt{map} and \texttt{reduce})}
270 | }
271 | \end{frame}
272 |
273 | \subsubsection{Signature moves}
274 |
275 | \subsubsection{Strengths and Weaknesses}
276 |
277 | \begin{frame}{Strengths and Weaknesses}
278 | \begin{block}{Strengths}
279 | \begin{itemize}[<+->]
280 | \item Proving things \hhl{mathematically} \srem{(referential transparency, \dots)}
281 | \item \hhl{Testability} \srem{(no object initializations and complex dependencies, pure functions)}
282 | \item Easy \hhl{debugging} \srem{(no hidden states)}
283 | \item Can be very \hhl{short} and \hhl{concise} $\lra$ easy to verify
284 | \item Sophisticated logical abstractions \srem{(using high level functions)} $\lra$ modularity, \hhl{code reuse}
285 | \item Easy \hhl{parallelization} \srem{(no (shared) mutable states)}
286 | \end{itemize}
287 | \end{block}
288 | \end{frame}
289 |
290 | \begin{frame}{Strengths and Weaknesses}
291 | \begin{block}{Weaknesses}
292 | \begin{itemize}[<+->]
293 | \item Structuring code in terms of objects can feel more intuitive if logic \srem{(methods)} are strongly tied to data
294 | \item Imperative algorithms might be easier to read and feel more natural than declarative notation
295 | \item FP might have a steeper \hhl{learning curve} \srem{(e.g., recursions instead of loops, \dots)}
296 | \item \hhl{Performance issues}: Immutable data types and recursion can lead to performance problems (speed and RAM), whereas many mutable data structures are very performant on modern hardware
297 | % \begin{itemize}
298 | %\item Declarative nature somewhat less efficient in CPU usage compared to imperative styles
299 | %\item due to \hhl{immutability}:
300 | % \end{itemize}
301 | \item Pure FP has still only a \hhl{small user base outside of academia}, but FP support more and more wide spread in common languages
302 | \end{itemize}
303 | \end{block}
304 | \end{frame}
305 |
--------------------------------------------------------------------------------
/latex/input/patterns/intro.tex:
--------------------------------------------------------------------------------
1 | \begin{frame}
2 | \tableofcontents[]
3 | Slides + exercises available at \hhl{\href{https://github.com/klieret/icsc-paradigms-and-patterns}{github.com/klieret/icsc-paradigms-and-patterns}}
4 | \end{frame}
5 |
6 | \section{More on OOP}
7 |
8 | \subsection{Repetition}
9 |
10 | \begin{frame}[t]{Repetition: Object Oriented Programming}
11 | \begin{itemize}[<+->]
12 | \item \hhl{Inheritance:} Subclasses inherit all \srem{(public and protected)} attributes and methods of the base class
13 | \item Methods and attributes can be \hhl{public} \srem{(anyone has access)}, \hhl{private} \srem{(only the class itself has access)} or \hhl{protected} \srem{(only the class and its subclasses have access)}
14 | \item \hhl{Abstract methods} of an \hhl{abstract class} are methods that have to be implemented by a subclass (\hhl{concrete class})
15 | \end{itemize}
16 |
17 | \only<+->{
18 | \bigskip
19 | \stress{New}: \hhl{class methods}: Methods of the class, rather than its instances
20 | \inputminted[fontsize=\small]{python}{code/patterns/intro/classmethod.py}
21 | }
22 | \end{frame}
23 |
24 | \subsection{Class Diagrams}
25 |
26 | \begin{frame}{Class diagrams I}
27 | UML \srem{(\underline Unified \underline Markup \underline Language)} class diagrams visualize classes and the relationships between them. We will use the following subset of notations:
28 |
29 | \bigskip
30 | \begin{changemargin}{-1cm}{-1cm}
31 | \centering
32 | \begin{tikzpicture}[scale=0.9, transform shape]
33 | \umlclass[x=0,y=3]{class A}{
34 | + public variable : type\\
35 | -- private variable : type \\
36 | \# protected variable : type
37 | }{
38 | + public method(arg : type) : return type\\
39 | \dots
40 | }
41 |
42 | \umlemptyclass[x=0,y=0]{class B}
43 | \umlnote[x=3,y=0, width=2cm, scale=0.9, transform shape]{class B}{\ subclass of A}
44 | \umlinherit{class B}{class A}
45 |
46 |
47 | \umlemptyclass[x=0,y=-2]{class C}
48 | \umlnote[x=3,y=-2,width=2cm, scale=0.9, transform shape]{class C}{\ subclass of B}
49 | \umlinherit{class C}{class B}
50 |
51 | \umlemptyclass[x=6, y=3]{class D}
52 | \umlaggreg{class A}{class D}
53 | \umlnote[x=9,y=3,width=2cm, scale=0.9, transform shape]{class D}{\ A contains\\\ instances of D}
54 |
55 | \umlemptyclass[x=6, y=1]{class E}
56 | % \umlaggreg{class A}{class D}
57 | \umlnote[x=9,y=1,width=2cm, scale=0.9, transform shape]{class E}{\ A is otherwise associated with E}
58 | \umlassoc{class E}{class A}
59 | %
60 |
61 | \end{tikzpicture}
62 | \end{changemargin}
63 | \end{frame}
64 |
65 |
66 | \subsection{The SOLID rules of OOP}
67 |
68 | %\begin{frame}{The SOLID rules of OOP: SOLID}
69 | %
70 | %\end{frame}
71 |
72 | \frame{\tableofcontents[currentsection, currentsubsection]}
73 |
74 | \begin{frame}[t]{The SOLID rules of OOP: Single responsibility principle}{\underline SOLID}
75 | \bigskip
76 | % https://hackernoon.com/you-dont-understand-the-single-responsibility-principle-abfdd005b137
77 | Commonly (mis-)quoted as:
78 |
79 | \begin{quote}
80 | A class should only have \hhl{one responsibility}.
81 | \end{quote}
82 |
83 | {
84 | \medskip
85 | More accurate:
86 |
87 | \begin{quote}
88 | A class should only have \hhl{one reason to change}.
89 | \end{quote}
90 | }
91 |
92 | \only<2->{
93 | \medskip
94 | Better still:
95 | \begin{quote}
96 | \hhl{Gather} together the things that change for the same reasons. \\
97 | \hhl{Separate} those things that change for different reasons.
98 | \end{quote}
99 |
100 | \only<3->{
101 | \medskip
102 | So this actually proposes a \hhl{balance}!
103 | \begin{itemize}
104 | \item Avoid classes that do too much \srem{(\enquote{god class})}
105 | \item But also avoid having changes always affect many classes \srem{(\enquote{shotgun surgery})}
106 | \end{itemize}
107 | }
108 | }
109 | \end{frame}
110 |
111 | \begin{frame}{The SOLID rules of OOP: Open Closed Principle}{S\underline OLID}
112 | \begin{quote}
113 | You should be able to \hhl{extend} the behavior of a system\\
114 | without having to \hhl{modify} that system.
115 | \end{quote}
116 |
117 | \begin{itemize}
118 | \item<2-> Writing a library, \hhl{modifying} functionality means that all users have to be informed (\hhl{not backwards compatible}) $\lra$ Avoid!
119 | \item<2-> In your own code: Modifying one functionality \srem{(also by overriding methods of the super class, etc.)} poses the danger of breaking other parts \srem{(though tests can help with that)}
120 | \item<3-> Extending code by providing additional methods, attributes, etc. does not have this danger $\lra$ preferred!
121 | \item<4-> Requires thinking ahead: What parts have to be flexible, what remains constant?
122 | \item<4-> Again a \hhl{balance} is required:
123 | \begin{itemize}
124 | \item Be \hhl{too generic} \srem{(avoid future modifications at any cost)} and your code won't do anything
125 | \item Be \hhl{too concrete} and you will need to modify \srem{(and potentially break things)} often
126 | \end{itemize}
127 | \end{itemize}
128 | \end{frame}
129 |
130 | \begin{frame}[t]{The SOLID rules of OOP: Liskov Substitution Principle}{SO\underline LID}
131 | \begin{quote}
132 | If $S$ is a \hhl{subtype} (subclass) of $T$, then objects of type $T$ can be \hhl{replaced} with objects of type $S$ without breaking anything
133 | \end{quote}
134 |
135 | \srem{e.g., I can replace all instances of \texttt{Animal} with instances of \texttt{Cat}}
136 |
137 | \medskip
138 | \only<2->{
139 | This can be expanded to a series of properties that should be fulfilled:
140 | \begin{itemize}[<+->]
141 | \item \hhl{Signature} of methods of the subclass:
142 | \begin{itemize}[<+->]
143 | %
144 | \item
145 | Required type of arguments should be supertype (\defn{contravariance})\\
146 | \srem{Violation: Supermethod accepts any \texttt{Animal}, submethod only \texttt{Cat}}
147 | %
148 | \item
149 | Return type of method should be a subtype (\defn{covariance})\\
150 | \srem{Violation: Supermethod returns \texttt{Cat}, submethod returns \texttt{Animal}}
151 | \end{itemize}
152 | \item Behavior:
153 | \begin{itemize}[<+->]
154 | %
155 | \item
156 | \hhl{Preconditions} \srem{(requirements to be fulfilled before calling method)} cannot be strengthened in the subtype\\
157 | \srem{Violation: Only in subclass \texttt{prepare()} must be called before \texttt{method()}}
158 | %
159 | \item
160 | \hhl{Postconditions}
161 | \srem{(conditions fulfilled after calling a method)} cannot be weakened by the subtype
162 | %
163 | \item
164 | \hhl{Invariants} \srem{(properties that stay the same)} of supertype must be preserved in the subtype
165 | %
166 | \item
167 | \hhl{History constraint}: Subtypes cannot modify properties that are not modifiable in supertype\\
168 | \srem{Violation: \texttt{VariableRadiusCircle} as subtype of \texttt{FixedRadiusCircle}}
169 | \end{itemize}
170 | \end{itemize}
171 | }
172 | \end{frame}
173 |
174 | \begin{frame}{The SOLID rules of OOP: Interface segregation principle (ISP)}{SOL\underline ID}
175 | \begin{quote}
176 | Clients should not be forced to depend on methods they do not use
177 | \end{quote}
178 |
179 | \bigskip
180 | \begin{itemize}[]
181 | \item<2->
182 | \hhl{\enquote{Thin} interfaces} offering a reasonably small number of methods with \defn{high cohesion} \srem{(serve similar purposes; belong logically together)} are \stress{preferred} over \hhl{\enquote{fat} interfaces} offering a large number of methods with low cohesion
183 | \item<3->
184 | Sometimes we should therefore split up (\hhl{segregate}) fat interfaces into thinner \hldefn{role interfaces}
185 | \item<3->
186 | This leads to a more \hhl{decoupled} system that is easier to maintain
187 | \item<4-> \hhl{Example}: Even if all data is contained in one \srem{(e.g., SQL)} database, the ISP asks to write \emph{different} interfaces to do different things, e.g., have a \texttt{CustomerDb}, \texttt{OrderDb}, \texttt{StoreDb}, \dots
188 | \end{itemize}
189 | \end{frame}
190 |
191 | \begin{frame}[t]{The SOLID rules of OOP: Dependency Inversion Principle}{SOLI\underline D}
192 | This is about \hhl{decoupling} different classes and modules:
193 | \begin{quote}
194 | \begin{itemize}
195 | \item[1.] High-level modules should not depend on low-level modules. Both should depend on abstractions \srem{(interfaces)}.
196 | \end{itemize}
197 | \end{quote}
198 | \only<2->{
199 | Let's consider a very simple example: A \hhl{button} controlling a lamp. One way to implement this:
200 |
201 | \bigskip
202 | \begin{columns}
203 | \column{0.1\textwidth}
204 | %
205 | \begin{tikzpicture}[scale=0.7, transform shape]
206 | \umlclass[x=0,y=3]{Button}{
207 | - client
208 | }{
209 | + turn\_on()\\
210 | + turn\_off()\\
211 | + flip()
212 | }
213 |
214 | \umlemptyclass[x=0,y=0]{Lamp}
215 | \umlaggreg{Button}{Lamp}
216 | \end{tikzpicture}
217 |
218 | \column{0.8\textwidth}
219 | \only<3->{
220 | This violates the DIP, because \texttt{Button} \srem{(high-level)} depends on \texttt{Lamp} \srem{(detail)}.
221 | \bigskip
222 |
223 | What if we have multiple consumers \srem{(\texttt{Motor}, \texttt{Lamp}, \dots)} and multiple types of buttons \srem{(swipe button, switch, push button, \dots)}? How can we force them to behave consistent? What methods does a consumer have to implement to work together with the button?\\
224 |
225 | \bigskip
226 | $\lra$ Enter abstractions (interfaces)
227 | }
228 | \end{columns}
229 | }
230 | %
231 | \end{frame}
232 |
233 | \begin{frame}[t]{The SOLID rules of OOP: Dependency Inversion Principle}{SOLI\underline D}
234 | \bigskip
235 | \begin{center}
236 | \begin{tikzpicture}[scale=0.7, transform shape]
237 | \umlclass[x=0,y=3, type=abstract]{AbstractButton}{
238 | - client
239 | }{
240 | + turn\_on()\\
241 | + turn\_off()\\
242 | + flip()
243 | }
244 |
245 | \umlemptyclass[x=0,y=0]{ConcreteButton}
246 | \umlinherit{ConcreteButton}{AbstractButton}
247 |
248 | \umlclass[y=3,x=5, type=abstract]{AbstractClient}{
249 | }{
250 | + turn\_on()\\
251 | + turn\_off()\\
252 | }
253 | \umlaggreg{AbstractButton}{AbstractClient}
254 |
255 | \umlemptyclass[y=0,x=5]{ConcreteClient}
256 | \umlinherit{ConcreteClient}{AbstractClient}
257 | \end{tikzpicture}
258 | \end{center}
259 |
260 | \only<2->{
261 | \medskip
262 | Now it's clear which methods the concrete client has to implement. Both high level and low level modules only depend on abstractions.
263 |
264 | \bigskip
265 | \only<3->{
266 | This also fulfills the second part of the DIP:
267 | \begin{quote}
268 | \begin{itemize}
269 | \item[2.] Abstractions should not depend on details. Details \srem{(i.e., concrete implementations)} should depend on abstractions.
270 | \end{itemize}
271 | \end{quote}
272 | }
273 | }
274 | \end{frame}
275 |
276 | \begin{frame}[t]{Performance considerations}
277 |
278 | \only<1->{
279 | Some patterns will advocate:
280 | \begin{itemize}
281 | \item Classes that only act as interfaces and pass on calls to other (worker) classes
282 | \item Using separate classes to facilitate communication between classes
283 | \item Accessing attributes (only) through methods
284 | \item Prefer composition over inheritance
285 | \end{itemize}
286 | }
287 |
288 | \only<2->{
289 | \bigskip
290 | However, when writing \hhl{performance critical} (\proglang{C++}, \dots) code, you should avoid unnecessary \enquote{detours}:
291 |
292 | \begin{itemize}
293 | \item Avoid unnecessary interfaces
294 | \item Consider inlining simple, often-called functions \srem{(e.g., getters and setters)}
295 | \item Inheritance > composition > \texttt{if} statements
296 | \end{itemize}
297 | Modern compilers will try to apply some optimization techniques automatically \srem{(automatic inling, return value optimization, \dots)}
298 |
299 | \bigskip
300 | General rule: \hl{Profile before Optimizing}
301 | }
302 | %
303 | \end{frame}
304 |
305 | \section{Patterns}
306 |
307 | \frame{\tableofcontents[currentsection, currentsubsection]}
308 |
309 | \subsection{Patterns}
310 |
311 | \begin{frame}[t]{Patterns}
312 | \only<+->{
313 | \bigskip
314 | \begin{quote}
315 | Software design patterns try to offer \hhl{general} and \hhl{reusable} solutions for \hhl{commonly} occurring problems in a given \hhl{context}.
316 | \end{quote}
317 |
318 | \bigskip
319 | }
320 |
321 | \only<+->{
322 | Commonly categorized as:
323 |
324 | \medskip
325 | \begin{itemize}[<+->]
326 | %
327 | \item
328 | \hhl{Creational patterns}: How are instances of classes instantiated? \srem{(What if I have a class that can create instances in different ways?)}
329 | %
330 | \item
331 | \hhl{Structural patterns}: Concerned with relationships between classes. \srem{(How can classes form flexible larger structures?)}
332 | %
333 | \item
334 | \hhl{Behavioral patterns}: Concerned with algorithms and communication between classes. \srem{(How are responsibilities assigned between classes?)}
335 | %
336 | \item
337 | \hhl{Parallel patterns}: Parallel processing and OOP \srem{$\lra$ only mentioned briefly}
338 | \end{itemize}
339 | }
340 | \end{frame}
341 | %
342 | %
343 | %
344 |
--------------------------------------------------------------------------------
/exercises/paradigms.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Exercises: Programming paradigms"
8 | ]
9 | },
10 | {
11 | "cell_type": "markdown",
12 | "metadata": {},
13 | "source": [
14 | "# Functional programming"
15 | ]
16 | },
17 | {
18 | "cell_type": "markdown",
19 | "metadata": {
20 | "heading_collapsed": true
21 | },
22 | "source": [
23 | "## Recursion"
24 | ]
25 | },
26 | {
27 | "cell_type": "markdown",
28 | "metadata": {
29 | "hidden": true
30 | },
31 | "source": [
32 | "**Exercise 1**: The Fibonacci numbers are defined as $f_1=1$, $f_2=1$, $f_{n+2} = f_n+f_{n+1}$."
33 | ]
34 | },
35 | {
36 | "cell_type": "code",
37 | "execution_count": null,
38 | "metadata": {
39 | "ExecuteTime": {
40 | "end_time": "2020-09-16T14:42:21.269814Z",
41 | "start_time": "2020-09-16T14:42:21.266007Z"
42 | },
43 | "hidden": true
44 | },
45 | "outputs": [],
46 | "source": [
47 | "# Your solution here\n",
48 | "def fib(n):\n",
49 | " pass"
50 | ]
51 | },
52 | {
53 | "cell_type": "code",
54 | "execution_count": null,
55 | "metadata": {
56 | "hidden": true
57 | },
58 | "outputs": [],
59 | "source": [
60 | "# Test your solution here\n",
61 | "\n",
62 | "assert fib(1) == 1\n",
63 | "assert fib(2) == 1\n",
64 | "assert fib(3) == 2\n",
65 | "assert fib(4) == 3\n",
66 | "assert fib(5) == 5"
67 | ]
68 | },
69 | {
70 | "cell_type": "markdown",
71 | "metadata": {
72 | "hidden": true
73 | },
74 | "source": [
75 | "\n",
76 | "\n",
77 | " Click me for the solution
\n",
78 | " \n",
79 | "```python\n",
80 | "def fib(n):\n",
81 | " if n in [1, 2]:\n",
82 | " return 1\n",
83 | " else:\n",
84 | " return fib(n-1) + fib(n-2)\n",
85 | "```\n",
86 | " \n",
87 | " \n",
88 | ""
89 | ]
90 | },
91 | {
92 | "cell_type": "markdown",
93 | "metadata": {},
94 | "source": [
95 | "## Higher order functions"
96 | ]
97 | },
98 | {
99 | "cell_type": "markdown",
100 | "metadata": {},
101 | "source": [
102 | "**Exercise 2a (easy)**: \n",
103 | "\n",
104 | "Given an arbitrary function ``fct`` that operators on \"single\" values (e.g. floats ``fct(1)=3``, etc.)\n",
105 | "\n",
106 | "We want to write a higher order function ``vectorize`` that returns a function ``fct_vectorized`` that can be both applied to single values (``fct_vectorized(1)=3``) and a list like so: ``fct_vectorized([1, 2, ...]) = [fct(1), fct(2), ...]``. "
107 | ]
108 | },
109 | {
110 | "cell_type": "code",
111 | "execution_count": null,
112 | "metadata": {},
113 | "outputs": [],
114 | "source": [
115 | "# Your solution here\n",
116 | "def vectorize(fct):\n",
117 | " pass"
118 | ]
119 | },
120 | {
121 | "cell_type": "code",
122 | "execution_count": null,
123 | "metadata": {},
124 | "outputs": [],
125 | "source": [
126 | "# Test your solution here:\n",
127 | "\n",
128 | "def _square(x):\n",
129 | " return x*x\n",
130 | "\n",
131 | "\n",
132 | "square = vectorize(_square)\n",
133 | "\n",
134 | "\n",
135 | "assert square(1) == 1\n",
136 | "assert square(3) == 9\n",
137 | "assert square([1, 2, 3, 4]) == [1, 4, 9, 16]\n",
138 | "assert square([]) == []\n"
139 | ]
140 | },
141 | {
142 | "cell_type": "markdown",
143 | "metadata": {
144 | "ExecuteTime": {
145 | "end_time": "2020-09-27T11:20:58.738923Z",
146 | "start_time": "2020-09-27T11:20:58.717412Z"
147 | }
148 | },
149 | "source": [
150 | "\n",
151 | "\n",
152 | " Click me for a hint
\n",
153 | " \n",
154 | "```python\n",
155 | " \n",
156 | "def vectorize(fct):\n",
157 | "\n",
158 | " def vectorized(lst):\n",
159 | " if isinstance(lst, list):\n",
160 | " # if we were given a list\n",
161 | " # YOUR CODE HERE\n",
162 | " else:\n",
163 | " # if we were given a single value\n",
164 | " # YOUR CODE HERE\n",
165 | "\n",
166 | " return vectorized\n",
167 | "```\n",
168 | " \n",
169 | " \n",
170 | ""
171 | ]
172 | },
173 | {
174 | "cell_type": "markdown",
175 | "metadata": {},
176 | "source": [
177 | "\n",
178 | "\n",
179 | " Click me for the solution
\n",
180 | " \n",
181 | "```python\n",
182 | " \n",
183 | "from typing import Iterable\n",
184 | "\n",
185 | "def vectorize(fct):\n",
186 | "\n",
187 | " def vectorized(lst):\n",
188 | " if isinstance(lst, Iterable):\n",
189 | " return [fct(item) for item in lst]\n",
190 | " else:\n",
191 | " return fct(lst)\n",
192 | "\n",
193 | " return vectorized\n",
194 | "```\n",
195 | " \n",
196 | " \n",
197 | ""
198 | ]
199 | },
200 | {
201 | "cell_type": "markdown",
202 | "metadata": {},
203 | "source": [
204 | "**Exercise 2b (harder)**: We want to be able to apply an arbitrary function fct that is defined for \"single\" values to a list (of lists) like so: ``fct([[1, 2], 3, [[4]], ...]) = [[fct(1), fct(2)], fct(3), [[fct(4)]], ...])``. \n",
205 | "\n",
206 | "For this we want to create a high-level function ``tree_vectorize``"
207 | ]
208 | },
209 | {
210 | "cell_type": "code",
211 | "execution_count": null,
212 | "metadata": {},
213 | "outputs": [],
214 | "source": [
215 | "# Your solution here\n",
216 | "def tree_vectorize(fct):\n",
217 | " pass"
218 | ]
219 | },
220 | {
221 | "cell_type": "code",
222 | "execution_count": null,
223 | "metadata": {},
224 | "outputs": [],
225 | "source": [
226 | "# Test your solution here:\n",
227 | "\n",
228 | "def _square(x):\n",
229 | " return x*x\n",
230 | "\n",
231 | "square = tree_vectorize(_square)\n",
232 | "\n",
233 | "assert square(4) == 16\n",
234 | "assert square([4]) == [16]\n",
235 | "assert square([1, 3]) == [1, 9]\n",
236 | "assert square([1, 2, [3, [4]]]) == [1, 4, [9, [16]]]"
237 | ]
238 | },
239 | {
240 | "cell_type": "markdown",
241 | "metadata": {},
242 | "source": [
243 | "\n",
244 | "\n",
245 | " Click me for a hint
\n",
246 | "\n",
247 | " - The inner function needs to recursively call itself if the input is a list
\n",
248 | " - You can test whether the input is a list using
isinstance(maybe_list, list) \n",
249 | "
\n",
250 | " \n",
251 | ""
252 | ]
253 | },
254 | {
255 | "cell_type": "markdown",
256 | "metadata": {},
257 | "source": [
258 | "\n",
259 | "\n",
260 | " Click me for the solution
\n",
261 | " \n",
262 | "```python\n",
263 | "def tree_vectorize(fct):\n",
264 | " \n",
265 | " def _vectorized(nested_list):\n",
266 | " if not isinstance(nested_list, list):\n",
267 | " return fct(nested_list)\n",
268 | " else:\n",
269 | " return [_vectorized(lst) for lst in nested_list]\n",
270 | " \n",
271 | " return _vectorized\n",
272 | "```\n",
273 | " \n",
274 | " \n",
275 | ""
276 | ]
277 | },
278 | {
279 | "cell_type": "markdown",
280 | "metadata": {},
281 | "source": [
282 | "**Exercise 3**: We want to log our function calls. Write a function ``log_call`` that takes a function and prints the function call (see the ``Test your solution`` example)."
283 | ]
284 | },
285 | {
286 | "cell_type": "code",
287 | "execution_count": null,
288 | "metadata": {
289 | "ExecuteTime": {
290 | "end_time": "2020-09-27T11:22:18.690296Z",
291 | "start_time": "2020-09-27T11:22:18.671225Z"
292 | }
293 | },
294 | "outputs": [],
295 | "source": [
296 | "# Your solution here\n",
297 | "\n",
298 | "def log_call(fct):\n",
299 | " \n",
300 | " pass"
301 | ]
302 | },
303 | {
304 | "cell_type": "code",
305 | "execution_count": null,
306 | "metadata": {},
307 | "outputs": [],
308 | "source": [
309 | "# Test your solution here\n",
310 | "\n",
311 | "logged_fib = log_call(fib)\n",
312 | "\n",
313 | "# The following should always print the call itself\n",
314 | "logged_fib(1)\n",
315 | "logged_fib(7)"
316 | ]
317 | },
318 | {
319 | "cell_type": "markdown",
320 | "metadata": {},
321 | "source": [
322 | "\n",
323 | "\n",
324 | " Click me for the solution
\n",
325 | "A very simple solution could look like this: \n",
326 | " \n",
327 | "```python\n",
328 | "def log_call(fct):\n",
329 | " \n",
330 | " def _logged_fct(argument):\n",
331 | " return_value = fct(argument)\n",
332 | " # fct.__name__ is the name of the function\n",
333 | " print(f\"{fct.__name__}({argument}) = {return_value}\")\n",
334 | " return return_value\n",
335 | " \n",
336 | " return _logged_fct\n",
337 | "```\n",
338 | "\n",
339 | "**Generalizing** to arbitrarily many arguments and keyword arguments:\n",
340 | " \n",
341 | "```python\n",
342 | "def log_call(fct):\n",
343 | " \n",
344 | " def _logged_fct(*args, **kwargs):\n",
345 | " return_value = fct(*args, **kwargs)\n",
346 | " # fct.__name__ is the name of the function\n",
347 | " print(f\"{fct.__name__}({args}, {kwargs}) = {return_value}\")\n",
348 | " return return_value\n",
349 | " \n",
350 | " return _logged_fct\n",
351 | "``` \n",
352 | "\n",
353 | "**Advanced**: The above solution works perfectly, but for some minor details, it is recommended to do this:\n",
354 | "```python\n",
355 | "from functools import wraps\n",
356 | " \n",
357 | "def log_call(fct):\n",
358 | " \n",
359 | " @wraps(fct)\n",
360 | " def _logged_fct(*args, **kwargs):\n",
361 | " return_value = fct(*args, **kwargs)\n",
362 | " # fct.__name__ is the name of the function\n",
363 | " print(f\"{fct.__name__}({args}, {kwargs}) = {return_value}\")\n",
364 | " return return_value\n",
365 | " \n",
366 | " return _logged_fct\n",
367 | "``` \n",
368 | " \n",
369 | ""
370 | ]
371 | },
372 | {
373 | "cell_type": "markdown",
374 | "metadata": {},
375 | "source": [
376 | "Using a bit of python dark magic, we can actually print what's happening in the recursion:"
377 | ]
378 | },
379 | {
380 | "cell_type": "code",
381 | "execution_count": null,
382 | "metadata": {},
383 | "outputs": [],
384 | "source": [
385 | "fib = log_call(fib)"
386 | ]
387 | },
388 | {
389 | "cell_type": "code",
390 | "execution_count": null,
391 | "metadata": {
392 | "scrolled": true
393 | },
394 | "outputs": [],
395 | "source": [
396 | "fib(7)"
397 | ]
398 | },
399 | {
400 | "cell_type": "markdown",
401 | "metadata": {},
402 | "source": [
403 | "To display a **fancier version** of this call graph of your recursion, head to https://anandology.com/python-practice-book/functional-programming.html and have a look at their ``trace`` function."
404 | ]
405 | },
406 | {
407 | "cell_type": "markdown",
408 | "metadata": {},
409 | "source": [
410 | "## Memoization"
411 | ]
412 | },
413 | {
414 | "cell_type": "markdown",
415 | "metadata": {},
416 | "source": [
417 | "As you can see in the above call graph, the same function values are calculated multiple times. This can be avoided by using the Memoization technique aka caching the output"
418 | ]
419 | },
420 | {
421 | "cell_type": "code",
422 | "execution_count": null,
423 | "metadata": {},
424 | "outputs": [],
425 | "source": [
426 | "from functools import lru_cache\n",
427 | "\n",
428 | "fib = lru_cache(100)(fib)"
429 | ]
430 | },
431 | {
432 | "cell_type": "code",
433 | "execution_count": null,
434 | "metadata": {},
435 | "outputs": [],
436 | "source": [
437 | "fib(20)"
438 | ]
439 | },
440 | {
441 | "cell_type": "markdown",
442 | "metadata": {},
443 | "source": [
444 | "# Object oriented programming"
445 | ]
446 | },
447 | {
448 | "cell_type": "markdown",
449 | "metadata": {},
450 | "source": [
451 | "There will be more exercises about OOP in the exercises for the next lecture \"Design Patterns\".\n",
452 | "This time we will only cover the absolute basics."
453 | ]
454 | },
455 | {
456 | "cell_type": "markdown",
457 | "metadata": {},
458 | "source": [
459 | "## Abstract methods"
460 | ]
461 | },
462 | {
463 | "cell_type": "code",
464 | "execution_count": null,
465 | "metadata": {
466 | "ExecuteTime": {
467 | "end_time": "2020-09-27T12:27:44.828931Z",
468 | "start_time": "2020-09-27T12:27:44.825794Z"
469 | }
470 | },
471 | "outputs": [],
472 | "source": [
473 | "from abc import ABC, abstractmethod"
474 | ]
475 | },
476 | {
477 | "cell_type": "code",
478 | "execution_count": null,
479 | "metadata": {
480 | "ExecuteTime": {
481 | "end_time": "2020-09-27T12:28:04.055057Z",
482 | "start_time": "2020-09-27T12:28:04.049088Z"
483 | }
484 | },
485 | "outputs": [],
486 | "source": [
487 | "class Shape(ABC):\n",
488 | " @abstractmethod\n",
489 | " def calculate_area(self):\n",
490 | " pass"
491 | ]
492 | },
493 | {
494 | "cell_type": "markdown",
495 | "metadata": {},
496 | "source": [
497 | "**Exercise**: Write a subclass ``Rectangle`` of ``Shape``."
498 | ]
499 | },
500 | {
501 | "cell_type": "markdown",
502 | "metadata": {
503 | "ExecuteTime": {
504 | "end_time": "2020-09-27T12:29:20.307535Z",
505 | "start_time": "2020-09-27T12:29:20.297821Z"
506 | }
507 | },
508 | "source": [
509 | "\n",
510 | "\n",
511 | " Click me for the solution
\n",
512 | " \n",
513 | "```python\n",
514 | "class Rectangle(Shape):\n",
515 | " def __init__(self, a, b):\n",
516 | " self.a = a\n",
517 | " self.b = b\n",
518 | " \n",
519 | " def calculate_area(self):\n",
520 | " return self.a * self.b\n",
521 | "```\n",
522 | " \n",
523 | " \n",
524 | ""
525 | ]
526 | }
527 | ],
528 | "metadata": {
529 | "kernelspec": {
530 | "display_name": "Python 3",
531 | "language": "python",
532 | "name": "python3"
533 | },
534 | "language_info": {
535 | "codemirror_mode": {
536 | "name": "ipython",
537 | "version": 3
538 | },
539 | "file_extension": ".py",
540 | "mimetype": "text/x-python",
541 | "name": "python",
542 | "nbconvert_exporter": "python",
543 | "pygments_lexer": "ipython3",
544 | "version": "3.7.5"
545 | },
546 | "toc": {
547 | "base_numbering": 1,
548 | "nav_menu": {},
549 | "number_sections": true,
550 | "sideBar": true,
551 | "skip_h1_title": false,
552 | "title_cell": "Table of Contents",
553 | "title_sidebar": "Contents",
554 | "toc_cell": false,
555 | "toc_position": {},
556 | "toc_section_display": true,
557 | "toc_window_display": false
558 | },
559 | "varInspector": {
560 | "cols": {
561 | "lenName": 16,
562 | "lenType": 16,
563 | "lenVar": 40
564 | },
565 | "kernels_config": {
566 | "python": {
567 | "delete_cmd_postfix": "",
568 | "delete_cmd_prefix": "del ",
569 | "library": "var_list.py",
570 | "varRefreshCmd": "print(var_dic_list())"
571 | },
572 | "r": {
573 | "delete_cmd_postfix": ") ",
574 | "delete_cmd_prefix": "rm(",
575 | "library": "var_list.r",
576 | "varRefreshCmd": "cat(var_dic_list()) "
577 | }
578 | },
579 | "types_to_exclude": [
580 | "module",
581 | "function",
582 | "builtin_function_or_method",
583 | "instance",
584 | "_Feature"
585 | ],
586 | "window_display": false
587 | }
588 | },
589 | "nbformat": 4,
590 | "nbformat_minor": 4
591 | }
592 |
--------------------------------------------------------------------------------
/license.md:
--------------------------------------------------------------------------------
1 | # LICENSE-CC-BY-4.0.md
2 |
3 | UNLESS OTHERWISE NOTED, THE CONTENTS OF THIS DIRECTORY ARE LICENSED UNDER THE CREATIVE COMMONS ATTRIBUTION 4.0 INTERNATIONAL LICENSE.
4 |
5 |  
6 |
7 | ## License Summary of CC-BY 4.0 International
8 |
9 | *This section is a human-readable summary of (and not a substitute for) the full license included below.*
10 |
11 | ### You are free to:
12 |
13 | * **Share** — copy and redistribute the material in any medium or format
14 | * **Adapt** — remix, transform, and build upon the material for any purpose, even commercially.
15 |
16 | The licensor cannot revoke these freedoms as long as you follow the license terms.
17 |
18 | ### Under the following terms:
19 |
20 | *  **Attribution** — You must give **appropriate credit**, provide **a link to the license**, and **indicate if changes were made**. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
21 |
22 | **No additional restrictions** — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
23 |
24 | ### Notices:
25 |
26 | You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable **exception or limitation**.
27 |
28 | No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as **publicity, privacy, or moral rights** may limit how you use the material.
29 |
30 | # Creative Commons Attribution 4.0 International License
31 |
32 | FROM: https://creativecommons.org/licenses/by/4.0/
33 |
34 | Creative Commons Corporation (“Creative Commons”) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an “as-is” basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible.
35 |
36 | ### Using Creative Commons Public Licenses
37 |
38 | Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses.
39 |
40 | * __Considerations for licensors:__ Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. [More considerations for licensors](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensors).
41 |
42 | * __Considerations for the public:__ By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor’s permission is not necessary for any reason–for example, because of any applicable exception or limitation to copyright–then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. [More considerations for the public](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensees).
43 |
44 | ## Creative Commons Attribution 4.0 International Public License
45 |
46 | By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.
47 |
48 | **Section 1 – Definitions.**
49 |
50 | 1. **Adapted Material** means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image.
51 | 2. **Adapter's License** means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License.
52 | 3. **Copyright and Similar Rights** means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights.
53 | 4. **Effective Technological Measures** means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements.
54 | 5. **Exceptions and Limitations** means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material.
55 | 6. **Licensed Material** means the artistic or literary work, database, or other material to which the Licensor applied this Public License.
56 | 7. **Licensed Rights** means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license.
57 | 8. **Licensor** means the individual(s) or entity(ies) granting rights under this Public License.
58 | 9. **Share** means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them.
59 | 10. **Sui Generis Database Rights** means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world.
60 | 11. **You** means the individual or entity exercising the Licensed Rights under this Public License. **Your** has a corresponding meaning.
61 |
62 | **Section 2 – Scope.**
63 |
64 | 1. **License grant**.
65 | 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to:
66 | 1. reproduce and Share the Licensed Material, in whole or in part; and
67 | 2. produce, reproduce, and Share Adapted Material.
68 | 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions.
69 | 3. Term. The term of this Public License is specified in Section 6(a).
70 | 4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material.
71 | 5. Downstream recipients.
72 |
73 | 1. Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License.
74 | 2. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material.
75 |
76 | 6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i).
77 | 2. **Other rights**.
78 |
79 | 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise.
80 | 2. Patent and trademark rights are not licensed under this Public License.
81 | 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties.
82 |
83 | **Section 3 – License Conditions.**
84 |
85 | Your exercise of the Licensed Rights is expressly made subject to the following conditions.
86 |
87 | 1. **Attribution**.
88 |
89 | 1. If You Share the Licensed Material (including in modified form), You must:
90 |
91 | 1. retain the following if it is supplied by the Licensor with the Licensed Material:
92 | 1. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated);
93 | 2. a copyright notice;
94 | 3. a notice that refers to this Public License;
95 | 4. a notice that refers to the disclaimer of warranties;
96 | 5. a URI or hyperlink to the Licensed Material to the extent reasonably practicable;
97 | 2. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and
98 | 3. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License.
99 | 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information.
100 | 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable.
101 | 4. If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License.
102 |
103 | **Section 4 – Sui Generis Database Rights.**
104 |
105 | Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material:
106 |
107 | 1. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database;
108 | 2. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and
109 | 3. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database.
110 | For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights.
111 |
112 | **Section 5 – Disclaimer of Warranties and Limitation of Liability.**
113 |
114 | 1. **Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.**
115 | 2. **To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.**
116 | 3. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability.
117 |
118 | **Section 6 – Term and Termination.**
119 |
120 | 1. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically.
121 | 2. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates:
122 |
123 | 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or
124 | 2. upon express reinstatement by the Licensor.
125 | For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License.
126 | 3. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License.
127 | 4. Sections 1, 5, 6, 7, and 8 survive termination of this Public License.
128 |
129 | **Section 7 – Other Terms and Conditions.**
130 |
131 | 1. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed.
132 | 2. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License.
133 |
134 | **Section 8 – Interpretation.**
135 |
136 | 1. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License.
137 | 2. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions.
138 | 3. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor.
139 | 4. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority.
140 |
141 | ---
142 |
143 | *Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the "Licensor." The text of the Creative Commons public licenses is dedicated to the public domain under the [CC0 Public Domain Dedication](http://creativecommons.org/publicdomain/zero/1.0/legalcode). Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at [creativecommons.org/policies](http://creativecommons.org/policies), Creative Commons does not authorize the use of the trademark "Creative Commons" or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses.*
144 |
145 | *Creative Commons may be contacted at [creativecommons.org](http://creativecommons.org/).*
146 |
147 | *Additional languages available: [Bahasa Indonesia](http://creativecommons.org/licenses/by/4.0/legalcode.id), [Nederlands](http://creativecommons.org/licenses/by/4.0/legalcode.nl), [norsk](http://creativecommons.org/licenses/by/4.0/legalcode.no), [suomeksi](http://creativecommons.org/licenses/by/4.0/legalcode.fi), [te reo Māori](http://creativecommons.org/licenses/by/4.0/legalcode.mi), [українська](http://creativecommons.org/licenses/by/4.0/legalcode.uk), [日本語](http://creativecommons.org/licenses/by/4.0/legalcode.ja). Please read the [FAQ](http://wiki.creativecommons.org/FAQ#officialtranslations) for more information about official translations.*
148 |
149 | ---
150 |
--------------------------------------------------------------------------------
/exercises/patterns.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Software Design Patterns"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": null,
13 | "metadata": {
14 | "ExecuteTime": {
15 | "end_time": "2020-09-30T09:54:35.935177Z",
16 | "start_time": "2020-09-30T09:54:35.648549Z"
17 | }
18 | },
19 | "outputs": [],
20 | "source": [
21 | "import matplotlib.pyplot as plt\n",
22 | "from abc import ABC, abstractmethod\n",
23 | "import numpy as np"
24 | ]
25 | },
26 | {
27 | "cell_type": "markdown",
28 | "metadata": {},
29 | "source": [
30 | "If the last line didn't work, please install matplotlib, e.g. by\n",
31 | "typing ``pip3 install --user install matplotlib``."
32 | ]
33 | },
34 | {
35 | "cell_type": "markdown",
36 | "metadata": {
37 | "heading_collapsed": true
38 | },
39 | "source": [
40 | "# Creational patterns"
41 | ]
42 | },
43 | {
44 | "cell_type": "markdown",
45 | "metadata": {
46 | "heading_collapsed": true,
47 | "hidden": true
48 | },
49 | "source": [
50 | "## Factory method pattern"
51 | ]
52 | },
53 | {
54 | "cell_type": "code",
55 | "execution_count": null,
56 | "metadata": {
57 | "ExecuteTime": {
58 | "end_time": "2020-09-30T09:47:41.656789Z",
59 | "start_time": "2020-09-30T09:47:41.628499Z"
60 | },
61 | "hidden": true
62 | },
63 | "outputs": [],
64 | "source": [
65 | "class Histogram(object):\n",
66 | " def __init__(self, bin_contents=None, bin_edges=None, data=None, nbins=10):\n",
67 | " \"\"\" Initialize histogram either by directly giving bin contents and edges\n",
68 | " or from data.\n",
69 | " \n",
70 | " Args:\n",
71 | " bin_contents: List of bin contents\n",
72 | " bin_edges: List of bin edges (n+1 values for n bins)\n",
73 | " data: List of data points that will be automatically binned\n",
74 | " nbins: Number of bins to bin data in, if bin_edges is not given\n",
75 | " \"\"\"\n",
76 | " if bin_contents is not None and bin_edges is not None:\n",
77 | " self.bin_contents = bin_contents\n",
78 | " self.bin_edges = bin_edges\n",
79 | " elif data is not None:\n",
80 | " if bin_edges is not None:\n",
81 | " self.bin_contents, self.bin_edges = np.histogram(data, bins=bin_edges)\n",
82 | " else:\n",
83 | " self.bin_contents, self.bin_edges = np.histogram(data, bins=nbins)\n",
84 | "\n",
85 | "h1 = Histogram(bin_contents=[1, 2, 3], bin_edges=[1, 2, 3, 4])\n",
86 | "h2 = Histogram(data=[1, 5, 7, 8, 4, 2, 2, 3, 4], nbins=5)"
87 | ]
88 | },
89 | {
90 | "cell_type": "markdown",
91 | "metadata": {
92 | "ExecuteTime": {
93 | "end_time": "2020-09-30T09:40:34.975903Z",
94 | "start_time": "2020-09-30T09:40:34.960933Z"
95 | },
96 | "hidden": true
97 | },
98 | "source": [
99 | "**Exercise**: Simplify the constructor using the factory method pattern. \n",
100 | "How can you recreate the two objects from before?"
101 | ]
102 | },
103 | {
104 | "cell_type": "markdown",
105 | "metadata": {
106 | "ExecuteTime": {
107 | "end_time": "2020-09-30T09:44:00.108067Z",
108 | "start_time": "2020-09-30T09:44:00.090870Z"
109 | },
110 | "hidden": true
111 | },
112 | "source": [
113 | "\n",
114 | "\n",
115 | " Click me for a hint
\n",
116 | " Change the __init__ constructor so that it only takes bin_contents and bin_edges.\n",
117 | "Create a new classmethod from_data that handles the construction from data. \n",
118 | " \n",
119 | ""
120 | ]
121 | },
122 | {
123 | "cell_type": "markdown",
124 | "metadata": {
125 | "ExecuteTime": {
126 | "end_time": "2020-09-30T09:46:53.869360Z",
127 | "start_time": "2020-09-30T09:46:53.855654Z"
128 | },
129 | "hidden": true
130 | },
131 | "source": [
132 | "\n",
133 | "\n",
134 | " Click me for the solution
\n",
135 | "Define the classmethod as follows.\n",
136 | "\n",
137 | "```python\n",
138 | "class Histogram(object):\n",
139 | " def __init__(self, bin_contents, bin_edges):\n",
140 | " self.bin_contents = bin_contents\n",
141 | " self.bin_edges = bin_edges\n",
142 | " \n",
143 | " @classmethod\n",
144 | " def from_data(cls, data, bin_edges=None, nbins=10):\n",
145 | " if bin_edges is not None:\n",
146 | " bin_contents, bin_edges = np.histogram(data, bins=bin_edges)\n",
147 | " else:\n",
148 | " bin_contents, bin_edges = np.histogram(data, bins=nbins)\n",
149 | " return cls(bin_contents=bin_contents, bin_edges=bin_edges)\n",
150 | "\n",
151 | "h1 = Histogram(bin_contents=[1, 2, 3], bin_edges=[1, 2, 3, 4])\n",
152 | "h2 = Histogram.from_data(data=[1, 5, 7, 8, 4, 2, 2, 3, 4], nbins=5)\n",
153 | "```\n",
154 | " \n",
155 | ""
156 | ]
157 | },
158 | {
159 | "cell_type": "markdown",
160 | "metadata": {
161 | "heading_collapsed": true,
162 | "hidden": true
163 | },
164 | "source": [
165 | "## Builder pattern"
166 | ]
167 | },
168 | {
169 | "cell_type": "markdown",
170 | "metadata": {
171 | "hidden": true
172 | },
173 | "source": [
174 | "Let's look at the following example of a class for plotting (you can run the next two cells to get an idea about what it does)."
175 | ]
176 | },
177 | {
178 | "cell_type": "code",
179 | "execution_count": null,
180 | "metadata": {
181 | "ExecuteTime": {
182 | "end_time": "2020-09-27T16:23:31.806437Z",
183 | "start_time": "2020-09-27T16:23:31.755189Z"
184 | },
185 | "hidden": true
186 | },
187 | "outputs": [],
188 | "source": [
189 | "class ComplexPlot(object):\n",
190 | " def __init__(self, xvalues, yvalues, colors, labels, hlines, vlines, hlinecolors, vlinecolors):\n",
191 | " self.xvalues = xvalues\n",
192 | " self.yvalues = yvalues\n",
193 | " self.colors = colors\n",
194 | " self.labels = labels\n",
195 | " self.hlines = hlines\n",
196 | " self.vlines = vlines\n",
197 | " self.hlinecolors = hlinecolors\n",
198 | " self.vlinecolors = vlinecolors\n",
199 | " \n",
200 | " def plot(self):\n",
201 | " fig, ax = plt.subplots()\n",
202 | " for i in range(len(self.xvalues)):\n",
203 | " ax.plot(self.xvalues[i], self.yvalues[i], color=self.colors[i], label=self.labels[i])\n",
204 | " for i in range(len(self.hlines)):\n",
205 | " ax.axhline(self.hlines[i], color=self.hlinecolors[i])\n",
206 | " for i in range(len(self.vlines)):\n",
207 | " ax.axvline(self.vlines[i], color=self.vlinecolors[i])\n",
208 | " ax.legend()\n",
209 | " return ax"
210 | ]
211 | },
212 | {
213 | "cell_type": "code",
214 | "execution_count": null,
215 | "metadata": {
216 | "ExecuteTime": {
217 | "end_time": "2020-09-27T16:24:04.925552Z",
218 | "start_time": "2020-09-27T16:24:04.656293Z"
219 | },
220 | "hidden": true
221 | },
222 | "outputs": [],
223 | "source": [
224 | "c = ComplexPlot(\n",
225 | " xvalues=[[1, 2, 3], [1, 2, 3]],\n",
226 | " yvalues=[[1, 2, 3], [4, 5, 6]],\n",
227 | " colors=[\"black\", \"red\"],\n",
228 | " labels=[\"label 1\", \"label 2\"],\n",
229 | " hlines=[1],\n",
230 | " vlines=[2],\n",
231 | " hlinecolors=[\"yellow\"],\n",
232 | " vlinecolors=[\"gray\"]\n",
233 | ")\n",
234 | "c.plot()"
235 | ]
236 | },
237 | {
238 | "cell_type": "markdown",
239 | "metadata": {
240 | "ExecuteTime": {
241 | "end_time": "2020-09-27T16:25:45.440750Z",
242 | "start_time": "2020-09-27T16:25:45.428730Z"
243 | },
244 | "hidden": true
245 | },
246 | "source": [
247 | "**Exercise**: \n",
248 | "\n",
249 | "1. Make use of the *builder pattern* to simplify the above class and to make it more flexible. \n",
250 | "2. Reproduce the plot with your new class"
251 | ]
252 | },
253 | {
254 | "cell_type": "markdown",
255 | "metadata": {
256 | "ExecuteTime": {
257 | "end_time": "2020-09-27T16:30:21.591750Z",
258 | "start_time": "2020-09-27T16:30:21.530636Z"
259 | },
260 | "hidden": true
261 | },
262 | "source": [
263 | "\n",
264 | "\n",
265 | " Click me for the solution
\n",
266 | " \n",
267 | "```python\n",
268 | "class ComplexPlot(object):\n",
269 | " def __init__(self):\n",
270 | " self.xvalues = []\n",
271 | " self.yvalues = []\n",
272 | " self.colors = []\n",
273 | " self.labels = []\n",
274 | " self.hlines = []\n",
275 | " self.vlines = []\n",
276 | " self.hlinecolors = []\n",
277 | " self.vlinecolors = []\n",
278 | " \n",
279 | " def add_dataset(self, x, y, color=\"black\", label=\"\"):\n",
280 | " self.xvalues.append(x)\n",
281 | " self.yvalues.append(y)\n",
282 | " self.colors.append(color)\n",
283 | " self.labels.append(label)\n",
284 | " \n",
285 | " def add_hline(self, y, color=\"black\"):\n",
286 | " self.hlines.append(y)\n",
287 | " self.hlinecolors.append(color)\n",
288 | " \n",
289 | " def add_vline(self, y, color=\"black\"):\n",
290 | " self.hlines.append(y)\n",
291 | " self.hlinecolors.append(color)\n",
292 | " \n",
293 | " def plot(self):\n",
294 | " fig, ax = plt.subplots()\n",
295 | " for i in range(len(self.xvalues)):\n",
296 | " ax.plot(self.xvalues[i], self.yvalues[i], color=self.colors[i], label=self.labels[i])\n",
297 | " for i in range(len(self.hlines)):\n",
298 | " ax.axhline(self.hlines[i], color=self.hlinecolors[i])\n",
299 | " for i in range(len(self.vlines)):\n",
300 | " ax.axvline(self.vlines[i], color=self.vlinecolors[i])\n",
301 | " ax.legend()\n",
302 | " return ax\n",
303 | "\n",
304 | "c = ComplexPlot()\n",
305 | "c.add_dataset([1, 2, 3], [1, 2, 3], label=\"label 1\")\n",
306 | "c.add_dataset([1, 2, 3], [4, 5, 6], color=\"red\", label=\"label 2\")\n",
307 | "c.add_hline(1, color=\"yellow\")\n",
308 | "c.add_vline(2, color=\"gray\")\n",
309 | "c.plot()\n",
310 | "```\n",
311 | " \n",
312 | " \n",
313 | ""
314 | ]
315 | },
316 | {
317 | "cell_type": "markdown",
318 | "metadata": {
319 | "heading_collapsed": true
320 | },
321 | "source": [
322 | "# Structural patterns"
323 | ]
324 | },
325 | {
326 | "cell_type": "markdown",
327 | "metadata": {
328 | "hidden": true
329 | },
330 | "source": [
331 | "## Adapter"
332 | ]
333 | },
334 | {
335 | "cell_type": "markdown",
336 | "metadata": {
337 | "hidden": true
338 | },
339 | "source": [
340 | "You have a nice setup for dealing with lamps:"
341 | ]
342 | },
343 | {
344 | "cell_type": "code",
345 | "execution_count": null,
346 | "metadata": {
347 | "ExecuteTime": {
348 | "end_time": "2020-09-27T16:43:15.942366Z",
349 | "start_time": "2020-09-27T16:43:15.924067Z"
350 | },
351 | "hidden": true
352 | },
353 | "outputs": [],
354 | "source": [
355 | "class Lamp(ABC):\n",
356 | " \"\"\" Interface of my lamps. \"\"\"\n",
357 | " @abstractmethod\n",
358 | " def toggle(self):\n",
359 | " pass\n",
360 | "\n",
361 | "class MyOldLamp(Lamp):\n",
362 | " \"\"\" This is one of my specific lamps. \"\"\"\n",
363 | " def __init__(self):\n",
364 | " self._turned_on = False\n",
365 | " \n",
366 | " def get_state(self):\n",
367 | " # (Note for advanced python users: \n",
368 | " # Accessor function because lecture didn't introduce\n",
369 | " # the '@property' decorator)\n",
370 | " return self._turned_on\n",
371 | " \n",
372 | " def toggle(self):\n",
373 | " self._turned_on = not self._turned_on\n",
374 | "\n",
375 | "\n",
376 | "def report_and_switch_on_lamp(lamp: Lamp):\n",
377 | " \"\"\" This function prints whether the lamp is lit\n",
378 | " and if not, flips the switch. \"\"\"\n",
379 | " if lamp.get_state():\n",
380 | " print(\"Lamp is lit\")\n",
381 | " else:\n",
382 | " print(\"Lamp is dark\")\n",
383 | " lamp.toggle()"
384 | ]
385 | },
386 | {
387 | "cell_type": "markdown",
388 | "metadata": {
389 | "hidden": true
390 | },
391 | "source": [
392 | "Let's try it!"
393 | ]
394 | },
395 | {
396 | "cell_type": "code",
397 | "execution_count": null,
398 | "metadata": {
399 | "ExecuteTime": {
400 | "end_time": "2020-09-27T16:42:17.948020Z",
401 | "start_time": "2020-09-27T16:42:17.938499Z"
402 | },
403 | "hidden": true
404 | },
405 | "outputs": [],
406 | "source": [
407 | "mol = MyOldLamp()\n",
408 | "\n",
409 | "report_and_switch_on_lamp(mol)\n",
410 | "report_and_switch_on_lamp(mol)"
411 | ]
412 | },
413 | {
414 | "cell_type": "markdown",
415 | "metadata": {
416 | "hidden": true
417 | },
418 | "source": [
419 | "Let's try with a new lamp:"
420 | ]
421 | },
422 | {
423 | "cell_type": "code",
424 | "execution_count": null,
425 | "metadata": {
426 | "ExecuteTime": {
427 | "end_time": "2020-09-27T16:43:29.099310Z",
428 | "start_time": "2020-09-27T16:43:29.081037Z"
429 | },
430 | "hidden": true
431 | },
432 | "outputs": [],
433 | "source": [
434 | "class MyNewLamp():\n",
435 | " def __init__(self):\n",
436 | " self.turned_on = False\n",
437 | " \n",
438 | " def get_state(self):\n",
439 | " return self.turned_on\n",
440 | " \n",
441 | " def flip_switch(self):\n",
442 | " self.turned_on = not self.turned_on"
443 | ]
444 | },
445 | {
446 | "cell_type": "code",
447 | "execution_count": null,
448 | "metadata": {
449 | "ExecuteTime": {
450 | "end_time": "2020-09-27T16:44:25.968814Z",
451 | "start_time": "2020-09-27T16:44:25.948987Z"
452 | },
453 | "hidden": true
454 | },
455 | "outputs": [],
456 | "source": [
457 | "mnl = MyNewLamp()\n",
458 | "report_and_switch_on_lamp(mnl)\n",
459 | "report_and_switch_on_lamp(mnl) # Ooouch"
460 | ]
461 | },
462 | {
463 | "cell_type": "markdown",
464 | "metadata": {
465 | "hidden": true
466 | },
467 | "source": [
468 | "That didn't work!"
469 | ]
470 | },
471 | {
472 | "cell_type": "markdown",
473 | "metadata": {
474 | "hidden": true
475 | },
476 | "source": [
477 | "**Exercise**: Create an adapter class for ``MyNewLamp``"
478 | ]
479 | },
480 | {
481 | "cell_type": "markdown",
482 | "metadata": {
483 | "ExecuteTime": {
484 | "end_time": "2020-09-27T16:43:59.438902Z",
485 | "start_time": "2020-09-27T16:43:59.407197Z"
486 | },
487 | "hidden": true
488 | },
489 | "source": [
490 | "\n",
491 | "\n",
492 | " Click me for the solution
\n",
493 | " \n",
494 | "```python\n",
495 | "class MyNewLampAdapter(Lamp):\n",
496 | " def __init__(self, lamp: MyNewLamp):\n",
497 | " self._lamp = lamp\n",
498 | " \n",
499 | " def get_state(self):\n",
500 | " return self._lamp.get_state()\n",
501 | " \n",
502 | " def toggle(self):\n",
503 | " self._lamp.flip_switch()\n",
504 | "\n",
505 | "mnl = MyNewLampAdapter(MyNewLamp())\n",
506 | "report_and_switch_on_lamp(mnl)\n",
507 | "report_and_switch_on_lamp(mnl)\n",
508 | "```\n",
509 | " \n",
510 | " \n",
511 | ""
512 | ]
513 | },
514 | {
515 | "cell_type": "markdown",
516 | "metadata": {
517 | "heading_collapsed": true
518 | },
519 | "source": [
520 | "# Behavioral patterns"
521 | ]
522 | },
523 | {
524 | "cell_type": "markdown",
525 | "metadata": {
526 | "heading_collapsed": true,
527 | "hidden": true
528 | },
529 | "source": [
530 | "## Template method"
531 | ]
532 | },
533 | {
534 | "cell_type": "code",
535 | "execution_count": null,
536 | "metadata": {
537 | "ExecuteTime": {
538 | "end_time": "2020-09-30T09:52:34.068993Z",
539 | "start_time": "2020-09-30T09:52:34.037091Z"
540 | },
541 | "hidden": true
542 | },
543 | "outputs": [],
544 | "source": [
545 | "class MLModel():\n",
546 | " def __init__(self, model=\"BDT\"):\n",
547 | " self.model = model\n",
548 | " \n",
549 | " def prepare_features(self):\n",
550 | " if self.model == \"BDT\":\n",
551 | " print(\"Preparing features for BDT\")\n",
552 | " elif self.model == \"RandomForest\":\n",
553 | " print(\"Preparing features for RandomForest\")\n",
554 | " else:\n",
555 | " raise ValueError(\"Invalid model\")\n",
556 | " \n",
557 | " def train(self):\n",
558 | " if self.model == \"BDT\":\n",
559 | " print(\"Training BDT model\")\n",
560 | " elif self.model == \"RandomForest\":\n",
561 | " print(\"Training RandomForest\")\n",
562 | " else:\n",
563 | " raise ValueError(\"Invalid model\")\n",
564 | " \n",
565 | " def validate(self):\n",
566 | " print(\"Your model is doing okayish...\")\n",
567 | " \n",
568 | " \n",
569 | " def run_all(self):\n",
570 | " self.prepare_features()\n",
571 | " self.train()\n",
572 | " self.validate()\n",
573 | "\n",
574 | "m1 = MLModel(model=\"BDT\")\n",
575 | "m1.run_all()\n",
576 | "\n",
577 | "m2 = MLModel(model=\"RandomForest\")\n",
578 | "m2.run_all()"
579 | ]
580 | },
581 | {
582 | "cell_type": "markdown",
583 | "metadata": {
584 | "hidden": true
585 | },
586 | "source": [
587 | "**Exercise**: What are the problems here? How can you solve them with the template method pattern?"
588 | ]
589 | },
590 | {
591 | "cell_type": "markdown",
592 | "metadata": {
593 | "ExecuteTime": {
594 | "end_time": "2020-09-30T09:56:52.670723Z",
595 | "start_time": "2020-09-30T09:56:52.653279Z"
596 | },
597 | "hidden": true
598 | },
599 | "source": [
600 | "\n",
601 | "\n",
602 | " Click me for a hint
\n",
603 | " Make the prepare_features and train methods of MLModel abstract.\n",
604 | " Create two subclasses that implement them.\n",
605 | " \n",
606 | ""
607 | ]
608 | },
609 | {
610 | "cell_type": "markdown",
611 | "metadata": {
612 | "ExecuteTime": {
613 | "end_time": "2020-09-30T09:57:19.356616Z",
614 | "start_time": "2020-09-30T09:57:19.346542Z"
615 | },
616 | "hidden": true
617 | },
618 | "source": [
619 | "\n",
620 | "\n",
621 | " Click me for a hint
\n",
622 | "Your code for the new class might look like this:\n",
623 | "\n",
624 | "```python\n",
625 | "class MLModel(ABC):\n",
626 | " \n",
627 | " @abstractmethod\n",
628 | " def prepare_features(self):\n",
629 | " pass\n",
630 | " \n",
631 | " @abstractmethod\n",
632 | " def train(self):\n",
633 | " pass\n",
634 | " \n",
635 | " def validate(self):\n",
636 | " print(\"Your model is doing okayish...\")\n",
637 | " \n",
638 | " \n",
639 | " def run_all(self):\n",
640 | " self.prepare_features()\n",
641 | " self.train()\n",
642 | " self.validate()\n",
643 | "```\n",
644 | " \n",
645 | ""
646 | ]
647 | },
648 | {
649 | "cell_type": "markdown",
650 | "metadata": {
651 | "ExecuteTime": {
652 | "end_time": "2020-09-30T09:58:06.526593Z",
653 | "start_time": "2020-09-30T09:58:06.518035Z"
654 | },
655 | "hidden": true
656 | },
657 | "source": [
658 | "\n",
659 | "\n",
660 | " Click me for a hint
\n",
661 | "Your code for one of the subclasses might look like this:\n",
662 | "\n",
663 | "```python\n",
664 | "class BDT(MLModel):\n",
665 | " def prepare_features(self):\n",
666 | " print(\"Preparing features for BDT\")\n",
667 | " \n",
668 | " def train(self):\n",
669 | " print(\"Training BDT\")\n",
670 | "```\n",
671 | " \n",
672 | ""
673 | ]
674 | },
675 | {
676 | "cell_type": "markdown",
677 | "metadata": {
678 | "ExecuteTime": {
679 | "end_time": "2020-09-30T09:58:25.169566Z",
680 | "start_time": "2020-09-30T09:58:25.148930Z"
681 | },
682 | "hidden": true
683 | },
684 | "source": [
685 | "\n",
686 | "\n",
687 | " Click me for the solution
\n",
688 | "Full solution:\n",
689 | "\n",
690 | "```python\n",
691 | "class MLModel(ABC):\n",
692 | " \n",
693 | " @abstractmethod\n",
694 | " def prepare_features(self):\n",
695 | " pass\n",
696 | " \n",
697 | " @abstractmethod\n",
698 | " def train(self):\n",
699 | " pass\n",
700 | " \n",
701 | " def validate(self):\n",
702 | " print(\"Your model is doing okayish...\")\n",
703 | " \n",
704 | " \n",
705 | " def run_all(self):\n",
706 | " self.prepare_features()\n",
707 | " self.train()\n",
708 | " self.validate()\n",
709 | " \n",
710 | "class BDT(MLModel):\n",
711 | " def prepare_features(self):\n",
712 | " print(\"Preparing features for BDT\")\n",
713 | " \n",
714 | " def train(self):\n",
715 | " print(\"Training BDT\")\n",
716 | "\n",
717 | "class RandomForest(MLModel):\n",
718 | " def prepare_features(self):\n",
719 | " print(\"Preparing features for RandomForest\")\n",
720 | " \n",
721 | " def train(self):\n",
722 | " print(\"Training RandomForest\")\n",
723 | "\n",
724 | "m1 = BDT()\n",
725 | "m1.run_all()\n",
726 | "\n",
727 | "m2 = RandomForest()\n",
728 | "m2.run_all()\n",
729 | "```\n",
730 | " \n",
731 | ""
732 | ]
733 | },
734 | {
735 | "cell_type": "markdown",
736 | "metadata": {
737 | "heading_collapsed": true,
738 | "hidden": true
739 | },
740 | "source": [
741 | "## Strategy pattern"
742 | ]
743 | },
744 | {
745 | "cell_type": "markdown",
746 | "metadata": {
747 | "hidden": true
748 | },
749 | "source": [
750 | "**Exercise**: Look at the strategy pattern example in the slides. Build up a similar ``MyAnalysis`` class that \n",
751 | "takes two machine learning models ``ml_model_1`` and ``ml_model_2``. Use the example from the last exercise\n",
752 | "to initialize it."
753 | ]
754 | },
755 | {
756 | "cell_type": "code",
757 | "execution_count": null,
758 | "metadata": {
759 | "ExecuteTime": {
760 | "end_time": "2020-09-30T10:06:09.687586Z",
761 | "start_time": "2020-09-30T10:06:09.671643Z"
762 | },
763 | "hidden": true
764 | },
765 | "outputs": [],
766 | "source": [
767 | "class MyAnalysis(object):\n",
768 | " def __init__(self, ml_model_1, ml_model_2):\n",
769 | " # your code here\n",
770 | " pass\n",
771 | " \n",
772 | " def run_all(self):\n",
773 | " # your code here\n",
774 | " # this should now call prepare_features for both\n",
775 | " # models, then train them, then validate them\n",
776 | " pass\n",
777 | "\n",
778 | "\n",
779 | "# Initialize an analysis with two BDTs\n",
780 | "# ma1 = your code here \n",
781 | "# ma1.run_all()\n",
782 | "# Initialize an analysis with a BDT and a RandomForest\n",
783 | "# ma2 = your code here\n",
784 | "# ma2.run_all()"
785 | ]
786 | },
787 | {
788 | "cell_type": "markdown",
789 | "metadata": {
790 | "ExecuteTime": {
791 | "end_time": "2020-09-30T10:05:07.794303Z",
792 | "start_time": "2020-09-30T10:05:07.778699Z"
793 | },
794 | "hidden": true
795 | },
796 | "source": [
797 | "\n",
798 | "\n",
799 | " Click me for a hint
\n",
800 | "Your constructor should simply save the two models\n",
801 | "\n",
802 | "```python\n",
803 | "def __init__(self, ml_model_1, ml_model_2):\n",
804 | " # your code here\n",
805 | " self.ml_model_1 = ml_model_1\n",
806 | " self.ml_model_2 = ml_model_2\n",
807 | "```\n",
808 | " \n",
809 | ""
810 | ]
811 | },
812 | {
813 | "cell_type": "markdown",
814 | "metadata": {
815 | "ExecuteTime": {
816 | "end_time": "2020-09-30T10:05:38.423743Z",
817 | "start_time": "2020-09-30T10:05:38.409761Z"
818 | },
819 | "hidden": true
820 | },
821 | "source": [
822 | "\n",
823 | "\n",
824 | " Click me for a hint
\n",
825 | "The full class should look like this:\n",
826 | " \n",
827 | "```python\n",
828 | "class MyAnalysis(object):\n",
829 | " def __init__(self, ml_model_1, ml_model_2):\n",
830 | " # your code here\n",
831 | " self.ml_model_1 = ml_model_1\n",
832 | " self.ml_model_2 = ml_model_2\n",
833 | " \n",
834 | " def run_all(self):\n",
835 | " # your code here\n",
836 | " # this should now call prepare_features for both\n",
837 | " # models, then train them, then validate them\n",
838 | " self.ml_model_1.prepare_features()\n",
839 | " self.ml_model_2.prepare_features()\n",
840 | " self.ml_model_1.train()\n",
841 | " self.ml_model_2.train()\n",
842 | " self.ml_model_1.validate()\n",
843 | " self.ml_model_2.validate()\n",
844 | "```\n",
845 | "\n",
846 | "Now you still need to find out how to initialize and run it.\n",
847 | " \n",
848 | ""
849 | ]
850 | },
851 | {
852 | "cell_type": "markdown",
853 | "metadata": {
854 | "ExecuteTime": {
855 | "end_time": "2020-09-30T10:06:04.193017Z",
856 | "start_time": "2020-09-30T10:06:04.169746Z"
857 | },
858 | "hidden": true
859 | },
860 | "source": [
861 | "\n",
862 | "\n",
863 | " Click me for the solution
\n",
864 | "The full class should look like this:\n",
865 | " \n",
866 | "```python\n",
867 | "class MyAnalysis(object):\n",
868 | " def __init__(self, ml_model_1, ml_model_2):\n",
869 | " # your code here\n",
870 | " self.ml_model_1 = ml_model_1\n",
871 | " self.ml_model_2 = ml_model_2\n",
872 | " \n",
873 | " def run_all(self):\n",
874 | " # your code here\n",
875 | " # this should now call prepare_features for both\n",
876 | " # models, then train them, then validate them\n",
877 | " self.ml_model_1.prepare_features()\n",
878 | " self.ml_model_2.prepare_features()\n",
879 | " self.ml_model_1.train()\n",
880 | " self.ml_model_2.train()\n",
881 | " self.ml_model_1.validate()\n",
882 | " self.ml_model_2.validate()\n",
883 | "\n",
884 | "\n",
885 | "# Initialize an analysis with two BDTs\n",
886 | "ma1 = MyAnalysis(BDT(), BDT()) \n",
887 | "ma1.run_all()\n",
888 | "# Initialize an analysis with a BDT and a RandomForest\n",
889 | "ma2 = MyAnalysis(BDT(), RandomForest())\n",
890 | "ma2.run_all()\n",
891 | "```\n",
892 | "\n",
893 | "Now you still need to find out how to initialize and run it.\n",
894 | " \n",
895 | ""
896 | ]
897 | }
898 | ],
899 | "metadata": {
900 | "kernelspec": {
901 | "display_name": "Python 3",
902 | "language": "python",
903 | "name": "python3"
904 | },
905 | "language_info": {
906 | "codemirror_mode": {
907 | "name": "ipython",
908 | "version": 3
909 | },
910 | "file_extension": ".py",
911 | "mimetype": "text/x-python",
912 | "name": "python",
913 | "nbconvert_exporter": "python",
914 | "pygments_lexer": "ipython3",
915 | "version": "3.7.5"
916 | },
917 | "toc": {
918 | "base_numbering": 1,
919 | "nav_menu": {},
920 | "number_sections": true,
921 | "sideBar": true,
922 | "skip_h1_title": false,
923 | "title_cell": "Table of Contents",
924 | "title_sidebar": "Contents",
925 | "toc_cell": false,
926 | "toc_position": {},
927 | "toc_section_display": true,
928 | "toc_window_display": false
929 | },
930 | "varInspector": {
931 | "cols": {
932 | "lenName": 16,
933 | "lenType": 16,
934 | "lenVar": 40
935 | },
936 | "kernels_config": {
937 | "python": {
938 | "delete_cmd_postfix": "",
939 | "delete_cmd_prefix": "del ",
940 | "library": "var_list.py",
941 | "varRefreshCmd": "print(var_dic_list())"
942 | },
943 | "r": {
944 | "delete_cmd_postfix": ") ",
945 | "delete_cmd_prefix": "rm(",
946 | "library": "var_list.r",
947 | "varRefreshCmd": "cat(var_dic_list()) "
948 | }
949 | },
950 | "types_to_exclude": [
951 | "module",
952 | "function",
953 | "builtin_function_or_method",
954 | "instance",
955 | "_Feature"
956 | ],
957 | "window_display": false
958 | }
959 | },
960 | "nbformat": 4,
961 | "nbformat_minor": 4
962 | }
963 |
--------------------------------------------------------------------------------