all repos — notes @ 1ea29adc0d0adc439e37244055e2109c95e45e28

Unnamed repository; edit this file 'description' to name the repository.

uni/Praktikum/Praktikumsbericht.typ (view raw)

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
#import "@preview/meander:0.4.1"

#set text(
  size: 12pt,
)

#set par(
  justify: true,
  leading: 12pt,
)

#set page(
  paper: "a4",
  margin: (x: 1.5in, y: 1.25in),
)

#set page(numbering: "1")
#set heading(numbering: "1.")

#show heading: set block(below: 1.5em)
#show title: set text(size: 24pt)

#align(center)[
  #title[Praktikumsbericht WS 25/26]
  Fraunhofer-Institut für Arbeitswirtschaft und
  Organisation IAO\
  H. Harengel
]

\
#outline()
#pagebreak()

= Stellenbeschreibung
Bei dieser Stelle beim Fraunhofer-Institut für Arbeitswirtschaft und Organisation handelt es sich um ein Praktikum im Bereich der Softwareentwicklung, spezifisch für die Entwicklung von beidem Front- und Backend.
Die Stelle war für dieses Anwendungszentrum ausgeschrieben, an dem an Forschungslösungen für verschiedene Bereiche gearbeitet wird und ist eine typische Praktikumsstelle welche auf 6 Monate begrenzt ist und 40 Arbeitsstunden die Woche voraussetzt.
Das Anwendungszentrum KEIM des Fraunhofer IAOs fokussiert sich dabei auf Forschungsprojekte zu den Themen Elektromobilität, Energie und IoT.

\
Die Art der Arbeit setzte es voraus das nicht nur eine theoretische Herangehensweise sondern direkt an einer fertigen Softwarelösung mitgearbeitet werden sollte.
Konkret handelte es sich um eine laufende Entwicklung verschiedener Softwarelösungen im Forschungsumfeld der Mikromobilität und Flottenmanagement, bei welcher sowohl die Gestaltung als auch die technische Umsetzung zu den Aufgaben zählten.
Die zu erledigenden Tätigkeiten umfassten dabei die Visualisierung von Daten, die Erweiterung vorhandener Algorithmen sowie die prototypische Implementierung neuer Ansätze. Dieser Praxisbezug zur Programmierung hat mich überzeugt beim KEIM des Fraunhofer IAOs mein Praktikum zu machen.

\
Gesucht wurde nach Personen welche ein Interesse an Technik, modernen Technologien und Innovationen haben und eventuell bereits Erfahrung in den Technologien TypeScript, JavaScript, Python und React mit sich bringen konnten. Das Arbeitsumfeld wurde als jung und interdisziplinär beschrieben, mit flexiblen Arbeitszeiten und dem Einsatz aktueller Technologien im Bereich der Softwareentwicklung.

\
Besonders angesprochen hat mich an der Ausschreibung die Kombination aus einem wissenschaftlichen Umfeld und einer gleichzeitig sehr anwendungsnahen Tätigkeit. Anders als in vielen anderen Praktikumsstellen im Bereich Softwareentwicklung wurde hier nicht nur der Wunsch nach vorhandenen Kenntnissen formuliert, sondern explizit auf die Möglichkeit hingewiesen, neue Technologien im Arbeitsalltag kennenzulernen und anzuwenden. Das hat mir das Gefühl gegeben, dass das Praktikum tatsächlich einen Lerncharakter haben würde und nicht nur darauf ausgerichtet ist, einfache Aufgaben abzuarbeiten oder bestehende Systeme zu warten ohne tieferes Verständnis davon aufzubauen.

\
Hinzu kam das Themenfeld selbst: Mikromobilität und Flottenmanagement sind Bereiche, die aktuell eine hohe Relevanz im städtischen Kontext haben und in denen sich technologische und gesellschaftliche Fragestellungen auf interessante Weise überschneiden. Städte stehen zunehmend unter dem Druck, ihre Mobilitätsinfrastruktur nachhaltiger und effizienter zu gestalten, und softwaregestützte Ansätze zur Optimierung von Fahrzeugflotten spielen dabei eine wachsende Rolle. Die Aussicht, an Softwarelösungen zu arbeiten, die in diesem Kontext eingesetzt werden, war für mich ein zusätzlicher Anreiz.

\
Die zeitliche Struktur der Stelle mit 40 Stunden pro Woche über sechs Monate hat dabei den Vorteil, dass man sich tiefgehend in Projekte einarbeiten und diese über einen längeren Zeitraum begleiten kann. Kurzpraktika ermöglichen zwar ebenfalls Einblicke, lassen aber kaum die Möglichkeit, selbst an einem Projekt von einem frühen Stadium bis zur Fertigstellung mitzuwirken. Das war für mich ein Aspekt, der die Stelle von anderen Angeboten unterschieden hat, die ich in Betracht gezogen hatte.

\
\
= Firma und Abteilung
Die Fraunhofer-Gesellschaft ist eine der größten Organisationen für angewandte Forschung in Europa und steht damit für ein breites Spektrum an wissenschaftlichen Tätigkeiten welche gezielt auf praktische Anwendung ausgerichtet sind. Mit über 70 Instituten und Einrichtungen sowie mehr als 30.000 Mitarbeitenden deckt die Gesellschaft ein enormes Themenspektrum ab, das von Mikroelektronik über Produktionstechnik bis hin zu Gesundheitstechnologien reicht. Finanziert wird die Forschung dabei durch eine Kombination aus öffentlichen Mitteln und Auftragsforschung für Industriepartner, was die Organisation strukturell eng an wirtschaftliche Anforderungen bindet.

\
Das Fraunhofer-Institut für Arbeitswirtschaft und Organisation IAO ist ein Teil dieser Gesellschaft und beschäftigt sich spezifisch mit dem Bereich der Arbeitsforschung, wobei der Fokus auf der Schnittstelle zwischen menschlicher Arbeit und technologischem Wandel liegt. Das Institut bearbeitet dabei Fragestellungen rund um die Zukunft der Arbeit, digitale Transformation und die Gestaltung von Arbeitsumgebungen und -prozessen. Ein Schwerpunkt liegt auf der Frage, wie neue Technologien so eingesetzt werden können, dass sie menschliche Arbeit sinnvoll unterstützen anstatt lediglich zu ersetzen. Diese Breite des Themenspektrums spiegelt sich auch in der Zusammensetzung der Belegschaft wider, die aus Personen verschiedenster fachlicher Hintergründe besteht und damit eine ungewöhnlich interdisziplinäre Perspektive auf technologische Fragestellungen ermöglicht.

