Deadline+

Deadline+

= Planning
:toc: preamble
:sectanchors:
//works around awesome_bot bug that used to be published at github.com/dkhamsing/awesome_bot/issues/182.
:emptyattribute:

The entry page of the Java course in L3.

== Prerequisites
You know algorithmics and, preferrably, the basic syntax of Java (or a related language). If you have followed an algorithmics course with illustrations and exercices in Java, you satisfy the prerequisites.

== Abbreviations

* [I]: Important
* [O]: Optional (do it if you are specifically interested in the related aspect)
* ESx.y (or ESx.y.z): designates section x.y (or x.y.z) in Eck’s http://math.hws.edu/javanotes/[book] (in chapter x)
* EQx: quiz chapter x
* EQx.y: question number y in Eck’s book, from quiz chapter x
* EEx.y: exercice number y in Eck’s book, from exercices chapter x
* Ranges are always given with ends included (EQ1.3 to 1.9 means 3 and 9 included)
* Markers apply to the whole line. Example: "4.3 intro to 4.3.2, 4.6.1 [I]" means that everything in between 4.3 and 4.3.2 plus 4.6.1 are important.

== General references
* Eck’s http://math.hws.edu/javanotes/[book]
* Stéphane Airiau’s https://www.lamsade.dauphine.fr/~airiau/Teaching/L3-Java/[course] (in French)
* The https://app.gosoapbox.com/event/290081765/[confusion barometer]
* https://pixees.fr/informatiquelycee/[Site] de David Roche

=== Take notes
* 5 ways of taking notes https://www.youtube.com/watch?v=AffuwyJZTQQ[video]
* https://doi.org/10.1177/0956797614524581[Research] shows that taking notes, and especially writing what is said in your own words after some mental processing, permits more effective study

Links taken from the https://www.edx.org/bio/eric-s-lander[course] “Introduction to Biology - The Secret of Life”, MITx
//www.edx.org/course/introduction-to-biology-the-secret-of-life-4, www.edx.org/course?search_query=introduction%20to%20biology%20-%20the%20secret%20of%20life&level=introductory

== Planning

[[S1]]
=== S1 (5 & 6 Feb 2020)

*First half*

* https://github.com/oliviercailloux/java-course/raw/master/Pr%C3%A9sentation%20du%20cours%20Objet/presentation.pdf[Pres course]
* https://github.com/oliviercailloux/java-course/raw/master/Syntaxe/presentation.pdf[Syntax] (without classes and objects) [Should be known or easy]
* *Exercice* with https://docs.oracle.com/en/java/javase/13/docs/specs/man/jshell.html[jshell] (or https://tryjshell.org/[online]):
** Assign 4659 and 23 to variables, and show the result of multiplying these variables
** Show the greatest divisor of 4659 that is different than 4659 (use the `%` operator and a loop)
** Define a method that accepts an integer parameter and returns its greatest divisor except itself; use it to show the greatest divisor of 4659.
** Going beyond: https://arbitrary-but-fixed.net/teaching/java/jshell/2017/12/14/jshell-peculiarities.html[The peculiarities of the JShell]
* Syntax (end): classes (no objects)
** Material: http://math.hws.edu/javanotes/contents-with-subsections.html[ES1.4] (Building blocks of programs), 2 intro (names and things), 2.1 (basic Java application), 2.2 (variables and primitive types), 2.3.3 (operations on strings), 2.4.1 (basic and formatted output), 2.5 (expressions), 2.6.7 (packages), ES3 intro to 3.6 (blocks, loops, algorithmic development, switch) [Should be known or easy]
** http://math.hws.edu/javanotes/c2/[ES2.2.1] (variables), 2.3.1 (subroutines), 2.4.6 (scanner for input) [I]
** ES1.6 (modern UI), 1.7 (internet) [O]
* *Exercice* with a text editor: define a class `MyMathClass` containing the method above and a method that returns the smallest divisor (greater than one) of its parameter; and a class `MyBooleanClass` containing a method `xor` returning `true` iff exactly one of its parameter is `true`. Copy-paste this in jshell and make sure you can call all these methods from jshell. (TODO home)

*Todo*

* Install a https://github.com/oliviercailloux/java-course/blob/master/Best%20practices/Various.adoc#installing-the-jdk[JDK] from OpenJDK (11 or ulterior)
* Install https://www.eclipse.org/downloads/packages/[Eclipse IDE] “for Java Developers”
* Install https://git-scm.com/download[git]
* Redirect your e-mails @ Dauphine if necessary to ensure you receive announcements posted on MyCourse

*Second half*

