├── 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 | [![DOI](https://zenodo.org/badge/240011587.svg)](https://zenodo.org/badge/latestdoi/240011587) 4 | [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/klieret/icsc-paradigms-and-patterns/master.svg)](https://results.pre-commit.ci/latest/github/klieret/icsc-paradigms-and-patterns/master) 5 | [![gh actions](https://github.com/klieret/icsc-paradigms-and-patterns/actions/workflows/workflow.yml/badge.svg)](https://github.com/klieret/icsc-paradigms-and-patterns/actions) 6 | [![git tutorial](https://img.shields.io/badge/PR-Welcome-%23FF8300.svg)](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 | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/klieret/icsc-paradigms-and-patterns/master) 46 | 47 | You should see something like this: 48 | 49 | ![binder loading](readme_assets/binder_loading.png) 50 | 51 | After some time (don't worry if it takes 5 minutes) you are brought to the Jupyter server: 52 | 53 | ![binder ready](readme_assets/binder_ready.png) 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 ![google colab](readme_assets/colab-button.png)](https://colab.research.google.com/github/klieret/icsc-paradigms-and-patterns/blob/master/exercises/paradigms.ipynb) 64 | * [Software Design Patterns ![google colab](readme_assets/colab-button.png)](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 | [![DOI](https://zenodo.org/badge/240011587.svg)](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", 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 | ![https://creativecommons.org/licenses/by/4.0/](https://i.creativecommons.org/l/by/4.0/88x31.png) ![Approved for Free Cultural Works](https://creativecommons.org/images/deed/seal.png) 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 | * ![CC-BY](https://creativecommons.org/images/deed/by.png) **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 | --------------------------------------------------------------------------------