\
Der Hauptsitz des IAO befindet sich in Stuttgart, was die räumliche Nähe zu einer der wirtschaftsstärksten Regionen Deutschlands mit sich bringt und damit einen direkten Zugang zu industriellen Partnern aus dem Automobil- und Maschinenbaubereich ermöglicht. Diese regionale Einbettung ist kein Zufall, sondern spiegelt den Anspruch wider, Forschungsergebnisse möglichst nah an den Anforderungen der Praxis zu entwickeln.

\
Die Abteilung bei der ich gearbeitet habe war das KEIM, das Kompetenzzentrum für energetische und informationstechnische Mobilitätsschnittstellen. Anders als ein klassischer Institutsstandort fungiert das KEIM als Außenposten welcher eng mit der Hochschule Esslingen zusammenarbeitet und somit eine direkte Verbindung zwischen Forschung und akademischer Ausbildung herstellt.
Diese Struktur ermöglicht es das Erkenntnisse aus der Forschung nicht nur theoretisch verbleiben sondern aktiv in echte Anwendungsfälle der Industrie überführt werden. Ziel ist dabei der Transfer von Innovation in praxisnahe Lösungen, was die Arbeit am KEIM inhaltlich eng an realen Anforderungen aus Wirtschaft und Industrie ausrichtet.

\
Im Alltag äußert sich diese Ausrichtung dadurch, dass die Projekte, an denen gearbeitet wird, stets einen konkreten Auftraggeber oder Anwendungsfall haben. Es wird nicht für die Schublade entwickelt, sondern mit dem Ziel, funktionierende Lösungen bereitzustellen, die tatsächlich genutzt werden. Das schafft eine andere Art von Verantwortungsbewusstsein gegenüber der eigenen Arbeit als es in rein akademischen Kontexten der Fall wäre. Fehler haben reale Konsequenzen, und das Bewusstsein dafür verändert die Art, wie man an Aufgaben herangeht und wie sorgfältig man Entscheidungen begründet.

\
Das Team am KEIM ist klein und besteht überwiegend aus jüngeren Personen, darunter sowohl Festangestellte als auch weitere Studierende in ähnlichen Praktikumsverhältnissen. Die Arbeitsatmosphäre war entsprechend unkompliziert und von einem direkten, kollegialen Umgang geprägt. Fragen konnten jederzeit gestellt werden und es wurde Wert darauf gelegt, dass man sich in neue Aufgabenbereiche eigenständig einarbeiten konnte, ohne dabei allein gelassen zu werden.

\
Organisatorisch ist das KEIM wie viele Forschungseinrichtungen in laufende Projekte gegliedert, die jeweils eigene Ziele, Zeitpläne und Ressourcen haben. Praktikanten werden dabei in der Regel einem oder mehreren dieser Projekte zugeordnet und arbeiten dort mit dem jeweiligen Team zusammen. Das hat zur Folge, dass man innerhalb des Praktikums in Berührung mit unterschiedlichen Projektkontexten kommen kann, was die Bandbreite der Erfahrungen erhöht, aber auch ein gewisses Maß an Anpassungsfähigkeit erfordert, da man sich immer wieder in neue Zusammenhänge einarbeiten muss.

= Aufgaben
== Analyse einer Verkehrs-Datenschnittstelle
Im Umfang einer meiner ersten Aufgaben durfte ich eine Verkehrs-Datenschnittstelle von TomTom analysieren um durch das Abrufen dieser möglicherweise Verkehrsdaten nutzbar zu machen. Ziel war es herauszufinden, welche Endpunkte die API bereitstellt, welche Datenformate zurückgegeben werden und in welchem Umfang diese Daten für die bestehenden Systeme verwendbar sein könnten.

\
Die Analyse umfasste sowohl das Studium der offiziellen Dokumentation als auch das praktische Ausprobieren verschiedener Endpunkte. TomTom stellt eine REST-basierte API bereit, über die unter anderem Echtzeitdaten zu Verkehrsfluss und -behinderungen abgerufen werden können. Die Daten werden dabei in einem GeoJSON-ähnlichen Format zurückgegeben, das geographische Koordinaten mit attributiven Informationen wie Geschwindigkeit, freier Kapazität und Art der Behinderung verknüpft.

\
Dabei stellte sich heraus, dass die TomTom API eine Vielzahl von Informationen zu Verkehrsfluss und Verkehrsbehinderungen liefern kann, diese jedoch in einem Format vorliegen, das zunächst aufbereitet werden muss, bevor es sinnvoll in eine Datenpipeline integriert werden kann. Besonders relevant war die Frage der räumlichen Auflösung: Die API liefert Daten segmentbasiert, also bezogen auf einzelne Straßenabschnitte, was für eine Integration in ein System, das mit Flottenbewegungen auf einer gröberen Granularitätsstufe arbeitet, zunächst eine Aggregation erfordert.

\
Als Ergebnis dieser Analyse habe ich eine Dokumentation erstellt, welche die relevanten Endpunkte zusammenfasst, die Datenstruktur beschreibt und eine Einschätzung zur Integrierbarkeit der Daten in die bestehende Systemlandschaft enthält. Dabei habe ich auch auf die Grenzen der API hingewiesen, etwa in Bezug auf Abfrageraten und die Verfügbarkeit historischer Daten, da diese Aspekte für eine langfristige Nutzung im Forschungskontext relevant sind. Diese erste Aufgabe hat mir einen guten Einstieg in die Arbeit gegeben, da sie einerseits selbstständiges Arbeiten erforderte und andererseits das Ergebnis unmittelbar in die weiteren Überlegungen des Teams einfließen konnte.

\
== Schnittstelle an Daten-Pipeline anbinden
Eine bereits zum Teil bestehende Daten-Pipeline musste mit der Funktion erweitert werden, Daten direkt aus den DWD Archiven zu sammeln. Dafür gab es eine bereits zum Teil implementierte Lösung, welche ich erweitert habe.
Im Anschluss mussten im Rahmen dieser Daten-Pipeline die gesammelten Daten in eine RabbitMQ geladen werden damit diese von den nächsten Schritten der Pipeline aufgegriffen werden können.