* https://github.com/oliviercailloux/java-course/raw/master/Ex%C3%A9cution/presentation.pdf[Exécution]
** http://math.hws.edu/javanotes/contents-with-subsections.html[ES1.1] (machine language), 1.2 (Asynchronous events), 1.3 (JVM)
* *Exercices* (TODO home):
** Add a `main` method to your `MyBooleanClass` that prints “Hello, this is my boolean class.” Use `System.out.println("…")` to print.
** Add a `main` method to you `MyMathClass` that accepts two arguments that can each be either `"true"` or `"false"`; the method calls your `xor` method with the corresponding parameters and prints the result.
** Compile `MyBooleanClass` with https://docs.oracle.com/en/java/javase/13/docs/specs/man/javac.html[javac], move the resulting file into its own folder, execute it from the source folder.
** Find out _in the official documentation_ how to compile the class and let the resulting class be placed in its own folder, in a single step (without you having to move the file afterwards)
** Compile `MyMathClass`, move the resulting file into its own folder (alone), and execute it from the source folder. Why does it fail? What does the error message indicate, and how is it related to the problem? Fix the problem and execute it, first by grouping the class files, second, while keeping both class files in different folders.
** (link:http://math.hws.edu/javanotes/c2/exercises.html[EE2.1] to 2.2, supposedly known)
** http://math.hws.edu/javanotes/c1/quiz.html[EQ1.3] to 1.9
** http://math.hws.edu/javanotes/c2/quiz.html[EQ2.1] to 2.4; 2.6 to 2.9; 2.11
* https://github.com/oliviercailloux/java-course/raw/master/Notions%20objets/presentation.pdf[Basics of objects]
** http://math.hws.edu/javanotes/contents-with-subsections.html[ES1.5] (objects), 2.3.2 (classes and objects)
** *http://math.hws.edu/javanotes/c2/exercises.html[EE2.3] to 2.6*; use Scanner, not TextIO
** *http://math.hws.edu/javanotes/c2/exercises.html[EE2.7]*: use user input (Scanner) instead of file input; do not use TextIO
** *http://math.hws.edu/javanotes/c3/exercises.html[EE3.1] to 3.3*
** *EE3.4, 3.6 [I]*
** EE3.8, 3.9 [O]

[[S2]]
=== S2 (28 Feb)

* Supposed known: https://github.com/oliviercailloux/java-course/blob/master/Git/README.adoc[Git]; https://github.com/oliviercailloux/java-course/blob/master/Shell.adoc[Shell]; Execution (see above).
* Reminder: https://github.com/oliviercailloux/java-course/raw/master/Notions%20objets/presentation.pdf[Basics of objects]
** Two roles of classes; static VS instance methods (whose behavior depends on values of parameters and instance attributes)
* Note about packages (for using `Scanner`)
** Class has a short name and a package, hence, a long name. (And two file names!)
* *Exercices* (TODO home):
** http://math.hws.edu/javanotes/c2/exercises.html[EE2.2] to 2.6; use Scanner, not TextIO
** http://math.hws.edu/javanotes/c2/exercises.html[EE2.7]; use user input (Scanner) instead of file input; do not use TextIO
** http://math.hws.edu/javanotes/c3/exercises.html[EE3.1] to 3.3
** EE3.4, 3.6 [I]
* Eclipse & Java:
** Use Outline view
** Use Problems view
** Use Javadoc view
** Content completion with CTRL+Space
** Organize imports: from an editor, select `Source` / `Organize Imports`
** In the http://help.eclipse.org/latest/topic/org.eclipse.jdt.doc.user/gettingStarted/qs-2.htm[Basic tutorial], read: Creating a Java Class; Renaming Java elements; Navigate to a Java element's declaration; Viewing the type Hierarchy; Running your programs
* https://github.com/oliviercailloux/java-course/blob/master/Maven/README.adoc[Maven]: Introduction
** Exercice: *Import a Maven project into Eclipse*

[[S3]]
=== S3 (4 March)

* Graded exercice similar to https://github.com/oliviercailloux/java-course/blob/master/Git/Dep-Git.adoc[Dep-Git] and similar to the exercices related to https://github.com/oliviercailloux/java-course/blob/master/Git/README.adoc[Git] in this course. Your GitHub username and git `user.name` must be identical (and for all exercices to come as well). See https://github.com/oliviercailloux/java-course/blob/master/Git/Git-Br.adoc[Git-Br] (8h32 to 8h52).
* https://github.com/oliviercailloux/java-course/blob/master/Maven/README.adoc[Maven], and *exercices* (TODO home: Modern project)
* Two major principles of software engineering: https://github.com/oliviercailloux/java-course/raw/master/Contrat/presentation.pdf[contract] and fail-fast.
** Mechanisms: interface; black box; preconditions and postconditions; javadoc; exceptions
** http://math.hws.edu/javanotes/contents-with-subsections.html[ES3.7] Exceptions (except 3.7.3)
** ES4 Subroutines, lambdas, packages, javadoc.
** ES4.2.4 Member Variables [I]
** ES4.3 intro to 4.3.2, 4.7.1 Preconditions and Postconditions [I]
** Javadoc: http://www.lamsade.dauphine.fr/~airiau/Teaching/L3-Java/cours3.pdf[Airiau C3], p. 12 to 19.
** http://math.hws.edu/javanotes/c4/quiz.html[EQ4]
** https://github.com/oliviercailloux/java-course/raw/master/Assert/presentation.pdf[assertions] (advanced)
** Illustration: ES4.7.2 A Design Example
* Javadoc in Eclipse: `Source` / `Generate Element Comment` (on methods and classes!), use the `Javadoc` view
* Append `throw IllegalArgumentException` (for example) on your method header when you want to raise attention to it, and document it in Javadoc
* *Exercices:*
** Comment several methods with Javadoc, including the exceptions
** Find out how you can find, when your program crashes because of an exception, the exact place where the exception was raised and which call caused the crash
** http://math.hws.edu/javanotes/c4/exercises.html[EE4.1], 4.2
** EE4.3, 4.4 [I] (TODO home)
** EE4.7

[[S4]]
=== S4 (5 March)

* Graded exercice using your knowledge from Shell; Execution; EE2.x; EE3.x (see above). See https://github.com/oliviercailloux/java-course/blob/master/Exécution/Print%20exec.adoc[Print exec]. (13h47 to 14h47)
* https://github.com/oliviercailloux/java-course/raw/master/Objets/presentation.pdf[Objets]
** http://math.hws.edu/javanotes/c5/[ES5] intro to 5.4
* *Exercices:*
** http://math.hws.edu/javanotes/c5/exercises.html[EE5.1], 5.2
** EE5.3 [I]
// ** Supplementary requirement: you will archive `PairOfDice` and `StatCalc` into a JAR file and use this in a new Eclipse project where only one class is defined, which uses `PairOfDice` and `StatCalc`. Commit both projects into your repository (in two separate folders). The structure of your git repository should be as follows. Please follow the exact naming scheme.
// ** `project43/`… (contains `src` with your source code inside a sub-folder of it)
// ** `project47/`… (contains `src` with your source code inside a sub-folder of it)
// ** `project53utils/`… (contains `utils.jar` and `src/` with `PairOfDice` and `StatCalc` inside a sub-folder of it)
// ** `project53main/`… (contains `src/` with you main method)
//* You may use the `groupId` `io.github.<yourgithubusername>`.
** EE5.4, EE5.5: Play Blackjack!

[[S5]]
=== S5 (18 March)

* Graded programming exercice
* https://github.com/oliviercailloux/java-course/blob/master/JUnit.adoc[Unit testing]
* Inheritance: Object; print an object; more polymorphism.
* Generics and https://www.scientecheasy.com/2018/09/collection-hierarchy-in-java.html[collections].
** For this course, use by default: `ArrayList` / `ImmutableList`; `LinkedHashSet` / `ImmutableSet`; `LinkedHashMap` / `ImmutableMap`.
* Exceptions: checked and unchecked
* https://github.com/oliviercailloux/java-course/blob/master/Search%20path/README.adoc[Search path] (packages, classes and directories).
* Java Interfaces and the Calculator example: replaceability and use as type
//* Exceptions in Java: http://www.lamsade.dauphine.fr/~airiau/Teaching/L3-Java/cours5.pdf[Airiau C5] (and see slides Contrat, appendix)

* https://www.youtube.com/watch?v=lcYkOh4nweE&t=1m21s[Mars Climate Orbiter] (1m21 to 5m18; small mistake in the video: it’s Newton times second, not Newton force per second; see also https://en.wikipedia.org/wiki/Mars_Climate_Orbiter[Wikipedia]; similarly http://www-users.math.umn.edu/~arnold/disasters/ariane.html[sad] https://www.youtube.com/watch?v=gp_D8r-2hwk[story]{emptyattribute})

*Material and going beyond*

* http://math.hws.edu/javanotes8/c5/[ES5.5] to 5.8
* http://math.hws.edu/javanotes8/c10/[ES10] to 10.2
// simple inheritance (no TextIO depended on, actually), but complex set up
* http://math.hws.edu/javanotes8/c5/exercises.html[EE5.4] (use `Scanner` instead of `TextIO`)
//interfaces with generics and collections
* http://math.hws.edu/javanotes8/c10/exercises.html[EE10.4]
// list of words
* http://math.hws.edu/javanotes8/c7/exercises.html[EE7.6] (you may use standard input instead of file input)
// set (long)
* http://math.hws.edu/eck/cs124/javanotes7/c10/exercises.html[EE10.2]

*Exercices*

* Write an interface `Calculator` with a method `add` that takes two integers as parameters. Write a method `tester` in a different class that receives a calculator as a parameter and check that `add(2, 3)` gives 5. Write a `SimpleCalculator` that uses the normal Java addition (“+”) to implement `Calculator`.
//interfaces with generics
* Implement a `Predicate<String>` to represent a function that associates to a String the value `true` iff its length is even.
* Define a class `Pair<T1, T2>` to store an ordered pair of objects of type `T1` and `T2`.
// implements but no inheritance
* http://math.hws.edu/javanotes8/c5/exercises.html[EE5.7] [I] (the part about anonymous classes is optional)
//** Supplementary requirements: your code must lie in at least two packages;
//** The idea of this exercice is that you simulate that three different people work on this exercice: one provides some interfaces; another implements the interfaces; a third one uses the interfaces and their implementations to solve the exercice (except you represent all these persons).
//** Declare at least one interface in another Eclipse project, exported as a Java archive (JAR file);
//** implement those interfaces in another Eclipse project, exported as a Java archive (JAR file) (will you need the previous JAR file? Why / why not?);
//** solve the exercices in a third Eclipse project (will you need the previous JAR files? Which ones and why?).
// read, sort a list
* http://math.hws.edu/javanotes8/c7/exercises.html[EE7.1], 7.5 (except that you can use built-sorting functions from the Java API).
* A class E1 that asks the end-user for a set of integer values. The user enters 0 to stop entering values. Store these values in a Set of Integer values (discarding duplicates). Do it again, obtaining a second set. Then print each set of values entered, then the union of both sets. For example, if the user enters 3, 4, 2, 0, then 1, 1, 2, 5, 0, it prints: 3, 4, 2, then 1, 2, 5, then 3, 4, 2, 1, 5. Use Java sets and interfaces appropriately. [I]

*Todo*

* https://github.com/oliviercailloux/java-course/blob/master/Tools.adoc#configuration[Tools]: use correct Eclipse config. (Check warnings, compile errors, instructions!)
* Commit mandatory exercices https://classroom.github.com/a/X7DXDNfU[here].

[[S6]]
=== S6 (Wednesday 17th of April, 2019)

*Lecture*

* https://github.com/oliviercailloux/java-course/tree/master/Maven[Maven]
* Use https://mvnrepository.com/artifact/com.google.guava/guava/27.1-jre[Guava] `https://github.com/google/guava/wiki/PreconditionsExplained[Preconditions]#checkArgument`
* Overload `toString()`: use Guava https://guava.dev/releases/snapshot/api/docs/com/google/common/base/MoreObjects.ToStringHelper.html[`MoreObjects`]
* null (started)
* Correct E1
.. découpé en sous-routines ?
.. contrat général (Collection au lieu de LinkedList) ?
.. noms complets de classes uniques ?
.. structures appropriées ? (Set)
.. réutilisation si on demande les nombres différemment ? (Lus depuis fichiers)
.. nommage approprié ? (searchNumber renvoie boolean, non, devrait poser une question: isIn)
.. documentation javadoc lorsque nécessaire ?
.. utilisation adéquate des structures ? (ne pas rechercher un nombre dans une liste)
.. conventions respectées ? (noms de variables et méthodes en camelCase, de classes en PascalCase, de packages en minuscules, …)
.. méthodes d’instance (et pas statiques) ?
.. pas de commentaires inutiles (tq auto-générés //TODO, @author vide, …)
.. (micro) pas de comparaison à `true` (`if(isBig == true)`)
.. vous arrivez à voir le résultat de votre code javadoc (exemple: `@param truc of type String` inutile)
* Maps, Comparable, Comparator (voir aussi diapos Airiau)

*Material and going beyond*

* http://math.hws.edu/eck/cs124/javanotes7/c10/[ES10.3] to 10.5
* http://math.hws.edu/eck/cs124/javanotes7/c8/[ES8] intro to 8.4

*Exercices*

* http://math.hws.edu/javanotes8/c10/exercises.html[EE10.1]
//interfaces with generics and collections
* http://math.hws.edu/javanotes8/c10/exercises.html[EE10.4]

[[S7]]
=== S7 (Friday 19th of April, 2019)

* No plagiarism (but reuse!)
* Static factory method
** A static method
** Produces the type of the class it belongs to
** Serves as a factory
** Examples: `String.valueOf(true);`, `Integer.valueOf(3);`, `ImmutableList.of();`, `String.link:https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#format(java.lang.String,java.lang.Object...)[format]("Person name: %s, id: %d", name, id);`
* https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html[Varargs]
* Files and https://github.com/oliviercailloux/java-course/blob/master/Flows.adoc[flows]
* https://github.com/oliviercailloux/java-course/blob/master/Best%20practices/Resources.adoc[Resources]; exercice: read a file from the class path.
* Primitive types (autoboxing); optional; give guarantees: https://github.com/oliviercailloux/java-course/blob/master/Best%20practices/Null.adoc[Best practices]

*Exercices*

* Implement an interface `EasyMap` with two methods: a method that puts a pair of key and value of your choice into a map, and a method that returns an `Optional` containing the value corresponding to the given key (parameter of the method) or that returns an empty `Optional` if there is no such value. Implement this interface in a class `EasyMapImpl`. Provide a static factory method in the interface `EasyMap`. Minimize the number of lines of code (but not at the price of readability). Note that this exercice implements the https://en.wikipedia.org/wiki/Forwarding_(object-oriented_programming)[forwarding] pattern.
** Define `MyComparator`, a class that implements a comparator over your values. Add a third method to `EasyMap`, that returns a list of values ordered by that comparator.
// list of words
* http://math.hws.edu/javanotes8/c7/exercises.html[EE7.6] (do not use the provided method: split words at space character; use standard file IO instead of TextIO)

*Todo*

* Read https://github.com/oliviercailloux/java-course/blob/master/Tools.adoc#eclipse[Eclipse] doc (or equivalent for your IDE of choice)
* Make sure you can see the javadoc of the JDK and of the libraries you add through Maven through your IDE, for coding efficiently
* If you use an IDE different than Eclipse, you are supposed to adjust your parameters to match the configuration provided for Eclipse (see Tools.adoc).

[[S8]]
=== S8 (Monday 6th of May, 2019)

* Questions?
* Graded https://github.com/oliviercailloux/java-course/blob/master/Divers/Extractor.adoc[exercice]
** Submitted code must be clean: well-formatted, clear, well named, …
** Must compile using Maven (otherwise, no point awarded)
** No warning given by Eclipse
** 15h44 to 16h24
* Choose your https://github.com/oliviercailloux/java-course/blob/master/Divers/Projets.adoc[project]
* Comparing Persons, revisited, using https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html[Lambda Expressions]
* Override `equals` and `hashcode`

[[S9]]
=== S9 (Friday 10th of May, 2019)

* Tentative coefficients: graded quizz: 0.5, Extractor: 0.5, next graded exercices: 1, last graded exercice: 2
* https://github.com/oliviercailloux/java-course/blob/master/DevOps/CI.adoc[CI]: Travis
* TODO : livraison 1 avant fin de la veille de S10.

[[S10]]
=== S10 (Monday 20th of May, 2019)

* Graded https://github.com/oliviercailloux/java-course/blob/master/Divers/Dep-Git.adoc[exercice] (about Maven dependencies and Git)
* https://stackoverflow.com/questions/28972893/what-is-exception-wrapping-in-java[Wrapping] exceptions
* https://github.com/oliviercailloux/java-course/blob/master/Log/README.adoc[Logging]
* https://github.com/oliviercailloux/java-course/raw/master/Annotations/presentation.pdf[Annotations]

[[S11]]
=== S11 (Thursday 23rd of May, 2019)

* https://github.com/oliviercailloux/java-course/tree/master/SWT[SWT]

[[S12]]
=== S12 (Friday 24th of May, 2019)

* Back to https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html[Method references]
* TODO : livraison suivante avant fin de la veille de la prochaine séance.

[[S13]]
=== S13 (Tuesday 4th of June, 2019)

* Graded https://github.com/oliviercailloux/java-course/blob/master/Divers/JUnit.adoc[exercice]: unit tests / access resources through class path / continue Extractor.
** 17h17 to 17h42 (5 min for delays due to GitHub)

* Write the list of PRs for Iteration 2 for each sub-team in `README.adoc` in your `dev` branch.

[[S14]]
=== S14 (Wednesday 5th of June, 2019)

* Licenses and philosophy: https://www.gnu.org/philosophy/philosophy.html[GNU]; https://opensource.org/[OSI]; Copyleft (GNU https://opensource.org/licenses/GPL-3.0[GPL]); Non-copyleft (https://opensource.org/licenses/MIT[MIT])
* Parsing HTML: https://github.com/oliviercailloux/java-course/blob/master/HTML%20to%20DOM.adoc[DOM]
* Accessing REST web services: https://github.com/oliviercailloux/java-course/blob/master/WS%20client/JAX-RS%20client.adoc[JAX-RS client]

[[S15]]
=== S15 (Monday 17th of June, 2019)

* Work on project
* TODO : livraison 3 avant fin du jeudi 20, avec PRs affectées à une Milestone « Itération 3 » (merci à l’équipe Assisted Board Games pour cette astuce).

[[S16]]
=== S16 (Friday 21st of June, 2019)

* Work on project
* TODO : livraison 4 avant fin du vendredi 28, avec PRs affectées à une Milestone « Itération 4 ».
** Facultatif : une tâche qui ajoute dans votre README des éléments que vous désirez que je prenne en compte dans mon évaluation globale (difficultés rencontrées, travaux que j’aurais oublié d’évaluer lors d’une itération précédente, …). Complémentez vos propos d’éléments vérifiables (commits, documents, …).
** Remise autorisée jusqu’à la fin du samedi 29 si nécessaire, mais une prime sera accordée pour une remise le vendredi soir.
* Présentation avant fin du dimanche 30 directement sur branche master, dans `Doc/Présentation 2019.pdf`.

[[S17]]
=== S17 (Monday 1st of July, 2019)

* Présentations :
https://github.com/13tomoore/J-Confs/raw/master/Doc/Pr%C3%A9sentation%202019.pdf[J-Confs],
https://github.com/Amioplk/Apartments/raw/master/Doc/Pr%C3%A9sentation%202019.pdf[Apartments],
https://github.com/CHARLONCyril/2D-Library/raw/master/Doc/Pr%C3%A9sentation%202019.pdf[2D Library],
https://github.com/busychess/Assisted-Board-Games/raw/master/Doc/Pr%C3%A9sentation%202019.pdf[Assisted Board Games],
https://github.com/j-voting/J-Voting/raw/master/Doc/Pr%C3%A9sentation%202019.pdf[J-Voting]
** Code & diapos sur ordinateur de présentation
** 15 à 30 minutes
** Noté : intérêt pour l’audience ; compréhension par l’audience du contexte et de l’objectif du projet ; compréhension par l’audience de l’architecture du code et des aspects techniques ; distinction claire des fcts déjà présentes VS ajoutées ; originalité & créativité éventuelle ; …
* Votes
* Evals, and https://github.com/oliviercailloux/projets/blob/master/Licences/Licence.adoc[Licences]: https://github.com/oliviercailloux/projets/raw/master/Licences/Declaration%20of%20licensing.odt[Decl]

= Planning
:toc: preamble
:sectanchors:
//works around awesome_bot bug that used to be published at github.com/dkhamsing/awesome_bot/issues/182.
:emptyattribute:

The entry page of the Java course in L3.

== Prerequisites
You know algorithmics and, preferrably, the basic syntax of Java (or a related language). If you have followed an algorithmics course with illustrations and exercices in Java, you satisfy the prerequisites.

== Abbreviations

* [I]: Important
* [O]: Optional (do it if you are specifically interested in the related aspect)
* ESx.y (or ESx.y.z): designates section x.y (or x.y.z) in Eck’s http://math.hws.edu/javanotes/[book] (in chapter x)
* EQx: quiz chapter x
* EQx.y: question number y in Eck’s book, from quiz chapter x
* EEx.y: exercice number y in Eck’s book, from exercices chapter x
* Ranges are always given with ends included (EQ1.3 to 1.9 means 3 and 9 included)
* Markers apply to the whole line. Example: "4.3 intro to 4.3.2, 4.6.1 [I]" means that everything in between 4.3 and 4.3.2 plus 4.6.1 are important.

== General references
* Eck’s http://math.hws.edu/javanotes/[book]
* Stéphane Airiau’s https://www.lamsade.dauphine.fr/~airiau/Teaching/L3-Java/[course] (in French)
* The https://app.gosoapbox.com/event/290081765/[confusion barometer]
* https://pixees.fr/informatiquelycee/[Site] de David Roche

=== Take notes
* 5 ways of taking notes https://www.youtube.com/watch?v=AffuwyJZTQQ[video]
* https://doi.org/10.1177/0956797614524581[Research] shows that taking notes, and especially writing what is said in your own words after some mental processing, permits more effective study

Links taken from the https://www.edx.org/bio/eric-s-lander[course] “Introduction to Biology - The Secret of Life”, MITx
//www.edx.org/course/introduction-to-biology-the-secret-of-life-4, www.edx.org/course?search_query=introduction%20to%20biology%20-%20the%20secret%20of%20life&level=introductory

== Planning

[[S1]]
=== S1 (5 & 6 Feb 2020)

*First half*

* https://github.com/oliviercailloux/java-course/raw/master/Pr%C3%A9sentation%20du%20cours%20Objet/presentation.pdf[Pres course]
* https://github.com/oliviercailloux/java-course/raw/master/Syntaxe/presentation.pdf[Syntax] (without classes and objects) [Should be known or easy]
* *Exercice* with https://docs.oracle.com/en/java/javase/13/docs/specs/man/jshell.html[jshell] (or https://tryjshell.org/[online]):
** Assign 4659 and 23 to variables, and show the result of multiplying these variables
** Show the greatest divisor of 4659 that is different than 4659 (use the `%` operator and a loop)
** Define a method that accepts an integer parameter and returns its greatest divisor except itself; use it to show the greatest divisor of 4659.
** Going beyond: https://arbitrary-but-fixed.net/teaching/java/jshell/2017/12/14/jshell-peculiarities.html[The peculiarities of the JShell]
* Syntax (end): classes (no objects)
** Material: http://math.hws.edu/javanotes/contents-with-subsections.html[ES1.4] (Building blocks of programs), 2 intro (names and things), 2.1 (basic Java application), 2.2 (variables and primitive types), 2.3.3 (operations on strings), 2.4.1 (basic and formatted output), 2.5 (expressions), 2.6.7 (packages), ES3 intro to 3.6 (blocks, loops, algorithmic development, switch) [Should be known or easy]
** http://math.hws.edu/javanotes/c2/[ES2.2.1] (variables), 2.3.1 (subroutines), 2.4.6 (scanner for input) [I]
** ES1.6 (modern UI), 1.7 (internet) [O]
* *Exercice* with a text editor: define a class `MyMathClass` containing the method above and a method that returns the smallest divisor (greater than one) of its parameter; and a class `MyBooleanClass` containing a method `xor` returning `true` iff exactly one of its parameter is `true`. Copy-paste this in jshell and make sure you can call all these methods from jshell. (TODO home)

*Todo*

* Install a https://github.com/oliviercailloux/java-course/blob/master/Best%20practices/Various.adoc#installing-the-jdk[JDK] from OpenJDK (11 or ulterior)
* Install https://www.eclipse.org/downloads/packages/[Eclipse IDE] “for Java Developers”
* Install https://git-scm.com/download[git]
* Redirect your e-mails @ Dauphine if necessary to ensure you receive announcements posted on MyCourse

*Second half*

* https://github.com/oliviercailloux/java-course/raw/master/Ex%C3%A9cution/presentation.pdf[Exécution]
** http://math.hws.edu/javanotes/contents-with-subsections.html[ES1.1] (machine language), 1.2 (Asynchronous events), 1.3 (JVM)
* *Exercices* (TODO home):
** Add a `main` method to your `MyBooleanClass` that prints “Hello, this is my boolean class.” Use `System.out.println("…")` to print.
** Add a `main` method to you `MyMathClass` that accepts two arguments that can each be either `"true"` or `"false"`; the method calls your `xor` method with the corresponding parameters and prints the result.
** Compile `MyBooleanClass` with https://docs.oracle.com/en/java/javase/13/docs/specs/man/javac.html[javac], move the resulting file into its own folder, execute it from the source folder.
** Find out _in the official documentation_ how to compile the class and let the resulting class be placed in its own folder, in a single step (without you having to move the file afterwards)
** Compile `MyMathClass`, move the resulting file into its own folder (alone), and execute it from the source folder. Why does it fail? What does the error message indicate, and how is it related to the problem? Fix the problem and execute it, first by grouping the class files, second, while keeping both class files in different folders.
** (link:http://math.hws.edu/javanotes/c2/exercises.html[EE2.1] to 2.2, supposedly known)
** http://math.hws.edu/javanotes/c1/quiz.html[EQ1.3] to 1.9
** http://math.hws.edu/javanotes/c2/quiz.html[EQ2.1] to 2.4; 2.6 to 2.9; 2.11
* https://github.com/oliviercailloux/java-course/raw/master/Notions%20objets/presentation.pdf[Basics of objects]
** http://math.hws.edu/javanotes/contents-with-subsections.html[ES1.5] (objects), 2.3.2 (classes and objects)
** *http://math.hws.edu/javanotes/c2/exercises.html[EE2.3] to 2.6*; use Scanner, not TextIO
** *http://math.hws.edu/javanotes/c2/exercises.html[EE2.7]*: use user input (Scanner) instead of file input; do not use TextIO
** *http://math.hws.edu/javanotes/c3/exercises.html[EE3.1] to 3.3*
** *EE3.4, 3.6 [I]*
** EE3.8, 3.9 [O]

[[S2]]
=== S2 (28 Feb)

* Supposed known: https://github.com/oliviercailloux/java-course/blob/master/Git/README.adoc[Git]; https://github.com/oliviercailloux/java-course/blob/master/Shell.adoc[Shell]; Execution (see above).
* Reminder: https://github.com/oliviercailloux/java-course/raw/master/Notions%20objets/presentation.pdf[Basics of objects]
** Two roles of classes; static VS instance methods (whose behavior depends on values of parameters and instance attributes)
* Note about packages (for using `Scanner`)
** Class has a short name and a package, hence, a long name. (And two file names!)
* *Exercices* (TODO home):
** http://math.hws.edu/javanotes/c2/exercises.html[EE2.2] to 2.6; use Scanner, not TextIO
** http://math.hws.edu/javanotes/c2/exercises.html[EE2.7]; use user input (Scanner) instead of file input; do not use TextIO
** http://math.hws.edu/javanotes/c3/exercises.html[EE3.1] to 3.3
** EE3.4, 3.6 [I]
* Eclipse & Java:
** Use Outline view
** Use Problems view
** Use Javadoc view
** Content completion with CTRL+Space
** Organize imports: from an editor, select `Source` / `Organize Imports`
** In the http://help.eclipse.org/latest/topic/org.eclipse.jdt.doc.user/gettingStarted/qs-2.htm[Basic tutorial], read: Creating a Java Class; Renaming Java elements; Navigate to a Java element's declaration; Viewing the type Hierarchy; Running your programs
* https://github.com/oliviercailloux/java-course/blob/master/Maven/README.adoc[Maven]: Introduction
** Exercice: *Import a Maven project into Eclipse*

[[S3]]
=== S3 (4 March)

* Graded exercice similar to https://github.com/oliviercailloux/java-course/blob/master/Git/Dep-Git.adoc[Dep-Git] and similar to the exercices related to https://github.com/oliviercailloux/java-course/blob/master/Git/README.adoc[Git] in this course. Your GitHub username and git `user.name` must be identical (and for all exercices to come as well). See https://github.com/oliviercailloux/java-course/blob/master/Git/Git-Br.adoc[Git-Br] (8h32 to 8h52).
* https://github.com/oliviercailloux/java-course/blob/master/Maven/README.adoc[Maven], and *exercices* (TODO home: Modern project)
* Two major principles of software engineering: https://github.com/oliviercailloux/java-course/raw/master/Contrat/presentation.pdf[contract] and fail-fast.
** Mechanisms: interface; black box; preconditions and postconditions; javadoc; exceptions
** http://math.hws.edu/javanotes/contents-with-subsections.html[ES3.7] Exceptions (except 3.7.3)
** ES4 Subroutines, lambdas, packages, javadoc.
** ES4.2.4 Member Variables [I]
** ES4.3 intro to 4.3.2, 4.7.1 Preconditions and Postconditions [I]
** Javadoc: http://www.lamsade.dauphine.fr/~airiau/Teaching/L3-Java/cours3.pdf[Airiau C3], p. 12 to 19.
** http://math.hws.edu/javanotes/c4/quiz.html[EQ4]
** https://github.com/oliviercailloux/java-course/raw/master/Assert/presentation.pdf[assertions] (advanced)
** Illustration: ES4.7.2 A Design Example
* Javadoc in Eclipse: `Source` / `Generate Element Comment` (on methods and classes!), use the `Javadoc` view
* Append `throw IllegalArgumentException` (for example) on your method header when you want to raise attention to it, and document it in Javadoc
* *Exercices:*
** Comment several methods with Javadoc, including the exceptions
** Find out how you can find, when your program crashes because of an exception, the exact place where the exception was raised and which call caused the crash
** http://math.hws.edu/javanotes/c4/exercises.html[EE4.1], 4.2
** EE4.3, 4.4 [I] (TODO home)
** EE4.7

[[S4]]
=== S4 (5 March)

* Graded exercice using your knowledge from Shell; Execution; EE2.x; EE3.x (see above). See https://github.com/oliviercailloux/java-course/blob/master/Exécution/Print%20exec.adoc[Print exec]. (13h45 to 14h45)
* https://github.com/oliviercailloux/java-course/raw/master/Objets/presentation.pdf[Objets]
** http://math.hws.edu/javanotes/c5/[ES5] intro to 5.4
* *Exercices:*
** http://math.hws.edu/javanotes/c5/exercises.html[EE5.1], 5.2
** EE5.3 [I]
// ** Supplementary requirement: you will archive `PairOfDice` and `StatCalc` into a JAR file and use this in a new Eclipse project where only one class is defined, which uses `PairOfDice` and `StatCalc`. Commit both projects into your repository (in two separate folders). The structure of your git repository should be as follows. Please follow the exact naming scheme.
// ** `project43/`… (contains `src` with your source code inside a sub-folder of it)
// ** `project47/`… (contains `src` with your source code inside a sub-folder of it)
// ** `project53utils/`… (contains `utils.jar` and `src/` with `PairOfDice` and `StatCalc` inside a sub-folder of it)
// ** `project53main/`… (contains `src/` with you main method)
//* You may use the `groupId` `io.github.<yourgithubusername>`.
** EE5.4, EE5.5: Play Blackjack!

[[S5]]
=== S5 (18 March)

* Graded programming exercice
* https://github.com/oliviercailloux/java-course/blob/master/JUnit.adoc[Unit testing]
* Inheritance: Object; print an object; more polymorphism.
* Generics and https://www.scientecheasy.com/2018/09/collection-hierarchy-in-java.html[collections].
** For this course, use by default: `ArrayList` / `ImmutableList`; `LinkedHashSet` / `ImmutableSet`; `LinkedHashMap` / `ImmutableMap`.
* Exceptions: checked and unchecked
* https://github.com/oliviercailloux/java-course/blob/master/Search%20path/README.adoc[Search path] (packages, classes and directories).
* Java Interfaces and the Calculator example: replaceability and use as type
//* Exceptions in Java: http://www.lamsade.dauphine.fr/~airiau/Teaching/L3-Java/cours5.pdf[Airiau C5] (and see slides Contrat, appendix)

* https://www.youtube.com/watch?v=lcYkOh4nweE&t=1m21s[Mars Climate Orbiter] (1m21 to 5m18; small mistake in the video: it’s Newton times second, not Newton force per second; see also https://en.wikipedia.org/wiki/Mars_Climate_Orbiter[Wikipedia]; similarly http://www-users.math.umn.edu/~arnold/disasters/ariane.html[sad] https://www.youtube.com/watch?v=gp_D8r-2hwk[story]{emptyattribute})

*Material and going beyond*

* http://math.hws.edu/javanotes8/c5/[ES5.5] to 5.8
* http://math.hws.edu/javanotes8/c10/[ES10] to 10.2
// simple inheritance (no TextIO depended on, actually), but complex set up
* http://math.hws.edu/javanotes8/c5/exercises.html[EE5.4] (use `Scanner` instead of `TextIO`)
//interfaces with generics and collections
* http://math.hws.edu/javanotes8/c10/exercises.html[EE10.4]
// list of words
* http://math.hws.edu/javanotes8/c7/exercises.html[EE7.6] (you may use standard input instead of file input)
// set (long)
* http://math.hws.edu/eck/cs124/javanotes7/c10/exercises.html[EE10.2]

*Exercices*

* Write an interface `Calculator` with a method `add` that takes two integers as parameters. Write a method `tester` in a different class that receives a calculator as a parameter and check that `add(2, 3)` gives 5. Write a `SimpleCalculator` that uses the normal Java addition (“+”) to implement `Calculator`.
//interfaces with generics
* Implement a `Predicate<String>` to represent a function that associates to a String the value `true` iff its length is even.
* Define a class `Pair<T1, T2>` to store an ordered pair of objects of type `T1` and `T2`.
// implements but no inheritance
* http://math.hws.edu/javanotes8/c5/exercises.html[EE5.7] [I] (the part about anonymous classes is optional)
//** Supplementary requirements: your code must lie in at least two packages;
//** The idea of this exercice is that you simulate that three different people work on this exercice: one provides some interfaces; another implements the interfaces; a third one uses the interfaces and their implementations to solve the exercice (except you represent all these persons).
//** Declare at least one interface in another Eclipse project, exported as a Java archive (JAR file);
//** implement those interfaces in another Eclipse project, exported as a Java archive (JAR file) (will you need the previous JAR file? Why / why not?);
//** solve the exercices in a third Eclipse project (will you need the previous JAR files? Which ones and why?).
// read, sort a list
* http://math.hws.edu/javanotes8/c7/exercises.html[EE7.1], 7.5 (except that you can use built-sorting functions from the Java API).
* A class E1 that asks the end-user for a set of integer values. The user enters 0 to stop entering values. Store these values in a Set of Integer values (discarding duplicates). Do it again, obtaining a second set. Then print each set of values entered, then the union of both sets. For example, if the user enters 3, 4, 2, 0, then 1, 1, 2, 5, 0, it prints: 3, 4, 2, then 1, 2, 5, then 3, 4, 2, 1, 5. Use Java sets and interfaces appropriately. [I]

*Todo*

* https://github.com/oliviercailloux/java-course/blob/master/Tools.adoc#configuration[Tools]: use correct Eclipse config. (Check warnings, compile errors, instructions!)
* Commit mandatory exercices https://classroom.github.com/a/X7DXDNfU[here].

[[S6]]
=== S6 (Wednesday 17th of April, 2019)

*Lecture*

* https://github.com/oliviercailloux/java-course/tree/master/Maven[Maven]
* Use https://mvnrepository.com/artifact/com.google.guava/guava/27.1-jre[Guava] `https://github.com/google/guava/wiki/PreconditionsExplained[Preconditions]#checkArgument`
* Overload `toString()`: use Guava https://guava.dev/releases/snapshot/api/docs/com/google/common/base/MoreObjects.ToStringHelper.html[`MoreObjects`]
* null (started)
* Correct E1
.. découpé en sous-routines ?
.. contrat général (Collection au lieu de LinkedList) ?
.. noms complets de classes uniques ?
.. structures appropriées ? (Set)
.. réutilisation si on demande les nombres différemment ? (Lus depuis fichiers)
.. nommage approprié ? (searchNumber renvoie boolean, non, devrait poser une question: isIn)
.. documentation javadoc lorsque nécessaire ?
.. utilisation adéquate des structures ? (ne pas rechercher un nombre dans une liste)
.. conventions respectées ? (noms de variables et méthodes en camelCase, de classes en PascalCase, de packages en minuscules, …)
.. méthodes d’instance (et pas statiques) ?
.. pas de commentaires inutiles (tq auto-générés //TODO, @author vide, …)
.. (micro) pas de comparaison à `true` (`if(isBig == true)`)
.. vous arrivez à voir le résultat de votre code javadoc (exemple: `@param truc of type String` inutile)
* Maps, Comparable, Comparator (voir aussi diapos Airiau)

*Material and going beyond*

* http://math.hws.edu/eck/cs124/javanotes7/c10/[ES10.3] to 10.5
* http://math.hws.edu/eck/cs124/javanotes7/c8/[ES8] intro to 8.4

*Exercices*

* http://math.hws.edu/javanotes8/c10/exercises.html[EE10.1]
//interfaces with generics and collections
* http://math.hws.edu/javanotes8/c10/exercises.html[EE10.4]

[[S7]]
=== S7 (Friday 19th of April, 2019)

* No plagiarism (but reuse!)
* Static factory method
** A static method
** Produces the type of the class it belongs to
** Serves as a factory
** Examples: `String.valueOf(true);`, `Integer.valueOf(3);`, `ImmutableList.of();`, `String.link:https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#format(java.lang.String,java.lang.Object...)[format]("Person name: %s, id: %d", name, id);`
* https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html[Varargs]
* Files and https://github.com/oliviercailloux/java-course/blob/master/Flows.adoc[flows]
* https://github.com/oliviercailloux/java-course/blob/master/Best%20practices/Resources.adoc[Resources]; exercice: read a file from the class path.
* Primitive types (autoboxing); optional; give guarantees: https://github.com/oliviercailloux/java-course/blob/master/Best%20practices/Null.adoc[Best practices]

*Exercices*

* Implement an interface `EasyMap` with two methods: a method that puts a pair of key and value of your choice into a map, and a method that returns an `Optional` containing the value corresponding to the given key (parameter of the method) or that returns an empty `Optional` if there is no such value. Implement this interface in a class `EasyMapImpl`. Provide a static factory method in the interface `EasyMap`. Minimize the number of lines of code (but not at the price of readability). Note that this exercice implements the https://en.wikipedia.org/wiki/Forwarding_(object-oriented_programming)[forwarding] pattern.
** Define `MyComparator`, a class that implements a comparator over your values. Add a third method to `EasyMap`, that returns a list of values ordered by that comparator.
// list of words
* http://math.hws.edu/javanotes8/c7/exercises.html[EE7.6] (do not use the provided method: split words at space character; use standard file IO instead of TextIO)

*Todo*

* Read https://github.com/oliviercailloux/java-course/blob/master/Tools.adoc#eclipse[Eclipse] doc (or equivalent for your IDE of choice)
* Make sure you can see the javadoc of the JDK and of the libraries you add through Maven through your IDE, for coding efficiently
* If you use an IDE different than Eclipse, you are supposed to adjust your parameters to match the configuration provided for Eclipse (see Tools.adoc).

[[S8]]
=== S8 (Monday 6th of May, 2019)

* Questions?
* Graded https://github.com/oliviercailloux/java-course/blob/master/Divers/Extractor.adoc[exercice]
** Submitted code must be clean: well-formatted, clear, well named, …
** Must compile using Maven (otherwise, no point awarded)
** No warning given by Eclipse
** 15h44 to 16h24
* Choose your https://github.com/oliviercailloux/java-course/blob/master/Divers/Projets.adoc[project]
* Comparing Persons, revisited, using https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html[Lambda Expressions]
* Override `equals` and `hashcode`

[[S9]]
=== S9 (Friday 10th of May, 2019)

* Tentative coefficients: graded quizz: 0.5, Extractor: 0.5, next graded exercices: 1, last graded exercice: 2
* https://github.com/oliviercailloux/java-course/blob/master/DevOps/CI.adoc[CI]: Travis
* TODO : livraison 1 avant fin de la veille de S10.

[[S10]]
=== S10 (Monday 20th of May, 2019)

* Graded https://github.com/oliviercailloux/java-course/blob/master/Divers/Dep-Git.adoc[exercice] (about Maven dependencies and Git)
* https://stackoverflow.com/questions/28972893/what-is-exception-wrapping-in-java[Wrapping] exceptions
* https://github.com/oliviercailloux/java-course/blob/master/Log/README.adoc[Logging]
* https://github.com/oliviercailloux/java-course/raw/master/Annotations/presentation.pdf[Annotations]

[[S11]]
=== S11 (Thursday 23rd of May, 2019)

* https://github.com/oliviercailloux/java-course/tree/master/SWT[SWT]

[[S12]]
=== S12 (Friday 24th of May, 2019)

* Back to https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html[Method references]
* TODO : livraison suivante avant fin de la veille de la prochaine séance.

[[S13]]
=== S13 (Tuesday 4th of June, 2019)

* Graded https://github.com/oliviercailloux/java-course/blob/master/Divers/JUnit.adoc[exercice]: unit tests / access resources through class path / continue Extractor.
** 17h17 to 17h42 (5 min for delays due to GitHub)

* Write the list of PRs for Iteration 2 for each sub-team in `README.adoc` in your `dev` branch.

[[S14]]
=== S14 (Wednesday 5th of June, 2019)

* Licenses and philosophy: https://www.gnu.org/philosophy/philosophy.html[GNU]; https://opensource.org/[OSI]; Copyleft (GNU https://opensource.org/licenses/GPL-3.0[GPL]); Non-copyleft (https://opensource.org/licenses/MIT[MIT])
* Parsing HTML: https://github.com/oliviercailloux/java-course/blob/master/HTML%20to%20DOM.adoc[DOM]
* Accessing REST web services: https://github.com/oliviercailloux/java-course/blob/master/WS%20client/JAX-RS%20client.adoc[JAX-RS client]

[[S15]]
=== S15 (Monday 17th of June, 2019)

* Work on project
* TODO : livraison 3 avant fin du jeudi 20, avec PRs affectées à une Milestone « Itération 3 » (merci à l’équipe Assisted Board Games pour cette astuce).

[[S16]]
=== S16 (Friday 21st of June, 2019)

* Work on project
* TODO : livraison 4 avant fin du vendredi 28, avec PRs affectées à une Milestone « Itération 4 ».
** Facultatif : une tâche qui ajoute dans votre README des éléments que vous désirez que je prenne en compte dans mon évaluation globale (difficultés rencontrées, travaux que j’aurais oublié d’évaluer lors d’une itération précédente, …). Complémentez vos propos d’éléments vérifiables (commits, documents, …).
** Remise autorisée jusqu’à la fin du samedi 29 si nécessaire, mais une prime sera accordée pour une remise le vendredi soir.
* Présentation avant fin du dimanche 30 directement sur branche master, dans `Doc/Présentation 2019.pdf`.

[[S17]]
=== S17 (Monday 1st of July, 2019)

* Présentations :
https://github.com/13tomoore/J-Confs/raw/master/Doc/Pr%C3%A9sentation%202019.pdf[J-Confs],
https://github.com/Amioplk/Apartments/raw/master/Doc/Pr%C3%A9sentation%202019.pdf[Apartments],
https://github.com/CHARLONCyril/2D-Library/raw/master/Doc/Pr%C3%A9sentation%202019.pdf[2D Library],
https://github.com/busychess/Assisted-Board-Games/raw/master/Doc/Pr%C3%A9sentation%202019.pdf[Assisted Board Games],
https://github.com/j-voting/J-Voting/raw/master/Doc/Pr%C3%A9sentation%202019.pdf[J-Voting]
** Code & diapos sur ordinateur de présentation
** 15 à 30 minutes
** Noté : intérêt pour l’audience ; compréhension par l’audience du contexte et de l’objectif du projet ; compréhension par l’audience de l’architecture du code et des aspects techniques ; distinction claire des fcts déjà présentes VS ajoutées ; originalité & créativité éventuelle ; …
* Votes
* Evals, and https://github.com/oliviercailloux/projets/blob/master/Licences/Licence.adoc[Licences]: https://github.com/oliviercailloux/projets/raw/master/Licences/Declaration%20of%20licensing.odt[Decl]


Fix 'supplemental' typo

Fix 'supplemental' typo

= Persistent Storage Using NFS
{product-author}
{product-version}
:data-uri:
:icons:
:experimental:
:toc: macro
:toc-title:
:prewrap!:

toc::[]

== Overview

OpenShift clusters can be provisioned with
link:../../architecture/additional_concepts/storage.html[persistent storage]
using NFS. Persistent volumes (PVs) and persistent volume claims (PVCs) provide
a convenient method for sharing a volume across a project. While the
NFS-specific information contained in a PV definition could also be defined
directly in a pod definition, doing so does not create the volume as a distinct
cluster resource, making the volume more susceptible to conflicts.

This topic covers the specifics of using the NFS persistent storage type. Some
familiarity with OpenShift and
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Storage_Administration_Guide/ch-nfs.html[NFS]
is beneficial. See the
link:../../architecture/additional_concepts/storage.html[Persistent Storage]
concept topic for details on the OpenShift persistent volume (PV) framework in
general.

[[nfs-provisioning]]
== Provisioning

Storage must exist in the underlying infrastructure before it can be mounted as
a volume in OpenShift. To provision NFS volumes, a list of NFS servers and
export paths are all that is required.

You must first create an object definition for the PV:

.PV Object Definition Using NFS
====
[source,yaml]
----
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0001 <1>
spec:
  capacity:
    storage: 5Gi <2>
  accessModes:
  - ReadWriteOnce <3>
  nfs: <4>
    path: /tmp <5>
    server: 172.17.0.2 <6>
  persistentVolumeReclaimPolicy: Recycle <7>
----
<1> The name of the volume. This is the PV identity in various `oc <command>
pod` commands.
<2> The amount of storage allocated to this volume.
<3> Though this appears to be related to controlling access to the volume, it is
actually used similarly to labels and used to match a PVC to a PV. Currently, no
access rules are enforced based on the `*accessModes*`.
<4> The volume type being used, in this case the *nfs* plug-in.
<5> The path that is exported by the NFS server.
<6> The host name or IP address of the NFS server.
<7> The reclaim policy for the PV. This defines what happens to a volume when released
from its claim. Valid options are *Retain* (default) and *Recycle*. See
link:#nfs-reclaiming-resources[Reclaiming Resources].
====

[NOTE]
====
Each NFS volume must be mountable by all schedulable nodes in the cluster.
====

Save the definition to a file, for example *_nfs-pv.yaml_*, and create the PV:

====
----
$ oc create -f nfs-pv.yaml
persistentvolume "pv0001" created
----
====

Verify that the PV was created:

====
----
# oc get pv
NAME                     LABELS    CAPACITY     ACCESSMODES   STATUS      CLAIM     REASON    AGE
pv0001                   <none>    5368709120   RWO           Available                       31s
----
====

The next step can be to create a persistent volume claim (PVC) which will bind
to the new PV:

.PVC Object Definition
====
[source,yaml]
----
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-claim1
spec:
  accessModes:
    - ReadWriteOnce <1>
  resources:
    requests:
      storage: 1Gi <2>
----
<1> As mentioned above for PVs, the `*accessModes*` do not enforce security, but
rather act as labels to match a PV to a PVC.
<2> This claim will look for PVs offering *1Gi* or greater capacity.
====

Save the definition to a file, for example *_nfs-claim.yaml_*, and create the
PVC:

====
----
# oc create -f nfs-claim.yaml
----
====

[[nfs-enforcing-disk-quotas]]
== Enforcing Disk Quotas

You can uses disk partitions to enforce disk quotas and size constraints. Each
partition can be its own export. Each export is one PV. OpenShift enforces
unique names for PVs, but the uniqueness of the NFS volume's server and path is
up to the administrator.

Enforcing quotas in this way allows the developer to request persistent storage
by a specific amount (for example, 10Gi) and be matched with a corresponding
volume of equal or greater capacity.

[[nfs-volume-security]]
== Volume Security

This section covers NFS volume security, including matching permissions and
SELinux considerations. The reader is expected to understand the basics of POSIX
permissions, process UIDs, supplemental groups, and SELinux.

[NOTE]
====
See the full
link:../../install_config/persistent_storage/pod_security_context.html[Volume
Security] topic before implementing NFS volumes.
====

Developers request NFS storage by referencing, in the `*volumes*` section of
their pod definition, either a PVC by name or the NFS volume plug-in directly.

The *_/etc/exports_* file on the NFS server contains the accessible NFS
directories. The target NFS directory has POSIX owner and group IDs. The
OpenShift NFS plug-in mounts the container's NFS directory with the same POSIX
ownership and permissions found on the exported NFS directory. However, the
container is not run with its effective UID equal to the owner of the NFS mount,
which is the desired behavior.

As an example, if the target NFS directory appears on the NFS server as:

[[nfs-export]]
====
----
# ls -lZ /opt/nfs -d
drwxrws---. nfsnobody 5555 unconfined_u:object_r:usr_t:s0   /opt/nfs

# id nfsnobody
uid=65534(nfsnobody) gid=65534(nfsnobody) groups=65534(nfsnobody)
----
====

Then the container must match SELinux labels, and either run with a UID of
*65534* (*nfsnobody* owner) or with *5555* in its supplemental groups in order
to access the directory.

[NOTE]
====
The owner ID of 65534 is used as an example. Even though NFS's *root_squash*
maps *root* (0) to *nfsnobody* (65534), NFS exports can have arbitrary owner
IDs. Owner 65534 is not required for NFS exports.
====

[[nfs-supplemental-groups]]
=== Group IDs

The recommended way to handle NFS access (assuming it is not an option to change
permissions on the NFS export) is to use supplemental groups. Supplemental
groups in OpenShift are used for shared storage, of which NFS is an example. In
contrast, block storage, such as Ceph RBD or iSCSI, use the *fsGroup* SCC
strategy and  the *fsGroup* value in the pod's `*securityContext*`.

[NOTE]
====
It is generally preferable to use supplemental group IDs to gain access to
persistent storage versus using link:#nfs-user-ids[user IDs]. Supplemental
groups are covered further in the full
link:pod_security_context.html#supplemental-groups[Volume Security] topic.
====

Because the group ID on the link:#nfs-export[example target NFS directory] shown
above is 5555, the pod can define that group ID using `*supplementalGroups*`
under the pod-level `*securityContext*` definition. For example:

====
----
spec:
  containers:
    - name:
    ...
  securityContext: <1>
    supplementalGroups: [5555] <2>
----
<1> `*securityContext*` must be defined at the pod level, not under a specific container.
<2> An array of GIDs defined for the pod. In this case, there is one element in the array;
additional GIDs would be comma-separated.
====

Assuming there are no custom SCCs that might satisfy the pod's requirements, the
pod will likely match the *restricted* SCC. This SCC has the
`*supplementalGroups*` strategy set to *RunAsAny*, meaning that any supplied
group ID will be accepted without range checking.

As a result, the above pod will pass admissions and will be launched. However,
if group ID range checking is desired, a custom SCC, as described in
link:pod_security_context#scc-supplemental-groups[pod security and custom SCCs],
is the preferred solution. A custom SCC can be created such that minimum and
maximum group IDs are defined, group ID range checking is enforced, and a group
ID of 5555 is allowed.

[[nfs-user-ids]]
=== User IDs

User IDs can be defined in the container image or in the pod definition. The
full link:pod_security_context.html#user-id[Volume Security] topic covers
controlling storage access based on user IDs, and should be read prior to
setting up NFS persistent storage.

[NOTE]
====
It is generally preferable to use link:#nfs-supplemental-groups[supplemental
group IDs] to gain access to persistent storage versus using user IDs.
====

In the link:#nfs-export[example target NFS directory] shown above, the container
needs its UID set to 65534 (ignoring group IDs for the moment), so the following
can be added to the pod definition:

====
[source,yaml]
----
spec:
  containers: <1>
  - name:
  ...
    securityContext:
      runAsUser: 65534 <2>
----
<1> Pods contain a `*securtityContext*` specific to each container (shown here) and
a pod-level `*securityContext*` which applies to all containers defined in the pod.
<2> 65534 is the *nfsnobody* user.
====

Assuming the *default* project and the *restricted* SCC, the pod's requested
user ID of 65534 will, unfortunately, not be allowed, and therefore the pod will
fail. The pod fails because of the following:

- It requests 65534 as its user ID.
- All SCCs available to the pod are examined to see which SCC will allow a user ID
of 65534 (actually, all policies of the SCCs are checked but the focus here is
on user ID).
- Because all available SCCs use *MustRunAsRange* for their `*runAsUser*`
strategy, UID range checking is required.
- 65534 is not included in the SCC or project's user ID range.

It is generally considered a good practice not to modify the predefined SCCs.
The preferred way to fix this situation is to create a custom SCC, as described
in the full link:pod_security_context.html#scc-runasuser[Volume Security] topic.
A custom SCC can be created such that minimum and maximum user IDs are defined,
UID range checking is still enforced, and the UID of 65534 will be allowed.

[[nfs-selinux]]
=== SELinux

[NOTE]
====
See the full link:pod_security_context.html#volsec-selinux[Volume Security]
topic for information on controlling storage access in conjunction with using
SELinux.
====

By default, SELinux does not allow writing from a pod to a remote NFS server.
The NFS volume mounts correctly, but is read-only.

To enable writing to NFS volumes with SELinux enforcing on each node, run:

----
# setsebool -P virt_use_nfs 1
# setsebool -P virt_sandbox_use_nfs 1
----

The `-P` option above makes the bool persistent between reboots.

The *virt_use_nfs* boolean is defined by the *_docker-selinux_* package. If an
error is seen indicating that this bool is not defined, ensure this package has
been installed.

[[nfs-export-settings]]
=== Export Settings

In order to enable arbitrary container users to read and write the volume, each
exported volume on the NFS server should conform to the following conditions:

- Each export must be:
+
----
/<example_fs> *(rw,root_squash)
----
- The firewall must be configured to allow traffic to the mount point. For NFSv4,
the default port is 2049 (*nfs*). For NFSv3, there are three ports to configure:
2049 (*nfs*), 20048 (*mountd*), and 111 (*portmapper*).
+
.NFSv4
----
# iptables -I INPUT 1 -p tcp --dport 2049 -j ACCEPT
----
+
.NFSv3
----
# iptables -I INPUT 1 -p tcp --dport 2049 -j ACCEPT
# iptables -I INPUT 1 -p tcp --dport 20048 -j ACCEPT
# iptables -I INPUT 1 -p tcp --dport 111 -j ACCEPT
----
- The NFS export and directory must be set up so that it is accessible by the
target pods. Either set the export to be owned by the container's primary UID,
or supply the pod group access using `*supplementalGroups*`, as shown in
link:#nfs-supplemental-groups[Group IDs] above. See the full
link:pod_security_context.html[Volume Security] topic for additional pod
security information as well.

[[nfs-reclaiming-resources]]
== Reclaiming Resources
NFS implements the OpenShift *Recyclable* plug-in interface. Automatic
processes handle reclamation tasks based on policies set on each persistent
volume.

By default, persistent volumes are set to *Retain*. NFS volumes which are set to
*Recycle* are scrubbed (i.e., `rm -rf` is run on the volume) after being
released from their claim (i.e, after the user's `*PersistentVolumeClaim*` bound
to the volume is deleted). Once recycled, the NFS volume can be bound to a new
claim.

[[nfs-automation]]
== Automation
Clusters can be provisioned with persistent storage using NFS in the following
ways:

- link:#nfs-enforcing-disk-quotas[Enforce storage quotas] using disk partitions.
- Enforce security by link:#nfs-volume-security[restricting volumes] to the
project that has a claim to them.
- Configure link:#nfs-reclaiming-resources[reclamation of discarded resources] for
each PV.

They are many ways that you can use scripts to automate the above tasks. You can
use an
link:https://github.com/openshift/openshift-ansible/tree/master/roles/kube_nfs_volumes[example
Ansible playbook] to help you get started.

[[nfs-additional-config-and-troubleshooting]]
== Additional Configuration and Troubleshooting

Depending on what version of NFS is being used and how it is configured, there
may be additional configuration steps needed for proper export and security
mapping. The following are some that may apply:

[cols="1,2"]
|====

|NFSv4 mount incorrectly shows all files with ownership of *nobody:nobody*
a|- Could be attributed to the ID mapping settings (/etc/idmapd.conf) on your NFS
- See https://access.redhat.com/solutions/33455[this Red Hat Solution].

|Disabling ID mapping on NFSv4
a|- On both the NFS client and server, run:
+
----
# echo 'Y' > /sys/module/nfsd/parameters/nfs4_disable_idmapping
----
|====

= Persistent Storage Using NFS
{product-author}
{product-version}
:data-uri:
:icons:
:experimental:
:toc: macro
:toc-title:
:prewrap!:

toc::[]

== Overview

OpenShift clusters can be provisioned with
link:../../architecture/additional_concepts/storage.html[persistent storage]
using NFS. Persistent volumes (PVs) and persistent volume claims (PVCs) provide
a convenient method for sharing a volume across a project. While the
NFS-specific information contained in a PV definition could also be defined
directly in a pod definition, doing so does not create the volume as a distinct
cluster resource, making the volume more susceptible to conflicts.

This topic covers the specifics of using the NFS persistent storage type. Some
familiarity with OpenShift and
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Storage_Administration_Guide/ch-nfs.html[NFS]
is beneficial. See the
link:../../architecture/additional_concepts/storage.html[Persistent Storage]
concept topic for details on the OpenShift persistent volume (PV) framework in
general.

[[nfs-provisioning]]
== Provisioning

Storage must exist in the underlying infrastructure before it can be mounted as
a volume in OpenShift. To provision NFS volumes, a list of NFS servers and
export paths are all that is required.

You must first create an object definition for the PV:

.PV Object Definition Using NFS
====
[source,yaml]
----
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0001 <1>
spec:
  capacity:
    storage: 5Gi <2>
  accessModes:
  - ReadWriteOnce <3>
  nfs: <4>
    path: /tmp <5>
    server: 172.17.0.2 <6>
  persistentVolumeReclaimPolicy: Recycle <7>
----
<1> The name of the volume. This is the PV identity in various `oc <command>
pod` commands.
<2> The amount of storage allocated to this volume.
<3> Though this appears to be related to controlling access to the volume, it is
actually used similarly to labels and used to match a PVC to a PV. Currently, no
access rules are enforced based on the `*accessModes*`.
<4> The volume type being used, in this case the *nfs* plug-in.
<5> The path that is exported by the NFS server.
<6> The host name or IP address of the NFS server.
<7> The reclaim policy for the PV. This defines what happens to a volume when released
from its claim. Valid options are *Retain* (default) and *Recycle*. See
link:#nfs-reclaiming-resources[Reclaiming Resources].
====

[NOTE]
====
Each NFS volume must be mountable by all schedulable nodes in the cluster.
====

Save the definition to a file, for example *_nfs-pv.yaml_*, and create the PV:

====
----
$ oc create -f nfs-pv.yaml
persistentvolume "pv0001" created
----
====

Verify that the PV was created:

====
----
# oc get pv
NAME                     LABELS    CAPACITY     ACCESSMODES   STATUS      CLAIM     REASON    AGE
pv0001                   <none>    5368709120   RWO           Available                       31s
----
====

The next step can be to create a persistent volume claim (PVC) which will bind
to the new PV:

.PVC Object Definition
====
[source,yaml]
----
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-claim1
spec:
  accessModes:
    - ReadWriteOnce <1>
  resources:
    requests:
      storage: 1Gi <2>
----
<1> As mentioned above for PVs, the `*accessModes*` do not enforce security, but
rather act as labels to match a PV to a PVC.
<2> This claim will look for PVs offering *1Gi* or greater capacity.
====

Save the definition to a file, for example *_nfs-claim.yaml_*, and create the
PVC:

====
----
# oc create -f nfs-claim.yaml
----
====

[[nfs-enforcing-disk-quotas]]
== Enforcing Disk Quotas

You can uses disk partitions to enforce disk quotas and size constraints. Each
partition can be its own export. Each export is one PV. OpenShift enforces
unique names for PVs, but the uniqueness of the NFS volume's server and path is
up to the administrator.

Enforcing quotas in this way allows the developer to request persistent storage
by a specific amount (for example, 10Gi) and be matched with a corresponding
volume of equal or greater capacity.

[[nfs-volume-security]]
== Volume Security

This section covers NFS volume security, including matching permissions and
SELinux considerations. The reader is expected to understand the basics of POSIX
permissions, process UIDs, supplemental groups, and SELinux.

[NOTE]
====
See the full
link:../../install_config/persistent_storage/pod_security_context.html[Volume
Security] topic before implementing NFS volumes.
====

Developers request NFS storage by referencing, in the `*volumes*` section of
their pod definition, either a PVC by name or the NFS volume plug-in directly.

The *_/etc/exports_* file on the NFS server contains the accessible NFS
directories. The target NFS directory has POSIX owner and group IDs. The
OpenShift NFS plug-in mounts the container's NFS directory with the same POSIX
ownership and permissions found on the exported NFS directory. However, the
container is not run with its effective UID equal to the owner of the NFS mount,
which is the desired behavior.

As an example, if the target NFS directory appears on the NFS server as:

[[nfs-export]]
====
----
# ls -lZ /opt/nfs -d
drwxrws---. nfsnobody 5555 unconfined_u:object_r:usr_t:s0   /opt/nfs

# id nfsnobody
uid=65534(nfsnobody) gid=65534(nfsnobody) groups=65534(nfsnobody)
----
====

Then the container must match SELinux labels, and either run with a UID of
*65534* (*nfsnobody* owner) or with *5555* in its supplemental groups in order
to access the directory.

[NOTE]
====
The owner ID of 65534 is used as an example. Even though NFS's *root_squash*
maps *root* (0) to *nfsnobody* (65534), NFS exports can have arbitrary owner
IDs. Owner 65534 is not required for NFS exports.
====

[[nfs-supplemental-groups]]
=== Group IDs

The recommended way to handle NFS access (assuming it is not an option to change
permissions on the NFS export) is to use supplemental groups. Supplemental
groups in OpenShift are used for shared storage, of which NFS is an example. In
contrast, block storage, such as Ceph RBD or iSCSI, use the *fsGroup* SCC
strategy and  the *fsGroup* value in the pod's `*securityContext*`.

[NOTE]
====
It is generally preferable to use supplemental group IDs to gain access to
persistent storage versus using link:#nfs-user-ids[user IDs]. Supplemental
groups are covered further in the full
link:pod_security_context.html#supplemental-groups[Volume Security] topic.
====

Because the group ID on the link:#nfs-export[example target NFS directory] shown
above is 5555, the pod can define that group ID using `*supplementalGroups*`
under the pod-level `*securityContext*` definition. For example:

====
----
spec:
  containers:
    - name:
    ...
  securityContext: <1>
    supplementalGroups: [5555] <2>
----
<1> `*securityContext*` must be defined at the pod level, not under a specific container.
<2> An array of GIDs defined for the pod. In this case, there is one element in the array;
additional GIDs would be comma-separated.
====

Assuming there are no custom SCCs that might satisfy the pod's requirements, the
pod will likely match the *restricted* SCC. This SCC has the
`*supplementalGroups*` strategy set to *RunAsAny*, meaning that any supplied
group ID will be accepted without range checking.

As a result, the above pod will pass admissions and will be launched. However,
if group ID range checking is desired, a custom SCC, as described in
link:pod_security_context#scc-supplemental-groups[pod security and custom SCCs],
is the preferred solution. A custom SCC can be created such that minimum and
maximum group IDs are defined, group ID range checking is enforced, and a group
ID of 5555 is allowed.

[[nfs-user-ids]]
=== User IDs

User IDs can be defined in the container image or in the pod definition. The
full link:pod_security_context.html#user-id[Volume Security] topic covers
controlling storage access based on user IDs, and should be read prior to
setting up NFS persistent storage.

[NOTE]
====
It is generally preferable to use link:#nfs-supplemental-groups[supplemental
group IDs] to gain access to persistent storage versus using user IDs.
====

In the link:#nfs-export[example target NFS directory] shown above, the container
needs its UID set to 65534 (ignoring group IDs for the moment), so the following
can be added to the pod definition:

====
[source,yaml]
----
spec:
  containers: <1>
  - name:
  ...
    securityContext:
      runAsUser: 65534 <2>
----
<1> Pods contain a `*securtityContext*` specific to each container (shown here) and
a pod-level `*securityContext*` which applies to all containers defined in the pod.
<2> 65534 is the *nfsnobody* user.
====

Assuming the *default* project and the *restricted* SCC, the pod's requested
user ID of 65534 will, unfortunately, not be allowed, and therefore the pod will
fail. The pod fails because of the following:

- It requests 65534 as its user ID.
- All SCCs available to the pod are examined to see which SCC will allow a user ID
of 65534 (actually, all policies of the SCCs are checked but the focus here is
on user ID).
- Because all available SCCs use *MustRunAsRange* for their `*runAsUser*`
strategy, UID range checking is required.
- 65534 is not included in the SCC or project's user ID range.

It is generally considered a good practice not to modify the predefined SCCs.
The preferred way to fix this situation is to create a custom SCC, as described
in the full link:pod_security_context.html#scc-runasuser[Volume Security] topic.
A custom SCC can be created such that minimum and maximum user IDs are defined,
UID range checking is still enforced, and the UID of 65534 will be allowed.

[[nfs-selinux]]
=== SELinux

[NOTE]
====
See the full link:pod_security_context.html#volsec-selinux[Volume Security]
topic for information on controlling storage access in conjunction with using
SELinux.
====

By default, SELinux does not allow writing from a pod to a remote NFS server.
The NFS volume mounts correctly, but is read-only.

To enable writing to NFS volumes with SELinux enforcing on each node, run:

----
# setsebool -P virt_use_nfs 1
# setsebool -P virt_sandbox_use_nfs 1
----

The `-P` option above makes the bool persistent between reboots.

The *virt_use_nfs* boolean is defined by the *_docker-selinux_* package. If an
error is seen indicating that this bool is not defined, ensure this package has
been installed.

[[nfs-export-settings]]
=== Export Settings

In order to enable arbitrary container users to read and write the volume, each
exported volume on the NFS server should conform to the following conditions:

- Each export must be:
+
----
/<example_fs> *(rw,root_squash)
----
- The firewall must be configured to allow traffic to the mount point. For NFSv4,
the default port is 2049 (*nfs*). For NFSv3, there are three ports to configure:
2049 (*nfs*), 20048 (*mountd*), and 111 (*portmapper*).
+
.NFSv4
----
# iptables -I INPUT 1 -p tcp --dport 2049 -j ACCEPT
----
+
.NFSv3
----
# iptables -I INPUT 1 -p tcp --dport 2049 -j ACCEPT
# iptables -I INPUT 1 -p tcp --dport 20048 -j ACCEPT
# iptables -I INPUT 1 -p tcp --dport 111 -j ACCEPT
----
- The NFS export and directory must be set up so that it is accessible by the
target pods. Either set the export to be owned by the container's primary UID,
or supply the pod group access using `*suppplementalGroups*`, as shown in
link:#nfs-supplemental-groups[Group IDs] above. See the full
link:pod_security_context.html[Volume Security] topic for additional pod
security information as well.

[[nfs-reclaiming-resources]]
== Reclaiming Resources
NFS implements the OpenShift *Recyclable* plug-in interface. Automatic
processes handle reclamation tasks based on policies set on each persistent
volume.

By default, persistent volumes are set to *Retain*. NFS volumes which are set to
*Recycle* are scrubbed (i.e., `rm -rf` is run on the volume) after being
released from their claim (i.e, after the user's `*PersistentVolumeClaim*` bound
to the volume is deleted). Once recycled, the NFS volume can be bound to a new
claim.

[[nfs-automation]]
== Automation
Clusters can be provisioned with persistent storage using NFS in the following
ways:

- link:#nfs-enforcing-disk-quotas[Enforce storage quotas] using disk partitions.
- Enforce security by link:#nfs-volume-security[restricting volumes] to the
project that has a claim to them.
- Configure link:#nfs-reclaiming-resources[reclamation of discarded resources] for
each PV.

They are many ways that you can use scripts to automate the above tasks. You can
use an
link:https://github.com/openshift/openshift-ansible/tree/master/roles/kube_nfs_volumes[example
Ansible playbook] to help you get started.

