From eb219b4ceeab1bb1b0796978a1966c9262e6c1c5 Mon Sep 17 00:00:00 2001
From: Juuso Rytilahti <rytilahti.juuso@gmail.com>
Date: Fri, 3 May 2024 17:41:33 +0300
Subject: [PATCH] Part 2 material published

---
 Part 2.1 - Contract-Based Programming.md      | 134 +++++
 Part 2.2 - Constructing Routines.md           | 112 ++++
 Part 2.3 - Side-Effects and Exceptions.md     | 218 ++++++++
 ... Encapsulation and integrity of a class.md | 409 ++++++++++++++
 Part 2.5 - Constructing Groups of Classes.md  | 126 +++++
 Part 2.6 - Creating a Class.md                | 497 ++++++++++++++++++
 6 files changed, 1496 insertions(+)
 create mode 100644 Part 2.1 - Contract-Based Programming.md
 create mode 100644 Part 2.2 - Constructing Routines.md
 create mode 100644 Part 2.3 - Side-Effects and Exceptions.md
 create mode 100644 Part 2.4 - Encapsulation and integrity of a class.md
 create mode 100644 Part 2.5 - Constructing Groups of Classes.md
 create mode 100644 Part 2.6 - Creating a Class.md

diff --git a/Part 2.1 - Contract-Based Programming.md b/Part 2.1 - Contract-Based Programming.md
new file mode 100644
index 0000000..69456b7
--- /dev/null
+++ b/Part 2.1 - Contract-Based Programming.md	
@@ -0,0 +1,134 @@
+# Contract-Based Programming / Design
+
+**Methodology** aims for correctness. 
+
+**Component**  examines routines and classes. Component is a concept that describes a self-contained piece of software in which the components are strongly interconnected and the links between the components are looser, allowing the software to be assembled from the components, and also allowing the components to be interchangeable. Component can be small, but in practise components are bigger than a couple of methods e.g. they might contain multiple classes. In java a typical component could be e.g. a package that contains multiple classes.
+
+Components can be examined in two different ways: client relationship and inheritance relationship.
+
+**Specification** forms a **contract** between the (software) component's client and **implementor** (**interface**). In this context interface could be described as a communication layer between two different entities. Later in this course the term interface will also be used in a slightly different context.
+
+If the  component is not defined, can it even function incorrectly? On the other hand, if code follows the specification exactly (code === specification), then the code cannot function incorrectly! This might not matter so much on smaller projects (e.g. solo hobby projects), but when the scale (and the team size) grows, the need for the code to follow the specification becomes more important as well! As a more concrete example, think if the library you used to e.g. sort an array would cause an undisclosed side-effect?
+
+**redundancy**: e.g. verbal definition of a program code (e.g. method), and unit tests represent redundancy. – similar to strong typing for variables (e.g. `int num`). For example if we first define a method with comments and then implement the method. If the method follows the code exactly, there is redundancy on the comment and the implementation. Redundancy is not a bad thing in this context, as it increases the reliability of the code.
+
+## Using Contracts in the Course
+
+At first we will have a a brief introduction to specification, correctness, and contracts (this tutorial). The objective is to provide a new, correctness-emphasizing perspective on the subject matter.
+
+Contract is a mean to implement the *divide-and-conquer*-approach and break down (complex) design tasks.
+
+This course focuses on understanding the idea, using non-formal specification. (this will be discussed later during the course). 
+
+In the context of object-oriented programming theory, rule descriptions will be used to explain the theory in practice. In this context the objective of the rule description is to document and explain the operation of object concepts in a more formal way.
+
+At the end of the course, there will be a review of the use of contract-based programming. Its objective is to give you the ability to design your own contract terms and link them to implementation.
+
+Using contract-based programming can be taken even further:
+- Formal specifications can even be verified, e.g., at the compilation stage (~meta-level).
+- Specifications enable writing (unit) tests for the component. 
+- Specifications can also assist in designing tests.
+- In the future they could maybe be utilized using Large Language models. NOTE: there are risks based on this approach (mainly hallucination).
+
+## Example: Contract Specifications
+Let's look at couple an example:
+```java
+public class InsertionSort {
+
+    /** Method 'sort'
+        Meaning: Sort integers in ascending order using insertion sort.
+        Parameter numbers: a vector containing the numbers to be sorted.
+        Precondition: 'numbers' is not null; 'numbers' contains only
+        Integer-type objects.
+        Postcondition: Returns a new vector where 'numbers'' integer objects are sorted in ascending order. Does not
+        modify the 'numbers' vector. No side effects.
+        Stable (with respect to equal elements).
+        Exceptions: none.
+    */
+    public static Vector<Integer> sort(Vector<Integer> numbers)
+```
+
+The method names in the contract specification (e.g.`Method sort`) is in this case an unnecessary redundancy, as java defines the method name in the method's signature. It is included here as an example, as what is included in the specification depends also on the information the programming language itself conveys.
+
+The contract-based programming adds to the comment the `precondition` and `postcondition` and `exception`.
+
+The `precondition` is a list of conditions that must be fulfilled in order to ensure that the program executes correctly.
+
+The `postcondition` is important, as it can convey information e.g. if the method returns a new array, or mutates e.g. an array given as a parameter. This information might be useful, if e.g. one wants also to preserve the original array for some other purposes, e.g. displaying it based on multiple different sorting options (e.g. name, profession, etc.).
+
+Additional note: Stable means that if the elements are equal, their original order remains.
+
+## Example: Contract Specifications #2
+```java
+    /** Method 'findPosition'
+        Meaning: Returns the position in 'vec' where inserting 'elem' would
+        keep 'vec' sorted.
+        Parameter vec: An integer vector to search for 'elem''s position.
+        Parameter elem: The integer for which a position is sought in 'vec'.
+        Precondition: 'vec' and 'elem' must not be null. All elements of 'vec'
+        and 'elem' are Integer-type objects.
+        'vec''s elements are in ascending order.
+        Postcondition: Returns the integer position of the first element in 'vec'
+        that is greater than 'elem'. If none are greater, returns the size of 'vec'.
+        No side effects; does not alter 'vec' or 'elem'.
+        Exceptions: none.
+    */
+    public static int findPosition(Vector<Integer> vec, Integer elem)
+```
+
+Please note that the specification might also be not dependent only on the code it describes, but also the writer of the specification. Exact wording might differ between specifications of the same code from different writers.
+
+As an additional side note: In java, that elements can be null requires that they are based on objects. More specifically, if the `elem` would be `int` instead of `Integer` it could not be null in any situation.
+
+## Contract Implementation
+
+Roots trace back to the 70s to the works of E.W. Dijkstra, who created a kind of foundation for the Science of Programming direction. Background: *Bertrand Meyer / Eiffel Software 1986: Design by Contract*.
+
+Examples of contract implementation in languages
+- Directly in the language (e.g., programming language `D`)
+- Separate library (e.g., Java)
+- Separate precompiler
+- Comments (= not officially supported by the language). The comments are only instructions to the people reading the code. This is also the way contracts are mainly used in this course. Java takes this into consideration using signatures, which will be covered later on the course.
+
+
+## What do routine contracts address?
+- Input
+
+    - Allowed input values and meaning of the input values.
+    - **Preconditions**
+
+- Result/Output
+
+    - Allowed result values and the meaning of the result.
+    - **Postconditions**
+
+- Other Aspects that need to be considered when creating the specification
+
+    - How complete is the specification?
+      - All possible scenarios are impossible to cover!
+    - Error and exception situations
+    - Invariants
+    - Side effects
+    - Efficiency: time, and space complexity
+    - Methods of objects: the object itself is also an input and a result!
+   
+
+It should also be noted that in this course we probably go further than is necessary in real-life scenarios. However using (at least partially) contracts can and probably will be a beneficial tool for programming, especially on larger projects. Need of good documentation of the code can also be seen if you e.g. want to re-start developing a hobby project after taking a longer break of its development. 
+
+
+# Obligations as Contracts
+|            | Obligations                                          | Benefits                                                   |
+|------------|------------------------------------------------------|------------------------------------------------------------|
+| Customer   | The precondition must be valid before the call      | After the call, the postcondition is valid                 |
+| Implementer| The implementation must bring the postcondition into effect | Situations pruned by the precondition do not need to be addressed |
+
+defining the postcondition is often easier, because the precondition can often exclude complex scenarios.
+
+Another way to formulate:
+
+- What does the contract expect as input?
+- What does the contract guarantee as output?
+- What does the contract maintain?
+
+Now continue to:
+[Part 2.2 - Constructing Routines](Part%202.2%20-%20Constructing%20Routines.md)
\ No newline at end of file
diff --git a/Part 2.2 - Constructing Routines.md b/Part 2.2 - Constructing Routines.md
new file mode 100644
index 0000000..403d5d6
--- /dev/null
+++ b/Part 2.2 - Constructing Routines.md	
@@ -0,0 +1,112 @@
+# Constructing routines
+
+Today’s topics
+- Constructing routines
+- Routine specification
+- The significance of routine definition
+
+## The desired outcome
+
+Each routine should have one clear purpose. The routine represents some functional concept. The name of the routine should create and reflect the method's meaning. The rules on how methods should be written differs.
+
+The implementer should not (for the most part) need to know how the routine is used. This leads us to a principle called **Encapsulation**. The benefit of encapsulation is that the method's caller does not need to know how the routine is implemented. 
+
+For a more concrete example, if you are sorting an array using a predefined library, you do not need to know the specific implementation, only what are the preconditions and what are the postconditions (e.g. does the sorting method return a new array or mutate the original).
+
+Additionally, often it is preferable to have many 'moderately small' clearly stated routines rather than one complex routine that implements many things (divide-and-conquer). If the routine is overly complex, and contains multiple different functionalities, it can often be used only in very specific scenarios, leading to duplicate and hard-to-maintain code.
+
+**Signature** is the interface between the routine’s caller and implementer. It defines what functionality is the responsibility of the routine, what is excluded, and what is handled as a special case. An example of a routine is presented later on this lecture.
+
+an example of a signature in Java: 
+```java
+public float sqrt(float x) throws IllegalArgumentException
+```
+
+
+Side effect management is a significant challenge in defining definition and correctness.
+
+
+## Routine specification
+
+Let's look at the following example:
+
+```java
+/**
+* Returns the square root of x.
+* @.pre true (= precondition is always true)
+* @.post Math.abs(RESULT * RESULT - x) < 1.0e-10
+* & RESULT >= 0.0, or x < 0 -> raise exception
+*/
+public float sqrt(float x) throws NegValueException
+```
+
+**Definition** of the above example is on the lines 1-6 (the comment). It should be noted that this definition is partly unformal (e.g. the postcondition '*, or x < 0 -> raise exception*'). If the pre and postconditions would result in boolean values, the contract would be formally defined. However, as this method is aimed to be readable by a human, and not by a machine, this approach is fine. 
+
+If we look at the example more closely, The specification above constructs from the following parts:
+
+Verbal description:
+`Returns the square root of x.`
+
+Pre-condition:
+`@.pre true (= precondition is always true)`
+
+Post-condition:
+`@.post Math.abs(RESULT * RESULT - x) < 1.0e-10`
+
+The method's signature is the following
+```java
+public float sqrt(float x) throws NegValueException
+```
+
+We can also look more closely to the method's signature:
+
+access modifier: `public`
+
+result type: `float`
+
+method name: `sqrt`
+
+parameters: `float x`
+
+throwable exceptions: `throws NegValueException`
+
+In Java, a method's signature is part of the programming language itself. It specifies:
+
+- The name of the method
+- The data types of input and output values
+- The method's visibility (in a class context)
+- Exceptions raised by the method (only in error situations)
+- Generic types (not shown above, will be discussed later)
+
+As an additional side-note, the names of the parameters are not particularly significant in Java's signature!
+
+All methods have some sort of definition, which is **clarified** by the preconditions, postconditions and by the verbal description of the routine.
+- Precondition: when it can be called
+- Postcondition: what happens after the method has been called (e.g. the method returns an new array of students sorted by surname.)
+
+## The Significance of Routine Specification
+
+Routine specification can be seen as a communication between the routine and the client. Additionally, the implementation is freely modifiable, as long as the specification of the routine remains unchanged.
+
+The routine's caller does not need to know the implementation (sometimes they don't even have access to it)
+
+- Planning and Documentation
+    - Planning is possible with just routine specifications
+    - The same specification formalism throughout the project
+- Expectations
+    - What does the implementer commit to?
+    - Well defined routine specifications leads to general usability and reusability.
+
+Functionality of a routine can be verified with the routine specifications. One relevant question is does the implementation match the specification? If the specification is good, it can, for example, make writing unit tests easier. Additionally, in some languages and/or plugins, the specification can be automatically tested to make sure that the implementation follows the specification, thus making the code more robust.
+
+On the other hand, if the specification is missing or it is inadequate, the specification cannot be objectively verified. This leads to problems, especially in large and/or old projects. As a more concrete example, imagine joining into a 10-year-old project as a software developer. On your first day, you would notice that there is very little to no comments on the code. Maintaining or extending the code would be a nightmare!
+
+
+Routine specification also aims to give means to locate possible errors. The specification tries to provide "boundaries" for correction. If everything worked before the method was called and the precondition was fulfilled, if the method does not follow the postcondition, the error is most likely withing the routine specified by the specification. 
+
+As an additional side note, older code is often more reliable than new. Of course there are exceptions on this, as e.g. dependencies get major updates and require changes to the old code that uses them.
+
+In object-oriented programming, the routine specification in the context of classes, tries to affect the selection of characteristics and roles. There is also the additional challenge of ensuring class encapsulation. In the case of inheritance, there's a separate agreement between the inheritor and the inherited class.
+
+Now continue to:
+[Part 2.3 - Side-Effects and Exceptions](Part%202.3%20-%20Side-Effects%20and%20Exceptions.md)
\ No newline at end of file
diff --git a/Part 2.3 - Side-Effects and Exceptions.md b/Part 2.3 - Side-Effects and Exceptions.md
new file mode 100644
index 0000000..0ad992e
--- /dev/null
+++ b/Part 2.3 - Side-Effects and Exceptions.md	
@@ -0,0 +1,218 @@
+# Side-effects
+
+## What are side-effects?
+
+The concept of a side-effect is related to execution, and thus to methods. A side-effect means that something changes as a result of execution, typically a variable’s value changes.
+
+For example, a method that simply calculates a return value based on input values is free of side-effects.
+
+As an another example, a method that updates the value of some instance variable of an object has side-effects.
+
+Essentially, the prerequisite for a side-effect is that the programming language has an *assignment statement*. Assignment statement is a programming language structure that sets the value of the state indicated by a variable, but returns nothing (the setting is merely a side effect). 
+
+## Are side-effects unnatural? Undesirable?
+
+One way to look at side-effects is to use mathematics as a starting point. In mathematics, there are no side-effects; the 'variables' in mathematics are not like variables in imperative programming languages (such as Java). In mathematics, variables are set once to represent a value - in programming languages, a variable's value can change during execution.
+
+Side-effects are a natural way in imperative languages to change state. Computation/execution in imperative languages essentially consists of a series of state changes. Often, methods of objects are intended to have effects on the object’s state, thus having side-effects.
+
+In terms of method descriptions (and therefore correctness), the description of side-effects can be overlooked, especially if the effect extends outside the OO-program.
+
+## Manifestation of side-effects
+
+Let's look at side-effects more broadly. The following table lists manifestation of side-effects from an individual object towards larger entities:
+
+| Context                        | Description                                                                                      |
+|--------------------------------|--------------------------------------------------------------------------------------------------|
+| Internal state of the object   | Variables of the object during the execution of an OO-program.                                    |
+| Global state                   | Static variables of classes related to the execution of an OO-program.                            |
+| Operating system level         | Information in the execution environment of an OO-program that can be programmatically changed.   |
+| External world                 |   Effects on hardrives, networks, physical hardware, etc.                                                                                               |
+
+## Example: Side-effect to the internal state of an object
+
+The example below highlights that in java you can have a variable and a method with the same name. The idea is to display that the visibility of a variable can be limited to allow direct edits of a variable e.g. only inside the class itself. The method `isRunning()` enables us to ask the state of the variable outside this class.
+
+```java
+class Car {
+private boolean isRunning;
+boolean isRunning() { return isRunning; }
+/**
+    @.pre isRunning() == false
+    @.post isRunning() == true (side-effect)
+    */
+    void start() { isRunning = true; }
+    
+    /*
+    @.pre isRunning() == true
+    @.post isRunning() == false (side-effect)
+    */
+    void stopEngine() { isRunning = false; }
+    }
+```
+
+## Example: Global side-effect
+Creating objects of the Object class has a side-effect on the global state:
+
+```java
+class ObjectPool {
+static int createdObjects = 0;
+}
+class Object {
+{ ObjectPool.createdObjects++; }
+}
+void main() {
+    new Object();
+    new Object();
+    System.out.println(ObjectPool.createdObjects);
+}
+```
+In the example, the class keeps a tab on how many objects are created. This is a side-effect.
+
+In the example above, you might notice that the `public static void main(String[] args) ` has been changed to `void main`. This is possible in newer versions of Java. However, ViLLE does not yet support this.
+
+## Example: Side-effects outside the virtual machine
+
+Once again, we use newer Java to shorten the example.
+
+File creation:
+```java
+Files.writeString(Path.of("/tmp/test"), "some content");
+```
+Printing to the console:
+```java
+System.out.println("Hello world!");
+```
+Other side-effects:
+
+- Memory allocation outside of the JVM (Java Virtual Machine)
+- Changes to the graphical user interface.
+- Network connections
+- …
+
+## Limiting side-effects in language
+
+- In most mainstream languages, the use of side-effects is common.
+- BUT: side-effects make ensuring the correctness of the code challenging.
+
+This raises a natural question: how to limit side-effects?
+
+In a purely  functional language a variable can only be set once. 
+
+In Java, the side-effects can be limited by e.g. using the **final** modifier, immutable data structures, and voluntarily taking a disciplined approach to avoid possible side-effects.
+
+If side-effects are limited, assembling a program from separate components is more reliable. The scope of an function is apparent from its signature; on the other hand, this causes longer signatures. 
+
+
+# Handling of special cases
+
+Method could be imagined as a mathematical function. This is not exact definition, but (figuratively) it works.
+![reload button](images/part-4/routine-as-a-mathematical-functin.png)
+
+![reload button](images/part-4/partitioning_of_the_domain.png)
+
+- As an example, when opening a file:
+  - Precondition: name is null or empty
+  - Special case (in this case throws exception): File is not found.
+
+
+## Partial and Total Routine
+
+- A routine is said to be **total** if it has no preconditions, and **partial** if it does.
+- A total routine can be called at any time.
+- Users of a partial routine must ensure that preconditions are met when calling.
+- Exceptions are often used to make a routine total, or less partial.
+- However, making all routines total is not the goal.
+- Raising exceptions in the implementation of a routine often requires runtime checks.
+- Calling a routine that raises exceptions requires handling code from the caller as well.
+- When exceptions are used in routine signatures, there should be an effort to use descriptive exception classes, defining them as necessary.
+
+![absolute value example](images/part-4/absolute_value.png)
+In the example above, the type of the variable (number) causes that there is no need to add (any) preconditions. 
+
+The left side presents input values and the right side output values The impossible values return values are marked with gray background.
+
+
+
+We can look at another example (below).
+
+
+
+![second square root example](images/part-4/square_root.png)
+
+In this example we need to limit negative values from possible input values.
+
+ If this would be implemented in Java, we would need to describe this special case in precondition of the method. So the method could be defined in the following way:
+
+```java
+/* @.pre x >= 0
+* @.post Math.abs(RESULT*RESULT - x) < 1.0e-10.0 */
+double sqrt(double x)
+```
+
+Now the grayed values in input are limited with precondition.
+
+An alternative way to solve this issue could be the following:
+![total square root and special situations](images/part-4/total_square_root_and_special_situations.png)
+```java
+// R sqrt(D d) throws e1, e2, e3
+double sqrt(double d) throws IllegalArgumentException
+```
+We could implement the method so that there is no precondition. This however would mean that the method should handle these situations. In this case, in case of invalid input values `d`, the method throws `IllegalArgumentException`.
+
+On the image, the questions mark shows that the grayed out output values on the right are impossible to get as an ouput from the defined method.
+
+## Rules of Thumb for Handling Special Cases
+
+1. Shift the special case to a precondition if it is clear and understandable from the client's perspective.
+2. If rule 1 does not work, handle special cases with manageable exceptions, thereby forcing the clients to address them.
+3. If rules 1 and 2 do not work, handle the special case in another way (to be revisited later in the course).
+
+## Use of the Exception Mechanism
+
+
+The exception mechanism's use appears in three parts of Java syntax:
+
+1. **throws**: Indicates in the signature the checked exceptions that the routine may raise.
+2. **throw** T: Raises the exception **T** in a special situation.
+3. **catch**(T e) {}: Handles exceptions of type **T** that were raised within the preceding **try** block.
+
+The raised exception is an object of the exception class.
+
+- If necessary, define the class.
+
+The following example highlights the possible ways to use exceptions in Java:
+
+```java
+
+class EmptyArray extends Exception {}
+
+float avg(int[] nums) throws EmptyArray { // 1
+    int sum = 0;
+    if (nums == null || nums.length == 0)
+        throw new EmptyArray(); // 2
+    for(int n: nums) sum += n;
+    return sum / nums.length;
+}
+void main() {
+    int[] nums = new int[] { 1, 2 };
+    Float result;
+    try { result = avg(nums); } // 3
+    catch(EmptyArray e) {} // 3
+}
+```
+Java requires that if an exeption is thrown, it should also be defined in the method's signature (*throws*). In java, also the catch should define correct exception (So in this particular case, if the code would raise some other exception than `EmptyArray`, the `catch` block would not be executed and the code would crash.
+
+
+
+## Key Challenges in Defining/Implementing Routines
+
+- Have all 'special cases' and partialities been remembered in terms of the routine's calling situation?
+- Is the use of exceptions well-considered?
+- Considering side-effects in specification and implementation.
+- Can the input or output values be null - are their meanings defined?
+- From the perspective of encapsulation, reference value semantics (passing references to be stored within an object) can pose a threat to the implementation of encapsulation (to be addressed later in course when the class formation is discussed).
+
+
+Now continue to:
+[Part 2.4 - Encapsulation and integrity of a class](Part%202.4%20-%20Encapsulation%20and%20integrity%20of%20a%20class.md)
diff --git a/Part 2.4 - Encapsulation and integrity of a class.md b/Part 2.4 - Encapsulation and integrity of a class.md
new file mode 100644
index 0000000..65007e8
--- /dev/null
+++ b/Part 2.4 - Encapsulation and integrity of a class.md	
@@ -0,0 +1,409 @@
+# Encapsulation and integrity of a class
+
+Today's Topics:
+
+- From Routine Specification to Object-Oriented Programming
+- Protecting the Class: Encapsulation and Integrity
+  - External and Internal Threats
+  - Class Integrity: Class Invariant
+  - Public Invariant and Abstraction Function
+  - Protecting the State of an Object
+  - Class-Level Visibility Protection Modifiers
+  - Aspects of class protection
+
+## From routine specification to object oriented programming
+
+![](images/part-5/from_routine_specification_to_object_oriented_programming.png)
+
+Routines are in their core only sequences of code, which can be called repeatedly. Routines can have relations to another routines. For example, if we have three routines A, B and C, calling one routine can require calling some other routine.
+
+
+A more concrete example of the above image, could be that Routine A is a survey, routine C asks user information about that survey and routine B prints the answers given by the user. Due to the notation, routine A can call Routine C many different times with different parameters.
+
+Specification of a routine in contract-based programming can include the following things: pre-conditions, post-conditions, signature, verbal description.
+
+How the implementation of the desired method is done? The implementation can focus on e.g. the following things:
+  - Algorithms, data structures, etc.
+  - Data transfer: parameters (what routine is given as input), return values (what routine gives as output), global variables (a variable located outside of the routine, but still visible to the routine)
+
+The main focus of this course is designing and planning, not the impelentation itself.
+
+Encapsulation is an important aspect as well. Routine caller is unaware of the implementation, coding is done according to the specification.
+
+Next, lets look at a second abstract example:
+
+![](images/part-5/from_routine_specification_to_object_oriented_programming_2.png)
+
+In this example routine A and B belong to the same class, because they are cohesive. Cohesive routines should be grouped into the same class. 
+
+Each class object provides a common internal state to its routines (routine → method).
+
+New aspects in specification include: 
+
+a.) **features** of a class (around what data the class is built), 
+
+b.) constraining the **public interface** (**encapsulation**), 
+
+c.) **internal state** and **integrity** of the object 
+
+d.) **generalization**, **universality**.
+
+Features defined in a class are in the use of every instance of that class. 
+
+Constraining the public interface would be in Java, e.g. when the method has been set to private instead of public so it can be called only by the routines defined in that class. 
+
+The internal state means that the object has protected the inside of the class. Integrity means that we have some rules in place, that all of the objects adhere to. This could mean e.g. that a string variable can't be empty and it should always be in a specific format (e.g. personal identification number).
+
+Generalization and universality relate to inheritance and polymorphism and will be revisited later on the course.
+
+## Class Protection: Encapsulation and Integrity
+
+Let's assume that we have somehow identified the data content around which a class could be built. 
+
+If the class would be a class describing Students, a *Student* class should contain at least a name, study right and a student number.
+
+So we can ask what should be known about protecting the content of the class?
+
+We should think each feature through and define situations where they should be public to other classes.
+
+*How to apply encapsulation in the context of a class?*
+A practical example. Let's imagine that we would like to allow editing of the students name after it has been saved. This means that we should probably encapsulate the name change inside the said class and implement special rules, e.g. name must be at least one character long. This can be achieved inside the class with a *setName* method and protecting the actual *name* variable by setting it as private.
+
+
+*What does integrity mean in the context of the class (objects)?*
+Integrity could mean in this context that the student number is in a specific format, following specific predefined rules. Another example of integrity is that if the students age is saved, it could never be below zero. However, the rules should not be too strict, as they might cause problems, e.g. the student number could be in multiple different formats across different universities or a student could have multiple different student numbers.
+
+- Indirectly: What does class invariant mean? Class invariant is a way to enforce the rules.
+
+### Internal and external "threats"
+
+Below is an image that depicts two objects interacting with each other. It should be noted that the term attack is a little misdirecting in this case, as the objects are not active entities. 
+
+
+![](images/part-5/external_and_internal_threats.png)
+
+In the image, all objects are in control of the programmer and behave in the exact way programmer made them behave. This means that if the external attack is not preferred, e.g. it tries to modify some variable that it should not modify, access to the method used to perform the change could be hidden. Another way to mitigate attacks is that the method itself would not allow unwanted modifications e.g. setting a negative age for the student. We should not be overly optimistic as what the external object tries to achieve, but instead rely on preconditions said on the routines specification.
+
+Internal attack means in this context, that the object could contain methods, which could modify the object's internal state. There should also be some protection in place to avoid possible mistakes made by the programmer. This is a more realistic example of a risk especially in more complex classes.
+
+
+# Class Integrity: Class Invariant
+
+Requirements similar to pre-conditions and post-conditions are expanded to cover the class and all its instances, i.e., objects as a whole (→ **class invariant**).
+
+So a class invariant is a statement about the state of the object similar to pre-conditions and post-conditions (invariant → truth-valued & must always be true). It must be true immediately after the formation of an **object** of a class (after the **new**-call is complete). The invariant must remain true after each method call. Even though it is referred to as a **class** invariant, each **object** instance of the class must fulfill the condition.
+
+Invariant is a more broadly used term, which contains a set of truth (boolean) values.
+
+Further distinctions:
+- **Public class invariant**: Communicates to outside the rules set by the class for its objects, must be verifiable by users (challenging, because of encapsulation!).
+- **Private class invariant**: Communication is directed towards the implementing entity and handles, if necessary, the members hidden by **encapsulation**.
+
+Additionally, access to members (variables/methods) may be restricted with **protection modifiers**.
+
+### Example: Class Integrity
+The following example models a stack with a maximum of 10 elements. 
+
+The following is an example of using a class invariant, but it should be noted that it doesn't really follow good practice, as the code functionality relies solely on  the programmer following the specification (e.g. `push()` method's precondition is that you should push only if the size is less than 10). The `size` is set in the `@.classInvariant` as it is visible outside of the class (public).
+
+```java
+class Stack {
+  // @.classInvariant size() >= 0 && size() <= 10 // size() verifiable
+  // @.classInvariantPrivate data != null && s >= 0 // for implementer's knowledge
+  private int s = 0; // visibility limited
+  private int[] data = new int[10]; // visibility limited
+  
+  // @.pre true
+  // @.post RESULT == (stack size)
+  int size() { return s; }
+  
+  // @.pre size() < 10
+  // @.post size() == OLD(size()) + 1 && pop() == element
+  void push(int element) { data[s++] = element; }
+  
+  // @.pre size() > 0
+  // @.post size() == OLD(size()) - 1 && RESULT == (top element)
+  int pop() { return data[--s]; }
+}
+```
+### Class Invariant: What if..?
+
+The class invariant is therefore in effect at the beginning and end of each class method call.
+
+What about during the class methods execution?
+  - A: Since methods often change instance variable values incrementally as a side effect, the class invariant does not need to be in effect at every moment during the method's execution!
+
+What if, during the execution of class X's method, a method of another class Y is called, and through it indirectly calls again class X's (possibly another) method?
+  - Possible problem!
+  - **Solution**: It should be ensured that the class invariant is maintained if a method of another class is called, passing the calling object as a parameter.
+
+  ### Object's state
+
+Let's look at the following image:
+
+![](images/part-5/object_state.png)
+
+The image is divided into two parts by a line in the middle. The image does not represent only object-oriented programming, but it also is based partially on **abstract data type** theory.
+
+ The upper part of the image could be seen as presenting concepts. For example, we have an abstract specification, e.g. in the previously presented example *Stack*. The public class variant does not take into account how the stack is implemented, but in `Stack` implementations there is normally methods `pop()`, `push` and `size`. In OO-programming context, the upper part of the image could also be seen as an interface. 
+ 
+ The lower part of the image can be seen as a concrete class, containing also the implemenation of said class. Additionally, in Java, if the method shares the same name and the same signature, the concept is 1:1 (=the same) between the concrete class and the interface of the method the class implements.
+
+The *abstraction function*, links the concept or idea and the actual implementation together. For example, if there is implementation of the *Stack* class, the abstraction function describes how the idea of stack is presented in the implementation. 
+
+## Public Invariant and Abstraction Function
+
+- The purpose of the public invariant is to guarantee properties that the class object possesses and on which the class's clients can rely.
+- BUT the purpose of encapsulation is to hide the implementation – *how can a public invariant express anything about the properties of the class objects?*
+
+Option 1: Expressed using the public properties of the class.
+
+Option 2: Defined as a set of abstract properties (= abstract object; abstraction function) that the class objects possess, and these abstract properties are used.
+
+The approaches presented above are often similar.
+
+
+Now, let's look at an example: 
+
+*free spaces in a parking garage*
+
+- Abstract features: **freeCount**, **freeSpotsList** (Note: does not tell anything about the implementation e.g. is int, but instead tells the number of the free spots remaining).
+- Public invariant: **freeCount == (freeSpotsList.length)**.
+  - Boolean value, tells about the feature.
+
+There are (at least) two possible ways to do the internal implementation of the features:
+1. Implementation: **boolean spots[]**;
+   - Private class invariant: **spots != null**.
+2. Implementation: **int freeCount; boolean spots[];**
+    - Private class invariant: **spots != null && freeCount == (number of false values in the array spots)**.
+
+The implementation presented in option 1 has it's issues. If we would like to know how many free spots there are available, we would need to loop through the boolean array *spots*. This would probably be fine if the amount of spots stored inside the array would be small. But if the amounts of available spots is large, for example, if there would be thousands or even tens of thousands of spots, this could hinder the software's performance significantly.
+
+Option 2 is better, because with this approach information about the amount of available spots does not require any additional calculations, but can be directly seen from the value *freeCount*. This is because in option 2 the variable freeCount is updated every time the list is changed.
+
+Quite often public interfaces are methods instead of directly accessing a variable, while internally the variables might be modified directly.
+
+## Encapsulation: What if..?
+
+- If we have a recursive data structure, e.g., a binary search tree (BSTree), with properties:
+
+1. Root node value (**int**)
+2. Left subtree (**BSTree**) and
+3. Right subtree (**BSTree**).
+
+- Class invariant: All values in the left (right) subtree are smaller (larger) than the root.
+- Values can be added to the tree, and values can be removed from it. Null values indicate empty subtrees.
+- What if a reference to the left/right subtree is given out to some other class? (It's natural.)
+   - This might violate the class invariant, as then the class would have no control on how the subtree is being manipulated through the reference.
+   
+So how can the class invariant be maintained in the tree and all its subtrees?
+ 
+Generally speaking, its difficult! Copying the object (or in this case the subtree) could maybe provide a sufficient solution. However, a good solution should not give a reference to the subtrees (= encapsulation).
+
+Exposure of internal representation (*representation exposure*) is a common challenge.
+
+A common problem could be described in the following way: **when the class invariant depends on sub-objects, their content must be controllable** (e.g., no references allowed outside the object to sub-objects).
+
+As a more concrete example, let's examine the following implementation for the BSTree Class:
+
+```java
+class BSTree {
+  // @.classInvariant: if left != null, then left.largest() < value
+  // && if right != null, then right.smallest() > value
+  private int value; // visibility limited
+  private BSTree left = null, right = null; // visibility limited
+  // Constructors
+  BSTree(int value) { this.value = value; }
+  BSTree(int value, BSTree left, BSTree right) { ... }
+  int smallest() { ... }
+  int largest() { ... }
+  void insert(int value) { ... }
+  void remove(int value) throws EmptyTreeException { ... }
+  BSTree getLeft() { return left; }
+  BSTree getRight() { return right; }
+}
+```
+Notice, how the `@.classInvariant` limits the possibilities.  For example, what happens when a element in the tree is edited... One option could be to construct the whole tree again.
+
+Now let's look at parts of the presented example more closely:
+
+```java
+class BSTree {
+// @.classInvariant: if left != null, then left.largest() < value
+// && if right != null, then right.smallest() > value
+private int value; // limited visibility
+private BSTree left = null, right = null; // limited visibility
+...
+BSTree getLeft() { return left; }
+BSTree getRight() { return right; }
+```
+Look at the methods `getLeft` and `getRight`. Notice how they return a instance of *BSTree*? And the class BSTree allows the modification of the tree? So methods `getLeft` and `getRight` leak internal representation, therefore breaking encapsulation!
+
+These methods might not be in the external interface. Or perhaps only a deep copy of the subtree should be given out. (Deep copy = copying of the transitive closure = a full copy, which has zero references to the original object.)
+
+
+There are also other problems regarding the current implementation:
+
+```java
+// Constructors
+  BSTree(int value) { this.value = value; }
+  BSTree(int value, BSTree left, BSTree right) { ... }
+```
+The second constructor breaks if it stores the left and right references as part of the object being formed (it should copy the content of the passed objects).
+
+More generally speaking, this is about reference semantics. The same object can be a value in several 'places', leading to multiple references through which operations can be performed on the object's content.
+
+The problem arises in situations where the object's integrity (invariant) depends on the state of the sub-objects (values of the object's instance variables).
+
+
+## Protecting Object State
+In the next chapters, we'll consider the following methods to protect an object's internal state:
+
+- Visibility protection modifiers
+- Controlled handling through methods
+- Immutable data: changes are not allowed
+- Make a copy: changes do not affect the original
+- Wrapper object: selectively delegates changes
+
+### Visibility Protection Modifiers
+Levels of Protection for Visibility
+
+| Level    | Description                                                |
+|----------|------------------------------------------------------------|
+| Class    | Protecting the internal state of the object from external threats. |
+| Package  | Protecting the class from use outside the package.          |
+| Module   | Protecting packages from use outside the module.            |
+
+Visibility protection is enforced during the program's compilation. This means there is no need to separately validate them with a runtime test. Protection modifiers do not impose any 'burden' considering execution efficiency.
+
+### Class-Level Visibility Protection Modifiers
+
+- Based on limiting the visibility of class members. Also leads to limited use of hidden members. Visibility modifiers are **encapsulating** the implementation. They also aim to protect the object's state from external, possibly class invariant-breaking changes.
+
+Java's protection modifiers:
+  - **public**
+  - package (default)
+  - **protected**
+  - **private**
+
+Note: *package* is not a reserved word in Java!
+
+Let's look at the class level visibility scopes in more detail:
+  ![visibility scope table](images/part-5/class_level_visibility_scopes.png)
+
+  **X** marks which entity sees which member protected by the visibility modifier.
+
+  One thing that could be suprising is that subclass and inner class are visible (=accessible) inside the whole package if not specified otherwise.
+
+
+### Controlled Handling Through Methods
+
+Hiding member with a visibility modifier is an efficient way of controlling access (**private**, **protected**, package). Member is a part of instance of an object, e.g. variable. Controlled access is given only through visible methods.
+
+Only one "level of indirection" can be protected = a reference, i.e., if a member refers to an object, that object must manage its own protection. This comes with a consequence: If a member object cannot protect itself, no *reference* to this member should be given out from the object.
+
+There are no problems with primitive types, as primitive types return a copy (value semantics) and not a reference. This is also the case when getting a primitive type variable with a method.  For example, here `getMaxsize()` returns a copy of the internal size.
+
+```java
+class MyArray {
+    private int maxSize = 0;
+    int getMaxSize() { return maxSize; }
+    void setMaxSize(int maxSize) { this.maxSize = maxSize; }
+}
+```
+
+Now let's consider following two implementations, that provide the same functionality.
+
+Implementation 1:
+```java
+
+class MyArray {
+    public int maxSize = 0;
+}
+```
+Implementation 2:
+```java
+class MyArray {
+    private int maxSize = 0;
+    public int getMaxSize() {
+        return maxSize;
+    }
+    public void setMaxSize(int maxSize) {
+        this.maxSize = maxSize;
+    }
+}
+```
+
+Which one is better?
+
+There is no definitive answer. If the code would be implemented as is, without changes, then setting the getters and setters for `maxSize` introduces unnecessary complexity and bloat. On the other hand, if the code would be changed later, the advantage of implementation 2 is that additional restrictions can be applied easily by adding them to getter and setter methods.
+
+### Immutable Data
+The value of a variable can also be "frozen" with a **final** attribute or **record** type. Data marked with those variables is known to be entirely or partly **immutable**.
+
+The reference is not intended to be changed within the visibility scope of the variable. One aim is to prevent **the variable from being left uninitialized**. Additionally, using these modifiers prevents changing the reference both from outside and inside. This has a consequence: a **final** value can be more safely made visible.
+
+- Remember: only one "level of indirection" can be protected! This means that e.g. protecting an ArrayList by declaring it `final` still allows the addition, removal, and updating of items stored in the said ArrayList. As an additional side note this can still be useful, as it forces the variable to always reference to the same instance.
+
+Implementation of interface descriptions still requires a "getter method" (to be revisited later).
+
+```java
+
+class MyArray {
+    final int maxSize;
+    MyArray(int maxSize) { this.maxSize = maxSize; }
+    int getMaxSize() { return maxSize; }
+}
+```
+
+### Object Copying
+One other way to protect object is to just (deeply) copy it. Changes to the copy do not propagate to the original. When copying an object, make sure that you understand what actually is copied, and in which scenarios only a reference to the same object is copied!
+
+```java
+
+class MyArray {
+    final int[] data;
+    MyArray(int[] data) {
+        this.data = Arrays.copyOf(data, data.length);
+    }
+}
+
+void main() {
+    var array = new int[] { 1, 2, 3 };
+    var my = new MyArray(array);
+    System.out.println(Arrays.toString(my.data)); // 1, 2, 3
+    array[0] = 0;
+    System.out.println(Arrays.toString(my.data)); // 1, 2, 3
+}
+```
+## Wrapper Objects
+
+Behaves like the original, replaces methods that make changes with an empty implementation.
+
+```java
+
+public class MyInt {
+    private int value;
+    MyInt(int initial) { value = initial; }
+    int getValue() { return value; }
+    void setValue(int value) { this.value = value; }
+}
+```
+in the above class there is nothing special, only normal get and set. 
+
+By using a wrapper class, we can make an implementation of the class that behaves exactly as the previously mentioned `MyInt`, but is immutable, as `setValue` does nothing:
+
+```java
+public class ImmutableInt {
+    private MyInt my;
+    ImmutableInt(MyInt initial) { my = initial; }
+    int getValue() { return my.getValue(); }
+    void setValue(int value) { }
+}
+```
+
+Other option would be to leave out the setValue from the implementation of `ImmutableInt` entirely. Implementing with the setter method could be necessary, if e.g. the original would implement an *interface*, which would require the setter method.
+
+
+Now continue to:
+[Part 2.5 - Constructing Groups of Classes](Part%202.5%20-%20Constructing%20Groups%20of%20Classes.md)
\ No newline at end of file
diff --git a/Part 2.5 - Constructing Groups of Classes.md b/Part 2.5 - Constructing Groups of Classes.md
new file mode 100644
index 0000000..10d9b44
--- /dev/null
+++ b/Part 2.5 - Constructing Groups of Classes.md	
@@ -0,0 +1,126 @@
+
+# Constructing groups of classes
+
+Today's Topics:
+
+- Constructing groups of classes
+- Reflection on general advice
+
+## Motivational Example:
+Let's model a library management system that maintains information about books and library users. (Sharvit 2022)
+
+Our example includes:
+
+- Two types of library users: members & librarians.
+- Users can log in with an email and password.
+- Members can borrow books.
+- Both members and librarians can search for books by name or author.
+- Librarians can block members or remove a block (e.g., overdue book).
+- Librarians can list a member's current loans.
+- A library can have multiple copies of the same book.
+- Books belong to a physical library building.
+
+
+## Task:
+What kinds of classes, class attributes, and features can you think of? What about the relationships between classes?
+
+Next we are going to (lightly) inspect a set of different tools and techniques that aim to ease the design process.
+
+### Entities and Relations
+The entities and relations of the example could be presented in the following way:
+
+![](images/part-6/entities_and_relations.jpg)
+
+The black dimond (♦) means that element is constructed from smaller components. The diamond points to the parent/target class. In this case *Catalog* consists of many books. There can't be a catalog, if any Books are not present.
+
+The lighter (white) diamond represents that the class can use the element, but it does not necessarily contain an instance of it.
+
+The arrows show description of usage.
+
+
+
+### Traditional Object Model
+
+![](images/part-6/traditional_object_model.png)
+There are classes that are deeply interconnected. The model becames quite easily quite complex.
+
+### Data-Oriented View
+There is also data-oriented view. Notice how the arrows are going only to one direction.
+
+The relationships of data and the operations are presented separarately.
+
+![](images/part-6/data_driven_view.png)
+
+## Traditional Object Modeling
+
+The Object-Oriented Thought Process (Weisfeld 2013):
+
+*Rather than using a structured, or top-down, approach, where data and behavior are logically separate entities, the OO approach encapsulates the data and behavior into objects that interact with each other.*
+
+
+*The elegance of this mindset is that classes literally model real-world objects and how these objects interact with other real- world objects. These interactions occur in a way similar to the interactions between real-world objects, such as people. Thus, when creating classes, you should design them in a way that represents the true behavior of the object.*
+
+However, this approach can be a bit naïve, and will be revisited later in the course.
+
+## Data-Oriented View
+
+Data-oriented programming (Sharvit 2022):
+
+Data-oriented (DO) programming separates executable code from data. This separation makes the system easier to understand and more flexible. DO is against encapsulation.
+
+- Between classes containing methods, only UML's usage arrow is used.
+- Between data-containing classes, only UML's association (diamond) and composition (black diamond) are used.
+- Association = objects are independent.
+- Composition = an object's existence depends on another object.
+
+DO has advantages with code parallellization, synchronization, efficiency, and determinism. These are not the main themes of this course, but they are important aspects when trying to create robust and efficient programs.
+
+## Object-Oriented Software Construction
+We could also look at a bit older design principles presented in Object-Oriented Software Construction (1997):
+
+- Ideal class
+    - Clearly describes an abstraction.
+    - Name is a noun or adjective, describing the abstraction.
+    - Represents a set of possible objects or a single object.
+    - Methods for queries.
+    - Commands to change the state.
+    - Abstract properties (contracts).
+- Types of classes:
+    - Analysis class: directly from the task definition, describes an abstract or concrete concept.
+    - Design class: no direct counterpart in the modeled problem, facilitates implementation (e.g., iterator).
+    - Implementation class: frequently needed “lowest level” class, e.g., data structures.
+
+## Course Book
+Contract-based object programming in Java - chapter 4:
+
+- Bottom-up and top-down design.
+- A class is built around the information it's envisioned to contain.
+- Define the content of information, then the handling routines.
+- In a inheritance hierarchy, a feature is moved as high as it still fits into the whole.
+- In a client diagram, a feature should be placed in the "most primitive" client where it still has relevance. ("primitiveness": the implementation of class A is based on class B, whose implementation is based on class C – C is the most primitive)
+
+However, inheritance is not a problem free approach. Other possible approach in OO programming would be not to use top-down design, but use interfaces instead. Or one could use data-oriented programming.
+
+## Reflection on General Advice
+
+- Divide-and-conquer - solve the whole by identifying one class at a time?
+- How should data related to the (task) description be structured?
+    - It’s important that each class implements a clear/unified concept.
+    - Often, there is not just one correct solution.
+
+Designing a complex structure is never easy. However, experience helps to make good decisions. Additionally, utilizing design patterns can also prove to be helpful (however they are not the subject of this course).
+
+Furthermore, here are some other methods that have been explored in object-oriented programming:
+- **Cohesion metrics**: a cohesive class's parts extensively utilize each other.
+    - E.g., methods extensively use the class's instance variables.
+    - Aim for a high value of cohesion.
+- For a groups of classes, corresponding can be measured with **coupling metrics**.
+    - Aim for a low value – few mutual dependencies.
+    - Classes are interpreted to implement separate concepts.
+    - The nature of coupling (e.g., method reference) varies in these metrics (multiple interpretations).
+
+
+As you have probably realized by now, there is no silver bullet nor a one size fits all solution! This is also reflected on some of this course's exercises and in programming in general, as the same problem can often be solved in multiple different ways.
+
+Now continue to:
+[Part 2.6 - Creating a Class](Part%202.6%20-%20Creating%20a%20Class.md)
\ No newline at end of file
diff --git a/Part 2.6 - Creating a Class.md b/Part 2.6 - Creating a Class.md
new file mode 100644
index 0000000..6c4fb10
--- /dev/null
+++ b/Part 2.6 - Creating a Class.md	
@@ -0,0 +1,497 @@
+# Creating a class
+
+Now we're moving finally to emphasize the object oriented programming. 
+
+Today's topics include:
+
+- Constructing a group of classes
+- Defining a class
+- Defining a group of a classes
+- Examples
+    - Rational numbers
+    - Sequence
+    - Binary tree
+    - Phone & phone directory
+
+## Constructing a group of classes
+
+There is no one "true" way to define a class. However here is some advice for class design:
+
+- A class should implement one and only **one** concept, akin to a routine: "one clear purpose, **represents** some **functional concept**". In different contexts, it might mean something substantially different, e.g., a car in a car dealership vs. an autonomously driving car in traffic (in these cases, the key features are quite different).
+- You might also remember from previous lectures, that one option is to use the data-oriented model. In this case it would keep the car data & car functionality separate. This and more traditional object oriented programming could both be used to convey the same meaning/functionality, although both methods have different strengths and weaknesses. "Best" method often depends on the use-case.
+
+One should aim for general use/reusability, but not at any cost. Information can be structurally compiled, i.e., the internal implementation may rely on other classes that model part of the information (divide-and-conquer). The reusability can be achieved, e.g. using polymorphism, generic classes (e.g. `class Solution<T>`) or by structuring a group of classes (e.g. data-oriented model).
+
+- A class is built around data. A good question that should be asked is: What parts of the data to be modeled are closely related? Additionally, much depends on the intended use, i.e., the context of the planned class.
+
+## Class Structuring from Context Description:
+
+One way to structure a class us using a context description. This means that classes can be build when we are characterizing things (e.g., from created user story).
+
+**Nouns** are often good candidates for classes. Are there multiple instances, or is it a proper noun? Then, the noun is more likely an object of the class, e.g., Turku, class City.
+
+**Verbs** could represent actions. This makes them often good candidates for methods.
+
+**Adjectives** represent values. Generalization by grouping similar adjectives can function as a class, e.g., yellow, red → class (in this case enum) Color.
+
+These are not strictly defined guidelines, the line is drawn on the sand, e.g. a verb could also be a class name in some cases. You should also consider the structure based on multiple different angles e.g. performance, maintainability, extensibility etc.
+
+An example of a class structure:
+![](images/part-7/example_of_class_structure.PNG)
+
+## Classifying Classes: A Scientific Response
+
+There are various kinds metrics, or goodness measures been sought for OO (Object-Oriented) languages' classes. Each aims to serve as a design guideline. One could say that the basic idea behind the metrics is to present design as a group of numeric values, which present e.g. the structure's quality. Analytics are a good tool, but they might not reveal all possible benefits or problems of a design. Always check the potential up- and downsides of a particular tool/method before using it!
+
+Perhaps the most famous are the so-called cohesion metrics e.g. LCOM = Lack of Cohesion of Methods. LCOM1, LCOM2, LCOM3, LCOM4, TCC, LCC, LCIC, …
+
+The rough idea is that methods should extensively use the same instance variables (and/or other methods within the same class). For example, if the class's instance variables are divided into sets A and B, and the methods into sets AA and BB.
+
+Cohesion is poor if AA's (BB's) methods use only A's (B's) variables – then two different concepts are artificially tied together Unfortunately, the value of metrics often depends on the way the internal implementation is done – this should not be the case!
+
+## To Buy or to Inherit?
+
+Through inheritance, not only data structures but also functional implementations can be inherited. For example, through a client relationship (where class A's implementation uses class B), data structures and functional implementations can also be utilized.
+
+There seems to be no indisputable universal criterion to determine whether there should be an inheritance or a client relationship between classes A and B.
+
+Ownership (has-a) is rarely being (is-a). Has-a is a client relationship, where being is inheritance. Being is often also owning. Often the choice of relationship depends on the perspective and emphasis (things related to the intended use). Some good questions are:
+- Are (nearly) all features of A also features of B?
+- Are (nearly) all features needed? (Do they also play a significant role in B's entire essence?)
+
+## Stages of Class Formation
+One way to format a class would be to do it in these phases:
+
+1. **Mapping of Features**: What constructors, observation (e.g. getters), and modification (e.g. setters) routines the class should have?
+2. **Specification of operations**: Define the signature, description, and pre and post conditions of each routine. Define a public class invariant.
+3. **Determining the Public Interface**: Is the resulting class's public interface valid for both the class's client and its implementer?
+4. **Choice of Concrete Representation**: How is the stored information in the class presented? When the class variables has been selected, the next question on concrete implementation is to decide the type of the variables. 
+
+- As a quick refreshner: A class invariant is an invariant (boolean argument statement). If the program functions as intended, the invariants should always be true. For example, a class that would contain only positive numbers (and  zero) and would exclude all negative numbers. A class invariant holds true to all methods and properties of the said class. If the class invariant is not defined, this could cause problems due to e.g. inheritance. So even though this is not enforced through the code, this still should improve communication and make communication between developers more efficient.
+
+5. **Data Management in the Chosen Representation**: Define a private class invariant and abstraction function for the class.
+6. **Implementation-Related Decisions**: What is the class's implementation like (execution)?
+7. **Generalization**: Is the class generalizing, or is its use limited to just one client? (e.g., 1:1 or 1:M relation, generic types)
+
+Of course one could choose to do this more iteratively.
+
+
+## Steps in Forming a Class Group
+
+1. **Sketch the necessary classes and class structures.**
+
+- The course provides the tools for an initial conceptualization of class groups. Design patterns and architectures help conceptualize broader structures, but they mostly exceed the scope of this course.
+
+2. **Map out the necessary features in the classes.**
+
+- Constructors and getters and modification operations (and possible exceptions).
+- Consider definitions from both the client's and the implementer's perspectives.
+
+3. **Write definitions for the operations.**
+
+- Initial and final conditions
+- Class invariants, abstraction functions, …
+
+4. **Prepare implementations for the defined classes and test them**. 
+
+- Or should the tests be written first? (e.g. TDD)
+
+The development process can also be more or less iterative. (from the described stages, it might appear that the problem is fully known in advance)
+
+# Examples
+
+Next, lets look at some examples.
+
+## Example: rational numbers
+We briefly mentioned a possible use case as using non-negative (rational) numbers. Let's look it more closely next.
+
+- We are programming a system that requires rational numbers. A rational number is a real number that can be expressed as a quotient of two integers: p/q. The number 𝑝 is called the numerator, and 𝑞 the denominator.
+- Choose a quotient representation as the structure for implementing the class **RationalNumber**, meaning each instance of the class has **int** member variables for numerator and denominator. In this case, it would be good to check how a rational number is defined in mathematics. 
+
+Furthermore, one could think that the implemenation of this could be quite straightforward due to the fact that the implemented concept is a matter of quite simple arithmetics. However, this is not the case, as there are differences in the implementation of numbers in the programming languages.
+
+ In the example case mentioned above, the following things would need to be considered:
+
+1. Can the denominator be zero? If so, what does that mean?
+- No it cant, it could be defined e.g. in the class invariant.
+2. How is a negative number represented? Are *-1/2* and *1/-2*
+   valid?
+- If both are valid, the implementation should check both numbers. 
+
+3. Is the number presented in reduced form? Are *6/8* and *3/4* equivalent?
+- Additionally, the implementation needs to solve the problem of how to check the equivalence of the similar values with different numeric values. How the exceeding of max int value (overflow) should be handled? It's also a possible (and quite common) source of a security risk!
+
+4. How is zero represented? For example, are *0/1* and *0/2* valid?
+- In java, for example, float or double  zero can be either *+0* or *-0*. This could be problematic e.g. when a comparison between two different zero values is being done.
+
+
+As an additional side note: implementing this kind of concept can be useful in a real-life use scenarions, e.g. for a learning platform (for example, ViLLE).
+
+A example of a possible implementation (the class invariant and abstraction function for this class):
+
+```java
+class RationalNumber {
+    // abstraction function, the abstract ideas in this case are presented as class variables p and q.
+    // 'p' is the numerator of the rational number && 'q' is the denominator
+    private int p, q;
+
+
+    int numerator() { return p; }
+    int denominator() { return q; }
+    @classInvariantPrivate p >= 0 && q != 0 // This is a little bit different from our original implementation idea (p) but this is also fine.
+    @classInvariant numerator() >= 0 && denominator() != 0
+    ...
+}
+```
+In the above example, we have two different class invariants. First is for the integrity of the class itself, and the second one defines the rules for the public interface (in this case the getter methods). In this case these could also be combined, as the definitions do not differ from each other. Specification on this level could be beneficial e.g. when defining the *date* or *time* related classes (hours, holidays, leap days etc.). 
+
+## Another example: Queue
+
+A queue is a FIFO (first-in, first-out) data structure, which means the elements added earlier to the queue are removed first. A queue supports the following operations: adding an element to the end of the queue, querying the first element of the queue, and removing the first element of the queue.
+
+Design the implementation of the **Queue** class: public interface (definition of operations), concrete representation, and (public) class invariant.
+
+An example of a queue:
+
+![](images/part-7/Queue.PNG)
+
+Now let's start by defining the features of the class (step 2).
+
+Class: **Queue**
+Initially, the queue is empty (constructor)
+`first()` - query the first element
+`add()` - add element
+`remove()` - remove element
+
+The following are also useful and are fulfilled from the implementation (iteration #2):
+`size()` - number of elements
+`isEmpty()` - does it contain elements
+`isFull()` - can more elements still fit into the queue
+
+Now, let's start the third phase, 3. Writing specifications for operations
+
+```java
+// Queue: a collection of elements,
+// that follows the FIFO principle.
+class Queue {
+    // Constructs an empty queue
+    //
+    // @.pre true
+    // @.post (queue constructed)
+    Queue()
+    // First element of the queue.
+    //
+    // @.pre !isEmpty()
+    // @.post RESULT==(the 1st element of the queue)
+    Object first();
+```
+As the instance of a Queue class does not have any preconditions, it can be formed anywhere and the preconditions are set as true. On the post we do not have any good notation, so the paraphasing it is sufficient.
+
+```java
+ // Adds an element to the end of the queue.
+    //
+    // @.pre !isFull()
+    // @.post !isEmpty() &&
+    // size() == OLD(size()) + 1
+    // && ('e' added to the queue)
+    void add(Object e);
+    // Removes the first element of the queue.
+    //
+    // @.pre !isEmpty()
+    // @.post !isFull() &&
+    // size() == OLD(size()) - 1
+    // && (1st element removed)
+    void remove()
+```
+Naturally, adding an element to to a queue (`add(Object e)`) requires that the queue is not full and after adding a element the queue is not empty. Additional note: OLD is a conceptual example, not an actual implemenation from Java.
+
+On the `remove()`, the queue should not be empty when remove is called. Additional question to think about: in practice, would this be a good implementation? Additionally, one could argue that the `remove` should implement also the `first` so that the user can e.g. show details of a deleted element.
+
+```java
+// @.pre true
+// @.post RESULT ==
+// (number of elements in the queue)
+int size();
+// Does the queue contain elements?
+//
+// @.pre true
+// @.post RESULT == (size() == 0)
+boolean isEmpty();
+```
+
+```java
+// Is the queue full?
+// (implementation-specific maximum size)
+//
+// @.pre true
+// @.post RESULT ==
+// (no more space in the queue)
+boolean isFull();
+
+// class invariant
+@classInvariant
+size() >= 0 &&
+!(isEmpty() && isFull())
+```
+
+In this case the class invariant is a little bit redundant, as all of the conditions are restrained in the method implementations, but the class invariant say's general conditions that are (or at least should be true) in all cases.
+
+
+
+Now, lets look at a possible implementation (step 4):
+
+```java
+class Queue {
+    public static final int MAX_SIZE = 100;
+    private Object[] storage = new Object[MAX_SIZE];
+    private int idx = 0;
+    // public Queue() {}
+    public Object first() { return storage[idx - 1]; }
+    public void add(Object e) { storage[idx++] = e; }
+    public void remove() { idx--; }
+    public int size() { return idx; }
+    public boolean isEmpty() { return size() == 0; }
+    public boolean isFull() { return size() == MAX_SIZE; }
+}
+```
+
+The feature of queue-like behavior could also be isolated into an interface class:
+
+```java
+interface QueueLike {
+    Object first();
+    void add(Object e);
+    void remove();
+    int size();
+    default boolean isEmpty() { return size() == 0; }
+}
+```
+Notice how we left out the `isFull` to allow dynamic queue like structures? Additionally, notice how Java supports also defining the isEmpty that relies on the `size` method?
+
+#### Binary Tree
+
+A binary tree consists of a **header**, which represents the tree from the client's perspective, and **nodes** that form the actual structure of the tree. The **header** is aware of the tree's **root node**. Nodes can have a maximum of two **child nodes**, and each node also knows its **parent(s)**.
+Let's start out by sketching some class and object diagrams. Let's also draw a diagram showing the relationships between classes.
+
+  ![](images/part-7/Binary_tree.PNG)
+
+
+A more concrete example: a binary tree of numbers. The elements of the tree are arranged according to a specific tree traversal order.
+
+![](images/part-7/binary_tree_2.PNG)
+
+Now, let's visualize the possible connection(s) between the classes.
+
+Below are two possible options:
+
+![](images/part-7/nodes.PNG)
+
+The definition could also be done without using a *Tree* class, however it would mean that an empty tree (tree without any Node objects) would probably be referenced as a *null* instead of empty *Tree* object. This could cause problems in some use-cases. For example, if we would want to a option to also create an empty *Tree* object and differentiate it from a null value.
+
+Implementation of the left one:
+
+```java
+class BinaryTree
+{
+Node root;
+...
+}
+class Node
+{
+Data value;
+Node parent;
+Node leftChild;
+Node rightChild;
+// ... more code
+}
+```
+
+The right one implemented:
+
+```java
+interface Node
+{
+Node parent()
+Data value;
+}
+class BinaryTree
+{
+Node root;
+}
+class Leaf implements Node
+{
+...
+}
+class InnerNode implements Node
+{
+Node leftChild;
+Node rightChild;
+// ... More code
+}
+```
+
+## Phonebook
+
+Now let's inspect a little bit more complex example, a phonebook.
+
+Description:
+
+Market research has revealed that a large group of consumers would like a mobile phone with the simplest possible features. In addition to phone functions (making and answering calls), the mobile phone should only include a phonebook. You have been given the opportunity of a lifetime to design the software for this brand-new phone.Specifically, you are asked to sketch out the necessary classes and class structure (i.e., the relationships between classes).
+
+
+Unfortunately, implementing the phone requires a lot of additional information about the hardware implementation. Instead we will be focusing on contacts and the phonebook. We'll keep the solution as simple.
+
+```java
+abstract class Phone {
+    final Phonebook = new Phonebook();
+    abstract void call(long number);
+    abstract void call(Contact contact);
+    abstract void answer();
+}
+class Phonebook {
+    ...
+}
+class Contact {
+    ...
+}
+```
+
+## Example: Contact Class
+
+We identify a class **Contact** for storing contact information.
+Let's consider the necessary features of the class:
+
+- The record is practically a name-phone number pair.
+- We want to create records based on name and phone number.
+- We want to observe the information of the created record.
+- ~~We want to modify the information of the created record.~~
+
+We decide to implement contact information as an immutable data structure. Updating contact details requires replacing the entire contact. However, implementing the contact is now easier.
+
+```java
+interface ContactLike {
+    @classInvariant name() != null && number > 0 &&
+    (""+Long.valueOf(number())).length() > 2
+    // observation operations
+    // @.pre true
+    // @.post RESULT == (name / number)
+    String name();
+    long number();
+}
+// @.pre name != null && number > 0 &&
+// (""+Long.valueOf(number)).length() > 2
+// @.post (contact created)
+record Contact(String name, long number) implements ContactLike {}
+
+```
+
+Example: Examining the Formation of Contact Class
+
+1. Mapping features:
+
+- Creation of record and field queries.
+
+2. Definition of operations:
+
+- Described in the interface description.
+
+3. Fixing the public interface:
+   Yes.
+
+4. Choosing a concrete representation:
+
+- Pair: *String* and *long*.
+- number = E.164 without the plus (International standard)
+
+5. Managing data in the chosen representation:
+   Straightforward (name = contact name,
+   number = contact number).
+
+6. Decisions related to implementation:
+
+- Java's *record*.
+
+7. Generalization:
+
+- Possible other users.
+
+## Example: Phonebook Class
+
+Let's sketch out the following features for the class:
+
+```java
+interface PhonebookLike {
+    // observation operations (e.g. getters)
+    Contact[] getContacts(); // all contacts
+    int size(); // number of contacts
+    Contact[] getContacts(String name); // individual's contacts
+    int matchingContacts(String name); // count of an individual's contacts
+    boolean contains(String name); // contains the individual
+    boolean contains(Contact contact); // contains the contact
+    
+    // modification operations
+    PhonebookLike add(Contact contact); // add a contact
+    PhonebookLike remove(Contact contact); // remove a contact
+    PhonebookLike remove(String name); // remove an individual's contacts
+    // @.classInvariant size() >= 0
+}
+```
+
+Defining the specifications: 
+
+```java
+interface PhonebookLike {
+    // @.pre true
+    // @.post RESULT == (all contacts)
+    Contact[] getContacts();
+    // @.pre true
+    // @.post RESULT == getContacts().length
+    default int size() { return getContacts().length; }
+    // @.pre name != null
+    // @.post FORALL(c: RESULT; contains(c) && c.name().equals(name))
+    Contact[] getContacts(String name);
+    // @.pre name != null
+    // @.post RESULT == getContacts(name).length
+    default int matchingContacts(String name) { return getContacts(name).length; }
+    // @.pre name != null
+    // @.post RESULT == EXISTS(c: getContacts(); c.name().equals(name))
+    boolean contains(String name);
+
+    // @.pre contact != null
+    // @.post contains(contact) && RESULT.remove(contact).equals(OLD(this))
+    PhonebookLike add(Contact contact);
+    // @.pre contact != null && contains(contact)
+    // @.post !contains(contact) && RESULT.add(contact).equals(OLD(this))
+    PhonebookLike remove(Contact contact);
+    // @.pre name != null && contains(name)
+    // @.post !contains(name) && RESULT.add(OLD(this).getContacts(name)).equals(OLD(this))
+    PhonebookLike remove(String name);
+    // @.classInvariant size() >= 0
+}
+```
+
+Now let's look little bit of the implementation:
+
+
+Contact: String, Int tuple
+
+class Phonebook:
+- Contact[] array
+- List\<Contact> list
+   - ArrayList\<Contact>
+   - LinkedList\<Contact>
+   - Search tree, hash table, ...
+   - and possible helper methods
+
+```java
+class Phonebook implements PhonebookLike {
+private final List<Contact> contacts = new ArrayList<>();
+// ... 
+}
+```
+
+As an additional exercise, you may try now implementing the phonebook class fully.
+
+One additional benefit in using interfaces is that it reduces the need to manually write code, as the method signature's etc. can be automatically generated/copied with modern IDE's.
+
+Now do the exercises of the Part 2 in ViLLE.
\ No newline at end of file
-- 
GitLab