\
Diese Pipeline war so aufgebaut, das die Daten erst aus verschiedenen Quellen gesammelt werden und dann durch andere Services verarbeitet werden um diese als stimmigen Datensatz nutzbar zu machen.
Für die DWD Daten habe ich dann auch im Anschluss einen dieser weiteren Services gebaut welche die Daten aus der RabbitMQ empfängt und zu einem einheitlichen Datenformat bereinigt.

\
Um das erfolgreich zu erzielen mussten allerdings noch Änderungen am grundsätzlichen Datenformat welches in die RabbitMQ geladen wurde vorgenommen werden um dem System welche diese bereinigt sagen zu können um welche Art von Daten es sich handelt.

\
Der Deutsche Wetterdienst stellt seine archivierten Messdaten über ein öffentlich zugängliches FTP-Verzeichnis zur Verfügung. Die Herausforderung bestand dabei nicht nur im technischen Abruf der Daten, sondern auch im Umgang mit der uneinheitlichen Struktur der verschiedenen Datensätze. Je nach Messstation und Zeitraum unterscheiden sich die Dateinamen, Spaltenbeschriftungen und Kodierungen, was eine robuste und anpassungsfähige Implementierung nötig machte.

\
Ein konkretes Beispiel für diese Uneinheitlichkeit war der Umgang mit Fehlwerten: In verschiedenen Teilen des Archivs werden fehlende Messungen unterschiedlich kodiert, mal als leere Felder, mal als spezifische Sentinel-Werte wie -999 oder -1. Ohne eine explizite Behandlung dieser Fälle würden fehlerhafte Werte in die nachgelagerten Verarbeitungsschritte gelangen und dort zu verfälschten Ergebnissen führen. Das frühzeitige Erkennen und Dokumentieren solcher Besonderheiten war deshalb ein wichtiger Teil der Aufgabe.

\
RabbitMQ ist ein Message-Broker-System, das auf dem AMQP-Protokoll basiert und es ermöglicht, Nachrichten zwischen verschiedenen Services asynchron auszutauschen. In der Architektur dieser Pipeline übernimmt RabbitMQ die Rolle eines Puffers und Entkopplungsmechanismus: Der Datensammler produziert Nachrichten und legt diese in einer Queue ab, ohne wissen zu müssen, wer diese Nachrichten später konsumiert und wie sie weiterverarbeitet werden. Das erlaubt es, einzelne Komponenten der Pipeline unabhängig voneinander zu entwickeln, zu skalieren und bei Bedarf auszutauschen. Diese Erfahrung hat mir gezeigt, dass ereignisgesteuerte Architekturen in der Praxis deutlich häufiger eingesetzt werden als es im Studium vermittelt wird, und dass das Verständnis ihrer grundlegenden Prinzipien für die moderne Softwareentwicklung sehr wertvoll ist.

\
== Entwicklung, Bereitstellung sowie Administration eines Services
Als Teil einer Aufgabe war es nötig einen Service auf einem Raspberry Pi 4B zu deployen. Dabei war es wichtig eine stabile und zuverlässige Ausführung zu gewährleisten, so das selbst bei Internet-Verbindungsproblemen oder spontanen Stromausfällen das Programm sich selbst rettet und schnell normale Operation wiederaufnimmt.
Dieses Problem könnte mit einer großen Anzahl verschiedenster Herangehensweisen besser oder schlechter gelöst werden, aber ich habe mich am Ende für eine Umsetzung für einen Softwarestack von Golang als Programmiersprache und NixOS als Betriebssystem entschieden.

\

#meander.reflow({
  import meander: *
  placed(
    top + right,
    figure(
      image("Gopher.png", width: 50%),
      caption: [The Go gopher #cite(<Gopher>)],
    ),
  )
  container()
  content[
    #set par(justify: true)
    #par(
      "Go ist eine kompilierte, statisch typisierte Programmiersprache mit automatischer Speicherbereinigung. Es handelt sich um eine C-ähnliche multiparadigme Sprache welche von Google 2007 entwickelt wurde mit dem Ziel eine leicht erlernbare, hoch effiziente Programmiersprache zu entwerfen welche sich vor allem für Netzwerk-Anwendungen sehr leicht skalieren lässt.",
    )
  ]
})
Genau aus diesem Grund wähle ich diese Programmiersprache sehr gerne für solche Arten von Anwendungen. Hier eignet sie sich besonders gut da durch die automatische Speicherbereinigung weniger Probleme verursacht werden könnten welche zu unerwarteten Programmabbrüchen führen und die statische Typisierung von Go mir trotzdem genug Kontrolle gibt um das erwartete Verhalten näher an das tatsächliche Verhalten des Programms zu bringen.

\
Zudem macht es Go leicht alle Fehler so zu verarbeiten, das das Programm nicht unerwartet abstürzen sollte indem Fehler als Werte abgebildet werden. Den Rückgabewert eines Fehlers zu ignorieren ist deshalb eine sehr bewusste Wahl (z.B. `_, value := foo()` anstatt `err, value := foo()` bei einer Funktion `foo` welche die einen Fehler und Wert zurückgibt).

\
Ein weiterer Vorteil von Go für diesen Anwendungsfall ist das Kompilieren zu einer einzelnen, statisch verlinkten Binärdatei. Das bedeutet, dass die Anwendung auf dem Zielsystem ohne weitere Laufzeitabhängigkeiten ausgeführt werden kann, was das Deployment vereinfacht und potenzielle Fehlerquellen durch fehlende oder inkompatible Bibliotheken eliminiert. Gerade auf einem eingebetteten System wie dem Raspberry Pi, wo man tendenziell minimale Abhängigkeiten bevorzugt, ist das ein praktischer Vorteil.

\
Auch die Nebenläufigkeit in Go verdient in diesem Kontext eine Erwähnung. Go bietet mit Goroutines und Channels ein leichtgewichtiges Modell für parallele Ausführung, das sich gut für Anwendungen eignet, die gleichzeitig mehrere Aufgaben erledigen müssen, etwa das Empfangen von Daten, das Verarbeiten dieser Daten und das periodische Schreiben von Statusinformationen. Da der Service auf dem Raspberry Pi genau dieses Muster implementiert, hat sich Go hier als besonders gut geeignet erwiesen.

