Skip to content

Commit

Permalink
!fixup: topics: add software concepts topic
Browse files Browse the repository at this point in the history
  • Loading branch information
BacLuc committed Feb 27, 2024
1 parent 9f43b70 commit 79a26a2
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 59 deletions.
22 changes: 8 additions & 14 deletions topics/sw_concepts/sw_concept_code_examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def test_parses_brightness_correctly(self):
BrightnessParserTest Auswertung
-------

1. DRY...: "0000005a" könnte geteilt und benamst werden
1. DRY...: "0000005a" könnte geteilt und benannt werden
2. SOLID: -
3. Pattern: -
4. Verbesserung: -
Expand Down Expand Up @@ -168,7 +168,7 @@ public class TransactionObserverTest {
TransactionRepository Auswertung
-------

1. DRY...: KISS: 1 Mock kann auch einfach mit einer Klasse erreicht werden
1. DRY...: KISS: Ein Mock kann auch einfach mit einer Klasse umgesetzt werden
2. SOLID: Dependency Inversion
3. Pattern: -
4. Verbesserung: -
Expand All @@ -180,26 +180,20 @@ CreditCardAppIdMapperProvider
public class CreditCardAppIdMapperProvider implements Provider<CreditCardAppIdMapper> {
private final CreditCardAppIdMapper creditCardAppIdMapper;

@Inject
public CreditCardAppIdMapperProvider(CreditCardAppIdMappingConfiguration configuration,
CreditCardAppIdCategoryMappingParser creditCardAppIdCategoryMappingParser) {
if (configuration.isEnabled()) {
List<MappingEntry> mappingEntries = creditCardAppIdCategoryMappingParser.parse(new File(configuration.getMappingFilePath()));
Map<CreditCardAppIdMapper.CardAppIdCategory, String> map = new HashMap<>();
mappingEntries.forEach(mappingEntry -> {
CreditCardAppIdMapper.CardAppIdCategory keyToAdd = new CreditCardAppIdMapper.CardAppIdCategory(mappingEntry.getAppIdCategory());
map.put(keyToAdd, mappingEntry.getLabel());
});
creditCardAppIdMapper = new CreditCardAppIdMapper(map);
creditCardAppIdMapper = new CreditCardAppIdMapper(createMap(mappingEntries));
} else {
creditCardAppIdMapper = new CreditCardAppIdMapper(new HashMap<>());
}
}

@Override
public CreditCardAppIdMapper get() {
return creditCardAppIdMapper;
}
//...
}
```

Expand Down Expand Up @@ -237,7 +231,7 @@ Board Auswertung
1. DRY...: -
2. SOLID: -
3. Pattern: Observer
4. Verbesserung: Keine Möglichkeit um Observer zu entfernen -> Memory Leak
4. Verbesserung: Keine Möglichkeit um Observer zu entfernen $\rightarrow$ Memory Leak

Board2
-------
Expand Down Expand Up @@ -309,7 +303,7 @@ DoorEventHandler Auswertung
2. SOLID: -
3. Pattern: Observer
4. Verbesserung:
1. Liste der Observer muss je nach dem Threadsafe sein
1. Liste der Observer muss je nach Bedarf Threadsafe sein
2. Keine Möglichkeit Observer zu entfernen -> Memory Leak

ButtonFactory
Expand Down Expand Up @@ -340,7 +334,7 @@ ButtonFactory Auswertung
2. SOLID: -
3. Pattern: AbstractFactory
4. Verbesserung: Inheritance hat in diesem Fall zu Problemen geführt.
da man nicht Voraussagen kann, wo welche Buttons gebraucht werden,
Da man nicht Voraussagen kann, wo welche Buttons gebraucht werden,
bietet sich hier Composition + Interface besser an.

ReceiptFactory
Expand Down Expand Up @@ -402,7 +396,7 @@ class SubstopNetpointIdStrategy(OperatingPointNumberResolveStrategy):
OperatingPoint Auswertung
-------

1. DRY...: KISS: Hätte auch ein IF statement gereicht?
1. DRY...: KISS: Hätte auch ein IF Statement gereicht?
2. SOLID: -
3. Pattern: Strategy
4. Verbesserung: -
126 changes: 81 additions & 45 deletions topics/sw_concepts/sw_concept_slides.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ abstractions.py Zusammenfassung
Abstraktion: Nachteile
-------

* erhöht Komplexität
* Erhöht Komplexität
* Änderung der Abstraktion haben Auswirkungen auf alle User
* Die Abstraktion am falschen Ort (Vertikal)
* Die Abstraktion versteckt wichtige Features
Expand All @@ -40,12 +40,12 @@ private void setContactlessLogo(String imagePath) {
if (imagePath == null || getAcceptance() != ACCEPTED) {
final String imageFileName = getImageFileName()
final String imageUrl = IMAGES_PATH + imageFileName;
vibbekLogo.setImage(new Image(imageUrl));
contactlessLogo.setImage(new Image(imageUrl));
} else {
if (contactlessPMod.isCarouselEnabled()) {
vibbekLogo.setImage(new Image(imagePath));
contactlessLogo.setImage(new Image(imagePath));
} else {
vibbekLogo.setImage(new Image(IMAGES_PATH + "static_carousel.png"));
contactlessLogo.setImage(new Image(IMAGES_PATH + "static_carousel.png"));
}
}
}
Expand All @@ -63,10 +63,13 @@ DRY

* **D**on't **R**epeat **Y**ourself
* Für **Verhalten** aber auch für **Information**
* Was wäre cool, wenn es sich bei allen Copy-and-paste Orten ändern würde
* Gibt dem Extrahierten auch einen Namen
* Idee: Wenn man Verhalten oder Information ändern muss,
dann kann man das an einer Stelle tun.\
Sonst müssen alle Kopien angepasst werden.
* Der Name der extrahierten Methode (z.b. für Verhalten)
oder Konstante (z.b. für Information) sollte den Inhalt beschreiben.

DRY Beispiel für Konstanten
DRY Beispiel für Konstanten 1
------

```java
Expand All @@ -76,22 +79,50 @@ assertEquals(new Long(2), view.getServicePeriodSerialId());
assertEquals("RGS_EMPTYING_TO_RETURNTRAY", view.getServiceType());
```

DRY Beispiel für Konstanten 2
------

```java
assertEquals(SERVICE_START_DATE, view.getServiceStartDate());
assertEquals(SERVICE_SERIAL_ID, view.getServiceSerialId());
assertEquals(SERVICE_PERIOD_SERIAL_ID, view.getServicePeriodSerialId());
assertEquals(ServiceType.RGS_EMPTYING_TO_RETURNTRAY, view.getServiceType());
```

KISS
-------

* **K**eep **i**t **S**hort and **S**imple\
(Keep it simple stupid)

```python
# num % (modulo) 2 with a bitwise operator:
num & 1
# it is simpler and more readable
# to use the % operator.
num % 2
```

Erklärung Modulo 2 mit Bit operator
-------

```md
5 = 00000101 &
1 = 00000001
--------------
00000001 -> ungerade
```

YAGNI
-------

* **Y**ou **a**n't **g**onna **n**eed **i**t
* **Y**ou **a**ren't **g**onna **n**eed **i**t

NIH
-------

* **N**ot **i**nvented **h**ere
* Dinge selbst implementieren, die schon in der Sprache/in einer Library sind.
* Dinge nicht selber implementieren, die schon in der Sprache oder einer Library enthalten sind.

NIH Beispiel 1
-------
Expand All @@ -103,16 +134,16 @@ Clean Code

* **S**ingle Responsibility
* **O**pen Closed Principle
* **L**iskov's Substition Principle
* **L**iskov's Substitution Principle
* **I**nterface Segregation
* **D**ependency Inversion

Single Responsibility
-------

* Eine Funktion, Klasse, Modul sollte nur eine "Responsibility" haben.
* Grenze ist nicht ganz klar
* Indikator: wenn bei der benennung ein "and" vorkommt, dann sollte man aufteilen.
* Grenze ist nicht ganz klar.
* Indikator: Wenn bei der Bezeichnung ein "and" vorkommt, dann sollte man aufteilen.
* Andere Sichtweise: Eine Funktion, Klasse, Modul sollte nur einen Grund haben, sich zu ändern.

Beispiel Single Responsibility verletzt
Expand Down Expand Up @@ -140,16 +171,18 @@ Beispiel Single Responsibility verletzt mit Kommentar

```java
// Werte in unabhängige Felder packen
// Hier sind zwei eher unabhängige Zustände (Richtung 1/2, Razzia)
// in einem Feld abgebildet.
public enum DirectionAndRazziaValue {
DIRECTION_1,
DIRECTION_2,
RAZZIA
}

// 2 Concerns trennen
// Trennen der zwei Aufgaben
private static void updateCountersAndLogEjectedCoins(...)

// in 2 methoden aufteilen: es ist ja schon ein Builder
// in zwei Methoden aufteilen: es ist ja schon ein Builder
public SessionFactoryBuilder withUserAndPassword(String username, String password) {
this.username = username;
this.password = password;
Expand All @@ -161,21 +194,23 @@ public SessionFactoryBuilder withUserAndPassword(String username, String passwor
Open Closed
-------

* "Open for extension, closed for change"
* Neue Funktionalität -> nicht bestehenden code anpassen, sondern möglichst nur code hinzufügen
* "Open for extension, closed for modification"
* Für neue Funktionalität
* Bestehenden Code nicht anpassen
* Möglichst nur neuen Code hinzufügen

Open Closed Beispiel
-------

Regeln für Dame:

* Eigenen Spielstein bewegen
* Ziel Feld muss leer sein
* Bauer darf sich 1 weit Feld bewegen, der König 2
* Bauer darf nur vorwärts
* Bewegung muss diagonal sein
* Beim Springen muss gegnerische Figur dazwischen sein
* Falls man springen kann, muss man springen
* Eigenen Spielstein bewegen.
* Ziel-Feld muss leer sein.
* Bauer darf sich ein Feld weit bewegen, der König zwei Felder.
* Bauer darf sich nur vorwärts bewegen.
* Bewegung muss diagonal sein.
* Beim Springen muss gegnerische Figur übersprungen werden.
* Falls man springen kann, muss man springen.

<https://github.com/soco21/soco21-group8/blob/f4c0f734f759465c32a6a444ce8fa9656dacd6ec/assignment-1/exercise2/Class%20Diagramm%20Checkers.svg>

Expand All @@ -186,50 +221,50 @@ Wenn alle Regeln in separaten Klassen sind, macht das den Inhalt klarer.
Auch ist es jetzt einfacher, neue Regeln hinzuzufügen.
<https://github.com/soco21/soco21-group8/tree/fb763220b26d3ed0260580d944b92fe9172f6c7b/assignment-1/exercise3/src/main/java/ch/uzh/group8/assignment1/exercise3/movevalidator>

```python
class StartPieceValid:
class TargetFieldEmpty:
class MoveLength:
class MoveIsForwardIfNotKing:
class MoveIsDiagonal:
class OpponentPieceBetweenJump:
class NoOtherJumpMovePossible:
```java
class StartPieceValid {}
class TargetFieldEmpty {}
class MoveLength {}
class MoveIsForwardIfNotKing {}
class MoveIsDiagonal {}
class OpponentPieceBetweenJump {}
class NoOtherJumpMovePossible {}
```

Open Closed Beispiel 3
-------

Und es ermöglicht composition:
Und es ermöglicht Komposition:

```python
moveValidators = [
```java
moveValidators = List.of(
startPieceValid,
targetFieldEmpty,
moveLength,
moveIsForwardIfNotKing,
moveIsDiagonal,
opponentPieceBetweenJump,
noOtherMoveToJumpPossible
]
winCondition = new WinCondition([
);
winCondition = new WinCondition(List.of(
startPieceValid,
targetFieldEmpty,
moveLength,
moveIsForwardIfNotKing,
moveIsDiagonal,
opponentPieceBetweenJump
])
));
```

Liskovs substitution principle
Liskov's substitution principle
-------

* Implementationen eines Interfaces müssen ausgetauscht werden können.
* Sie nehmen mindestens die gleichen Input werte an (dürfen auch mehr).
* Sie nehmen mindestens die gleichen Inputwerte an (dürfen auch mehr).
* Sie geben maximal die gleichen Rückgabewerte zurück.
* Werfen maximal die gleichen Exceptions (oder Subtypen der Exceptions).

Beispiel Liskovs substitution principle Verletzung
Beispiel einer Verletzung des Liskov's substitution principle
-------

```python
Expand Down Expand Up @@ -258,8 +293,9 @@ Interface Segregation

* Um die Kopplung zu reduzieren, kann man auch Interfaces aufteilen.
* Eine Klasse kann mehrere Interfaces implementieren
* Man will mit einer Klasse nicht benötigte Methoden nicht implementieren
* Man will nicht, dass jemand plötzlich eine Methode nutzt, die man gar nicht zur Verfügung stellen wollte.
* Man will in einer Klasse nicht benötigte Methoden nicht implementieren
* Man möchte vermeiden, dass jemand unerwartet eine Methode verwendet,
die eigentlich nicht zur Verfügung gestellt werden sollte.

Interface Segregation Example
------
Expand All @@ -269,8 +305,8 @@ Interface Segregation Example
Dependency Inversion
------

* Um 2 Klassen zu entkoppeln kann ein Interface dazwischen geschalten werden.
* Das verhindert, dass eine High Level Komponente von einer Low Level Komponente abhängt.
* Um zwei Klassen zu entkoppeln, kann ein Interface verwendet werden.
* Das verhindert, dass eine High-Level-Komponente von einer Low-Level-Komponente abhängt.

Dependency Inversion Beispiel 1
-----
Expand Down Expand Up @@ -428,7 +464,7 @@ Zusammenfassung
* SOLID Principles
* Single Responsibility Principle
* Open Closed Principle
* Liskov's Substition Principle
* Liskov's Substitution Principle
* Interface Segregation Principle
* Depdendency Inversion Principle
* Design Patterns
Expand Down

0 comments on commit 79a26a2

Please sign in to comment.