[[nfs-additional-config-and-troubleshooting]]
== Additional Configuration and Troubleshooting

Depending on what version of NFS is being used and how it is configured, there
may be additional configuration steps needed for proper export and security
mapping. The following are some that may apply:

[cols="1,2"]
|====

|NFSv4 mount incorrectly shows all files with ownership of *nobody:nobody*
a|- Could be attributed to the ID mapping settings (/etc/idmapd.conf) on your NFS
- See https://access.redhat.com/solutions/33455[this Red Hat Solution].

|Disabling ID mapping on NFSv4
a|- On both the NFS client and server, run:
+
----
# echo 'Y' > /sys/module/nfsd/parameters/nfs4_disable_idmapping
----
|====


Update 2016-04-06-Inyeccion-H-T-M-L-y-X-S-S-persistente.adoc


Update 2016-07-29-Stable-Matching-Algorithm-in-progress.adoc


Delete the file at '_posts/2017-05-21-Typeclasses-in-haskell.adoc'

// = Your Blog title
// See https://hubpress.gitbooks.io/hubpress-knowledgebase/content/ for information about the parameters.
// :hp-image: /covers/cover.png
// :published_at: 2019-01-31
// :hp-tags: HubPress, Blog, Open_Source,
// :hp-alt-title: My English Title