\
Die andere genutzte Technologie in diesem Projekt ist Nix bzw. NixOS. Nix ist eine funktionale Programmiersprache, Linux Distribution und Paketmanager. Als Linux Distribution ist NixOS ein Betriebssystem welches um den Nix Paketmanager gebaut ist und Nix als funktionale Programmiersprache nutzt um das gesamte System zu konfigurieren.

\
Das System wird aus der Konfiguration welche in Nix geschrieben ist reproduzierbar gebaut.
Der wesentliche Grund warum für dieses Projekt NixOS als Betriebssystem gewählt wurde ist das es dank der Reproduzierbarkeit bei Systemproblemen einfach auf die letzte funktionierende Version zurückgerollt werden kann, was das Aufsetzen und Instandhalten eines Systems simpel macht.

\
Die Applikation wurde durch Nix Konfiguration als System-Service eingerichtet. Dazu musste für die Applikation erst ein internes Nix-Paket erstellt werden.

\
Die Erstellung von Nix Paketen stellte sich grundlegend als relativ simpel heraus, jedoch stellten sich Probleme mit der Kompatibilität von den Go Paket system heraus, da die Pakete im Vorhinein in die isolierte Umgebung geladen werden müssen damit sie beim kompilieren auch ohne Internetzugang verfügbar sind.

\
Um dieses Problem zu lösen habe ich das Tool gomod2nix genutzt welche die `go.mod` Datei eines Go-Projektes ausliest und diese für den vorhin genannten Prozess zur Verfügung stellt. Das Tool generiert dabei eine zusätzliche Lockdatei, die die exakten Versionen und Hashes aller verwendeten Go-Abhängigkeiten enthält, sodass der Nix-Build diese Pakete vorab herunterladen und in den Store legen kann. Damit ist der Build vollständig reproduzierbar und kann auch in einer vollständig isolierten Umgebung ohne Internetzugang durchgeführt werden, was ein zentrales Designprinzip des Nix-Ökosystems ist.

\
Ein weiterer Vorteil von NixOS in diesem Kontext ist die deklarative Serviceverwaltung über systemd-Units, die direkt in der Nix-Konfiguration beschrieben werden. Damit lässt sich genau festlegen, unter welchen Bedingungen ein Service neugestartet werden soll, welche Umgebungsvariablen gesetzt sind und welche Abhängigkeiten vor dem Start erfüllt sein müssen. So lässt sich zum Beispiel konfigurieren, dass der Service nach einem Absturz automatisch neugestartet wird und bei wiederholtem Fehlschlagen eine kurze Wartezeit einlegt bevor der nächste Versuch unternommen wird. Das Ergebnis ist ein System das sich bei den allermeisten Fehlerzuständen selbstständig erholt, ohne dass manuell eingegriffen werden muss.

\
Für die Konfiguration des Netzwerkzugriffs musste zudem sichergestellt werden, dass der Service bei vorübergehend fehlender Internetverbindung nicht dauerhaft in einen Fehlerzustand gerät. Das wurde durch eine Kombination aus internem Retry-Mechanismus in der Go-Applikation und einer entsprechenden Konfiguration des systemd-Services gelöst, sodass sowohl auf Anwendungsebene als auch auf Systemebene mit Verbindungsunterbrechungen umgegangen werden kann.

\
Am Ende konnte der Service erfolgreich auf dem Raspberry Pi 4B deployed werden und mit minimalem Wartungsaufwand operational gehalten werden. Die Wahl von NixOS hat sich dabei als besonders praktisch erwiesen, da im Verlauf des Projekts mehrfach kleinere Konfigurationsänderungen nötig waren, die sich durch die deklarative Struktur schnell und risikoarm umsetzen ließen. Das Rollback-Mechanismus von NixOS hat dabei mehrfach geholfen, fehlerhafte Konfigurationsänderungen rückgängig zu machen ohne dass ein manuelles Eingreifen auf dem System nötig gewesen wäre.

\
== Frontend-Entwicklung
Für die Weiterentwicklung einer Webapplikation war es nötig ein neues modernes Frontend zu planen und entwickeln. Das habe ich in einem Team machen dürfen welches sich um das Projekt gekümmert hatte.

\
Als ersten Schritt bei einer solchen Aufgabe hat es sich angeboten das UI mit einem Tool wie Figma zu designen. Da ich allerdings in der Vergangenheit schlechte Erfahrungen mit Figma gemacht habe und grundsätzlich Freie und Offene Software bevorzuge habe ich mich für die Alternative Penpot entschieden welches ähnliche Funktionalitäten zum Erstellen von Mockups hat.

\
Penpot ist ein browserbasiertes Open-Source-Designwerkzeug, das von der spanischen Firma Kaleidos entwickelt wird und sich als direkte Alternative zu Figma positioniert. Der wesentliche Unterschied liegt neben dem offenen Quellcode darin, dass Penpot intern mit SVG arbeitet, was eine enge Verwandtschaft zu Webstandards schafft und den Export von Designkomponenten in webkompatible Formate erleichtert. Für ein Projekt das ohnehin für das Web entwickelt wird hat sich das als praktischer Vorteil erwiesen, da Abstände, Schriftgrößen und Farben direkt in CSS-kompatiblen Einheiten definiert werden können.

\
Im Designprozess wurden zunächst Wireframes erstellt, um die grundlegende Seitenstruktur und Navigation festzulegen, bevor im zweiten Schritt ein detaillierteres visuelles Design ausgearbeitet wurde. Dieser zweistufige Ansatz hat sich als sinnvoll erwiesen, da er es erlaubt, strukturelle Fragen von gestalterischen Fragen zu trennen und beide unabhängig voneinander zu iterieren, ohne bei jeder kleinen Änderung das gesamte Design anpassen zu müssen. Zudem hat die Wireframe-Phase dazu beigetragen, frühzeitig ein gemeinsames Verständnis im Team über den Aufbau und die Navigation der Anwendung herzustellen, was spätere Missverständnisse bei der Implementierung reduziert hat.

\
Ein besonderes Augenmerk wurde auf die Konsistenz des Designs gelegt. Dazu wurde ein einfaches Designsystem in Penpot angelegt, das wiederverwendbare Komponenten wie Schaltflächen, Eingabefelder und Karten definiert. Dadurch konnte sichergestellt werden, dass gleiche Elemente an verschiedenen Stellen der Anwendung einheitlich aussehen und sich einheitlich verhalten, was die Benutzerführung verbessert und den Implementierungsaufwand reduziert.

\
Nachdem das Frontend geplant war, wurden die geplanten Aspekte nach und nach mit Next.js, einem React Framework, umgesetzt. Next.js bietet gegenüber einem einfachen React-Setup unter anderem serverseitiges Rendering sowie ein auf dem Dateisystem basierendes Routing-System, was die Strukturierung größerer Anwendungen deutlich vereinfacht. Serverseitiges Rendering hat dabei den Vorteil, dass die initiale Ladezeit der Anwendung verkürzt wird und Suchmaschinen den Inhalt der Seiten besser indexieren können, was für Webanwendungen mit öffentlichem Zugang relevant sein kann.

\
Da das Projekt bereits auf TypeScript gesetzt hatte, wurde das Frontend ebenfalls in TypeScript umgesetzt, was die Typsicherheit über Frontend und Backend hinweg erhöht und die Zusammenarbeit im Team erleichtert, da Schnittstellen klar definiert und von beiden Seiten nachvollziehbar sind. Gerade bei API-Anfragen an das Backend hat sich das als hilfreich erwiesen, da Typfehler beim Deserilisieren von Antwortdaten bereits zur Kompilierzeit erkannt werden können anstatt erst zur Laufzeit als schwer nachvollziehbare Fehler aufzutreten.

\
Ein herausfordernder Aspekt der Frontend-Entwicklung war die Visualisierung von georeferenzierten Daten. Die Anwendung stellt unter anderem Positionen und Routen von Fahrzeugen auf einer Karte dar, was die Integration einer Kartenbibliothek erforderte. Nach einer kurzen Evaluation verschiedener Optionen haben wir uns für eine auf Leaflet.js basierende Lösung entschieden, die sich gut in das React-Ökosystem integrieren lässt und die nötigen Funktionalitäten für interaktive Karten mitbringt.

\
== Middleware Entwicklung
Im Rahmen des neu geschriebenen Frontends für die Webapplikation, sollte eine Art Benchmark-System erstellt werden welches Teilergebnisse der Applikation anzeigt. Dabei war es wichtig das die vollen Ergebnis-Daten nicht an das Frontend gesendet werden sondern nur die Teilergebnisse.

\
Um das umzusetzen habe ich ein weiteres Backend als eine Art Middleware zwischen dem vollen Backend und dem Frontend der Applikation geschrieben um die vollen Ergebnisse abzufangen, zu den Teilergebnissen zu verarbeiten und nur diese an das Frontend zu senden.

\
Dieses Backend wurde in Python geschrieben um die Deserialisierung der vollen Daten durch die dynamische Typisierung leichter zu machen.

\
Das grundlegende Architekturmuster dieser Lösung ist das eines Proxys: Das Frontend kommuniziert ausschließlich mit der Middleware, die wiederum bei Bedarf Anfragen an das eigentliche Backend weiterleitet. Dadurch lässt sich nicht nur steuern, welche Daten nach außen sichtbar sind, sondern die Middleware kann auch als Schicht für Berechnungen genutzt werden, die nicht im Backend selbst implementiert werden sollen oder können. In diesem Fall bedeutete das konkret, dass aus den vollständigen Optimierungsergebnissen des Backends nur ausgewählte Kennzahlen aggregiert und in einem vereinfachten Format an das Frontend übermittelt wurden.

\
Für die Implementierung des HTTP-Servers habe ich Flask genutzt, ein leichtgewichtiges Python-Webframework, das sich für kleine und mittelgroße APIs sehr gut eignet. Flask stellt die grundlegende Infrastruktur für das Routing von HTTP-Anfragen und die Serialisierung von Antworten bereit, ohne dabei einen zu großen Overhead an Konfiguration und Projektstruktur vorauszusetzen. Da die Middleware klar umrissen und in ihrem Funktionsumfang bewusst begrenzt sein sollte, wäre ein schwergewichtigeres Framework wie Django für diesen Zweck überdimensioniert gewesen.

\
Die Implementierung in Python hat sich dabei als pragmatische Wahl erwiesen. Da die vollständigen Ergebnisdaten ein komplexes, teils verschachteltes JSON-Format hatten, wäre eine Deserialisierung in einer statisch typisierten Sprache mit erheblichem Aufwand für die Typdefinitionen verbunden gewesen. Python erlaubt es hier, deutlich direkter auf die benötigten Felder zuzugreifen, was die Entwicklungszeit erheblich verkürzt hat. Da die Middleware keinen hohen Durchsatz bewältigen muss und die Antwortzeiten des nachgelagerten Backends den maßgeblichen Faktor für die Gesamtlatenz darstellen, war die geringere Ausführungseffizienz von Python gegenüber kompilierten Sprachen für diesen Anwendungsfall kein ausschlaggebendes Kriterium.

\
Ein weiterer Aspekt, dem ich bei der Implementierung Aufmerksamkeit geschenkt habe, war das Fehlerverhalten der Middleware. Da sie als Vermittler zwischen zwei anderen Systemen agiert, kann es an beiden Seiten zu Fehlern kommen, die sinnvoll behandelt werden müssen. Anfragen des Frontends bei denen das Backend nicht erreichbar ist, sollten mit einer verständlichen Fehlermeldung beantwortet werden anstatt in einem undefinierten Zustand zu verharren. Auch der umgekehrte Fall, bei dem das Backend Daten in einem unerwarteten Format zurückgibt, musste abgefangen werden. Diese Überlegungen zur Robustheit sind in der Praxis oft aufwändiger als die eigentliche Kernfunktionalität, aber für den zuverlässigen Betrieb eines Systems unerlässlich.

\
== Datenaufbereitung
Im Rahmen eines Prozesses zur Verarbeitung von Kundendaten mussten diese aus dem Ursprungsformat welches uns zur Verfügung gestellt wurde in ein von unseren Programmen nutzbares Format konvertiert werden. Dabei handelte es sich nicht nur um eine simple Dateiformat-Konvertierung da einige Daten ergänzt oder mit einer Anfrage an andere bereits bestehende Datensätze angepasst werden mussten.