= Typeclasses in haskell

. You can think of them kind of as Java interface and unlike classes in OOP
. What's the type signature of the `==` function?
+
[source,shell session]
----
ghci> :t (==)
(==) :: (Eq a) => a -> a -> Bool
//`=>` class constraint
----
. Eq, Ord, Show, Read, Enum, Bounded, Num, Integral, Floating
. CHCI could infer what kind of result we wanted out of read.
+
[source,shell session]
----
ghci> read "4"
<interactive>:1:0:
    Ambiguous type variable `a' in the constraint:
      `Read a' arising from a use of `read' at <interactive>:1:0-7
    Probable fix: add a type signature that fixes these type variable(s)

ghci> read "5" :: Int
5
it :: Int

ghci> [1 .. 5]
[1,2,3,4,5]
it :: (Enum t, Num t) => [t]
ghci> succ 'b'
'c'
it :: Char
ghci> pred 'b'
'a'
it :: Char

ghci> maxBound :: Char
'\1114111'
it :: Char
----
. In this case, we can use explicit *Type annotations* by adding `::` refer to above
. 객체지향언어에 클래스들과 타입클래스는 다르다, 오히려 자바에 인터페이스 정도로 생각됨
. 타입추론이 항상 잘 될꺼라는 가정은 접어두시길

## Reference
http://learnyouahaskell.com/types-and-typeclasses