\
Das Skript welches diese Aufgabe erledigen sollte habe ich in Python geschrieben, da es sich als simple Skript-Sprache super für eine solche Aufgabe anbietet und dank dynamischer Typisierung die Deserialisierung der Daten leicht macht, was sich in statisch typisierten Programmiersprachen wie Go oft nur umständlich implementieren lässt. Eine Umsetzung in Go würde das Programm tendenziell schneller und möglicherweise robuster machen aber wegen der nicht zuverlässigen Natur der Daten hat sich eine solche Umsetzung als für diesen Fall zu umständlich herausgestellt.

\
Da ich bei diesem Praktikum oft mit der Deserialisierung von Daten aus meist JSON oder CSV zu tun hatte war das ein häufig vorkommendes Dilemma: Eine Umsetzung in Go ist etwas, was ich generell bevorzuge, aber kann sich manchmal als zu umständlich herausstellen, da Go als statisch typisierte Sprache bei der Deserialisierung eine feste Zuweisung von Feld zu Typ erwartet. Bei Eingangsdaten wo sich die Feldnamen oder Typen dessen je nach Bedingung ändern, wird eine saubere Typisierung schnell sehr verbos oder unklar, da entweder jedes Ergebnis einzeln als Typ abgebildet werden muss oder mit der Hilfe von Interfaces die Typisierung generalisiert wird, was die Vorteile der statischen Typisierung zum Großteil zunichte macht.

\
Ein besonderer Aspekt dieser Aufgabe war die Notwendigkeit, externe Datensätze per API abzufragen und die Ergebnisse mit den Kundendaten zusammenzuführen. Das erforderte nicht nur den technischen Abruf, sondern auch eine sorgfältige Behandlung von Fällen, in denen keine oder mehrdeutige Treffer zurückgegeben wurden. Da die Qualität der Ausgangsdaten nicht immer einheitlich war, mussten hier verschiedene Fallunterscheidungen implementiert werden, um das Skript robust genug zu machen, dass es auch mit unvollständigen oder fehlerhaften Eingaben sinnvoll umgehen kann.

\
Ein wiederkehrendes Problem bei der Datenaufbereitung war der Umgang mit Koordinatenangaben, die in verschiedenen Formaten vorlagen. Manche Datensätze enthielten Geokoordinaten im Dezimalgrad-Format, andere im Grad-Minuten-Format, und wieder andere enthielten statt numerischer Koordinaten nur Ortsbezeichnungen, die erst durch eine Geocodierungsanfrage in Koordinaten umgewandelt werden mussten. Das Skript musste diese verschiedenen Fälle erkennen und jeweils eine geeignete Umwandlung durchführen, was die Implementierung deutlich komplexer gemacht hat als eine einfache Formatkonvertierung.

\
Insgesamt hat diese Aufgabe gezeigt, dass Datenaufbereitung in der Praxis oft einen erheblichen Teil des Gesamtaufwands eines Projekts ausmacht, auch wenn dieser Aspekt in der Planung häufig unterschätzt wird. Die Qualität der Eingangsdaten ist dabei der entscheidende Faktor: Je uneinheitlicher und fehleranfälliger die Rohdaten sind, desto mehr Aufwand muss in Validierung, Bereinigung und Normalisierung investiert werden, bevor die eigentliche Analyse oder Verarbeitung beginnen kann.

\
\
= Fazit
Das Praktikum am KEIM des Fraunhofer IAO war für mich eine wertvolle Erfahrung, die mein bisheriges Studium in vielerlei Hinsicht sinnvoll ergänzt hat. Die Möglichkeit, über mehrere Monate hinweg an echten Projekten mit konkreten Anforderungen zu arbeiten, hat mir ein Verständnis dafür vermittelt, wie Softwareentwicklung im professionellen Umfeld tatsächlich abläuft, abseits von klar definierten Übungsaufgaben mit einem bekannten Ergebnis.

\
Besonders prägend war dabei die Erfahrung, dass technische Entscheidungen im Arbeitsalltag selten eine objektiv richtige Antwort haben, sondern immer von Rahmenbedingungen abhängen. Die wiederkehrende Abwägung zwischen einer Umsetzung in Go und einer in Python ist dafür ein gutes Beispiel: Je nach Art der Daten, dem Zeithorizont der Aufgabe und den bestehenden Systemen fiel die Entscheidung unterschiedlich aus. Diese Art von pragmatischem Denken ist etwas, das sich nur durch praktische Erfahrung entwickeln lässt und das ich als einen der wichtigsten Lerneffekte des Praktikums einordnen würde.

\
Darüber hinaus habe ich durch die Arbeit an der Systemadministration des Raspberry Pi mit NixOS Einblick in einen Bereich bekommen, mit dem ich zuvor kaum in Berührung gekommen war. Die funktionale, deklarative Herangehensweise an Systemkonfiguration ist konzeptuell ungewohnt, hat aber eine Logik, die sich mit der Zeit erschließt und die ich als sehr überzeugend empfinde. Es ist der Art und Weise, wie ich bisher über Betriebssysteme und deren Konfiguration gedacht habe, grundlegend fremd, was es zu einer besonders lehrreichen Erfahrung gemacht hat. Die Erkenntnis, dass ein gesamtes Betriebssystem aus einer versionierten, reproduzierbaren Konfiguration heraus aufgebaut werden kann, hat meine Vorstellung davon verändert, was in der Systemadministration möglich ist.

\
Die Arbeit im Team hat mir gezeigt, wie wichtig eine klare Kommunikation über Schnittstellen und Datenformate ist, wenn mehrere Personen gleichzeitig an verschiedenen Teilen eines Systems arbeiten. Missverständnisse in diesem Bereich können zu erheblichem Mehraufwand führen und machen deutlich, warum Dokumentation und gemeinsam vereinbarte Konventionen in der Softwareentwicklung einen so hohen Stellenwert haben. Ein konkretes Beispiel war eine Situation, in der das Format der Nachrichten, die in die RabbitMQ geladen wurden, geändert werden musste, ohne dass alle beteiligten Services vorab informiert wurden. Das hat kurzfristig zu Fehlern in nachgelagerten Verarbeitungsschritten geführt und gezeigt, wie wichtig es ist, Änderungen an gemeinsam genutzten Schnittstellen sorgfältig zu kommunizieren und koordiniert einzuführen.

\
Ein weiterer Aspekt, den ich aus dem Praktikum mitgenommen habe, ist eine realistischere Einschätzung von Aufwänden. In Projekten mit realen Randbedingungen, unvollständigen Spezifikationen und unbekannten Datenqualitäten ist es deutlich schwieriger, den Aufwand für eine Aufgabe im Voraus zu schätzen als bei klar umrissenen Studienaufgaben. Mehrfach habe ich die Erfahrung gemacht, dass Teilaufgaben die zunächst einfach wirkten, sich beim näheren Hinschauen als deutlich komplexer herausgestellt haben, zum Beispiel weil Randfälle in den Eingabedaten aufgetreten sind, die nicht im ursprünglichen Konzept berücksichtigt wurden. Das hat mir ein Gefühl dafür gegeben, warum in der professionellen Softwareentwicklung so viel Wert auf iterative Vorgehensweisen gelegt wird, die auf Unvorhergesehenes reagieren können.

\
Insgesamt blicke ich auf das Praktikum als eine Zeit zurück, in der ich nicht nur technische Fähigkeiten ausgebaut habe, sondern auch ein besseres Gespür dafür entwickelt habe, wie man sich in einem professionellen Arbeitsumfeld verhält, Aufgaben selbstständig strukturiert und einschätzt, wann man eigenständig weiterarbeiten kann und wann es sinnvoller ist, Rücksprache zu halten. Beides sind Fähigkeiten, die sich nicht aus Büchern oder Vorlesungen erlernen lassen, sondern die einen realen Kontext mit echten Anforderungen und echten Konsequenzen erfordern.

\
\
= Bezug zum Studium
In dem Praktikum konnte ich Wissen aus vielen der Module meines Studiums anwenden. Da es sich um eine Softwareentwicklungs-Stelle handelt war der Bezug größtenteils auf die Module Python, Algorithmen und Datenstrukturen und am meisten von allen das Software Praktikum.

\
Das Modul Python hat mir die Grundlagen vermittelt, die ich für die Skript-Aufgaben während des Praktikums benötigt habe. Gerade bei der Datenaufbereitung und der Middleware-Entwicklung konnte ich direkt auf Kenntnisse zurückgreifen, die ich dort erworben hatte. Die im Studium behandelten Themen wie Dateioperationen, der Umgang mit externen Bibliotheken und die Verarbeitung von JSON- und CSV-Daten haben sich als unmittelbar anwendbar erwiesen. Darüber hinaus war das im Studium entwickelte Verständnis für Ausnahmebehandlung besonders relevant, da robuste Skripte für die Verarbeitung unzuverlässiger Eingabedaten ohne sorgfältige Fehlerbehandlung schnell in undefinierten Zuständen enden.

\
Aus dem Modul Algorithmen und Datenstrukturen konnte ich vor allem bei der Analyse und Erweiterung bestehender Algorithmen im Bereich Flottenmanagement profitieren. Das Verständnis für Komplexität und die Fähigkeit, algorithmische Ansätze zu bewerten und gegeneinander abzuwägen, hat mir geholfen, technische Entscheidungen besser zu begründen. Gerade bei der Arbeit mit Datenpipelines, bei denen Daten in mehreren Schritten transformiert und gefiltert werden, ist ein klares Verständnis der eingesetzten Datenstrukturen wichtig, um Engpässe zu erkennen und gezielt zu beheben. Die im Studium behandelten Konzepte wie Queues und die ihnen zugrunde liegenden Eigenschaften waren dabei beim Verständnis der RabbitMQ-Architektur direkt nützlich, auch wenn die konkrete Umsetzung in einem verteilten System natürlich deutlich komplexer ist als die abstrakten Datenstrukturen aus der Vorlesung.

\
Das Software Praktikum war dabei das Modul, auf das ich mich im Laufe des Praktikums am häufigsten gestützt habe. Die Erfahrung, im Team an einer gemeinsamen Codebasis zu arbeiten, Versionskontrolle konsequent einzusetzen und Aufgaben in handhabbare Teilschritte aufzuteilen, war eine direkte Anwendung dessen, was in diesem Modul vermittelt wurde. Auch das Thema Code-Reviews und die damit verbundene Diskussion über Lesbarkeit und Wartbarkeit von Code war im Arbeitsalltag am KEIM präsent. Darüber hinaus haben die im Software Praktikum behandelten Themen rund um die Dokumentation von Code und die Strukturierung von Projekten geholfen, eigene Beiträge so zu gestalten, dass andere Mitglieder des Teams sie leicht nachvollziehen und weiterentwickeln können.

\
Weniger direkt, aber dennoch spürbar, war der Einfluss des Moduls Rechnernetze. Die Arbeit mit RabbitMQ als Message Broker und das Verstehen, wie Services über Nachrichten miteinander kommunizieren, baut konzeptuell auf dem Wissen über Netzwerkkommunikation und Protokolle auf, das in diesem Modul behandelt wird. Ohne diesen Hintergrund wäre der Einstieg in die Architektur der bestehenden Datenpipeline deutlich schwerer gefallen. Auch das Verständnis von REST-APIs und HTTP-Protokollen, das ich mir teilweise im Studium und teilweise autodidaktisch angeeignet hatte, war bei der Analyse der TomTom-Schnittstelle und der Implementierung der Middleware-API sehr hilfreich.

\
Ebenfalls relevant war das im Studium erworbene Grundlagenwissen über Betriebssysteme. Konzepte wie Prozessverwaltung, Dateisysteme und die Rolle des Kernels als Vermittler zwischen Hardware und Software bildeten die konzeptuelle Grundlage, auf der das Verständnis für die spezifischen Eigenheiten von NixOS aufgebaut werden konnte. Ohne dieses Fundament wäre es deutlich schwieriger gewesen, die Nix-Dokumentation zu lesen und zu verstehen, warum bestimmte Designentscheidungen in NixOS so getroffen wurden wie sie es wurden.

\
Gleichzeitig gab es auch Bereiche des Praktikums, für die ich kein direktes Äquivalent im Studium finden konnte. NixOS und die deklarative Systemkonfiguration zum Beispiel sind Themen, die im Curriculum nicht vorkommen. Das hat mich dazu gebracht, mir diese Kenntnisse vollständig durch Dokumentation, Community-Ressourcen und praktisches Ausprobieren anzueignen. Das war zwar aufwändiger als das Zurückgreifen auf Studieninhalte, hat mir aber gezeigt, dass selbstgesteuerte Einarbeitung in neue Themen eine eigene Fähigkeit ist, die sich trainieren lässt und die im Berufsleben mindestens ebenso wichtig ist wie das Wissen, das im Studium vermittelt wird.

\
Rückblickend würde ich mir wünschen, dass das Studium stärker auf einige Themen einginge, die im praktischen Arbeitsalltag eine hohe Relevanz haben, aber im Curriculum wenig Raum einnehmen. Dazu zählt für mich vor allem der Bereich der Systemadministration und des Deployments von Anwendungen, also die Frage, wie Software nicht nur entwickelt, sondern auch zuverlässig betrieben wird. Containerisierung mit Docker, Konfigurationsmanagement und die Grundlagen von CI/CD-Pipelines wären Themen, die den Übergang von der Entwicklung in den Betrieb deutlich erleichtern würden.

\
\
= Tipps für Bewerber
Beim Fraunhofer IAO bekommt man die Möglichkeit sich in verschiedenste Projekte einzuarbeiten und so durch direkt gewonnene Erfahrung praktisches Wissen zur Softwareentwicklung anzueignen.
Wer bereits grundlegende Kenntnisse in den verwendeten Technologien wie TypeScript, JavaScript oder React mitbringt, kann diese im Arbeitsalltag direkt anwenden und weiterentwickeln, da die Aufgaben von Anfang an praxisnah gestaltet sind.
Gleichzeitig ist es kein Nachteil wenn bestimmte Technologien noch nicht vollständig beherrscht werden, da die Einarbeitung in neue Werkzeuge und Frameworks ausdrücklich als Teil der Tätigkeit vorgesehen ist.

\
Das interdisziplinäre Umfeld am KEIM bringt es mit sich das man nicht nur mit Softwareentwicklern sondern auch mit Personen aus anderen Fachrichtungen zusammenarbeitet, was den Blick für übergreifende Zusammenhänge schärft und das Verständnis dafür fördert wie technische Lösungen in größere Projektkontexte eingebettet sind.
Wer offen für diese Art der Zusammenarbeit ist und Interesse an den Themenfeldern Elektromobilität, Energie und IoT mitbringt, wird die inhaltliche Ausrichtung des KEIM als zusätzliche Motivation erleben.
Die Nähe zur Hochschule Esslingen sorgt dabei für ein Umfeld in dem wissenschaftliches Denken und anwendungsorientiertes Arbeiten unmittelbar nebeneinander existieren.

\
Ein praktischer Hinweis für den Bewerbungsprozess: Es lohnt sich, in der Bewerbung konkret auf eigene Projekte oder Erfahrungen einzugehen, die zeigen, dass man sich bereits eigenständig in technische Themen eingearbeitet hat. Das kann ein privates Programmierprojekt sein, eine Studienarbeit mit technischem Schwerpunkt oder auch die Erfahrung mit einem bestimmten Werkzeug oder einer Programmiersprache, die man sich außerhalb des Curriculums angeeignet hat. Solche Beispiele signalisieren, dass man die Eigeninitiative mitbringt, die für eine Stelle mit praktischer Ausrichtung wichtig ist und die sich im Arbeitsalltag immer wieder als entscheidend erweist.

\
Grundlegende Kenntnisse in der Arbeit mit der Kommandozeile sind ebenfalls empfehlenswert. Viele der Werkzeuge, die in der täglichen Arbeit eingesetzt werden, werden über die Kommandozeile bedient, und ein sicherer Umgang damit erleichtert viele Aufgaben erheblich. Wer bisher hauptsächlich mit grafischen Oberflächen gearbeitet hat, sollte sich vor dem Praktikumsantritt zumindest mit den grundlegenden Konzepten von Shell-Befehlen, Dateisystemen und der Arbeit mit Git über die Kommandozeile vertraut machen. Das ist kein Grund zur Sorge, wenn dieser Bereich noch unbekannt ist, aber eine frühe Auseinandersetzung damit spart im Praktikum Zeit, die man sonst mit dem Erlernen dieser Grundlagen verbringt.

\
Wer das Praktikum antritt, sollte zudem offen dafür sein, dass Aufgaben manchmal weniger klar umrissen sind als man es von Studienaufgaben gewohnt ist. Es gehört zum Alltag, selbst herauszufinden, was genau gebraucht wird, welche Randbedingungen relevant sind und wie man am sinnvollsten vorgeht. Das kann anfangs ungewohnt sein, ist aber letztlich einer der Aspekte, durch die man am meisten lernt. Eine hilfreiche Strategie ist dabei, bei unklaren Anforderungen frühzeitig Rückfragen zu stellen und das eigene Verständnis der Aufgabe kurz zu formulieren und mit der zuständigen Person abzugleichen, bevor man mit der eigentlichen Implementierung beginnt. Das verhindert, dass man Zeit in eine Richtung investiert, die sich im Nachhinein als nicht gewünscht herausstellt.

\
Darüber hinaus ist es sinnvoll, von Anfang an eine gewisse Sorgfalt beim Dokumentieren der eigenen Arbeit walten zu lassen. Das muss keine ausführliche schriftliche Dokumentation sein, aber kurze Kommentare im Code, die erklären warum eine Entscheidung so getroffen wurde und nicht nur was der Code tut, sind im Nachhinein sehr wertvoll, sowohl für andere die den Code lesen als auch für einen selbst wenn man nach einigen Wochen zu einer früheren Stelle zurückkehrt. Gerade bei Aufgaben, die unerwartete Besonderheiten in den Eingabedaten behandeln, helfen solche Kommentare dabei, das gewonnene Wissen festzuhalten und nicht erneut herleiten zu müssen.

\
Für Bewerber welche ein Praktikum im Bereich Softwareentwicklung suchen und dabei nicht nur an bestehenden Systemen arbeiten sondern aktiv an der Gestaltung von Lösungen mitwirken wollen, ist das KEIM des Fraunhofer IAO eine passende Anlaufstelle. Die Kombination aus einem forschungsnahen Umfeld, praxisorientierten Projekten und einem kollegialen Team macht es zu einem Ort, an dem man als Praktikant tatsächlich etwas beitragen und im Gegenzug viel mitnehmen kann.

\
\
#bibliography("sources.bib")