13 Punkte von GN⁺ 2024-07-25 | 1 Kommentare | Auf WhatsApp teilen
  • Zeigt anhand der Termin-Funktion eines Google-Calendar-Klons einen Design-Flow, bei dem nicht zuerst Tabellen erstellt werden, sondern zunächst ein logisches Modell fertiggestellt und anschließend in ein SQL-Schema überführt wird
  • Die zentrale Methode besteht darin, zuerst Anker (anchors) wie User, DayEvent, TimeEvent und Timezone zu identifizieren und Anforderungen sowie Kardinalitäten über Attribute und 1:N- bzw. M:N-Links zu validieren
  • Termine werden in ganztägige Events und zeitbasierte Events unterteilt; zeitbasierte Events speichern die lokale Zeit von Beginn und Ende sowie jeweils die Timezone, um auch mögliche Änderungen von Zeitzonen abzudecken
  • Wiederkehrende Termine werden über Frequenz, Intervall, monatliche Wiederholungsart, Endbedingung und Wochentagsverknüpfungen dargestellt; für das Rendering auf dem Bildschirm und Änderungen einzelner Instanzen werden DaySlot und TimeSlot als eigene Anker geführt
  • Das finale physische Design folgt grundsätzlich „eine Tabelle pro Anker“, legt DayOfTheWeek jedoch nicht als Tabelle an und kommt damit auf insgesamt 8 SQL-Tabellen, darunter 6 Anker-Tabellen und 2 M:N-Link-Tabellen

Designansatz: zuerst ein logisches Modell erstellen

  • Ziel ist es, am Beispiel der Kalenderfunktion eines Google-Calendar-Klons einen Datenbanktabellen-Designprozess zu zeigen, der einem realen Projekt nahekommt
  • Der Gesamtablauf besteht darin, zuerst ein vollständiges logisches Modell der zu speichernden Kalenderdaten zu erstellen und dieses Modell anschließend in eine physische Tabellenstruktur zu übertragen
  • Der erste Teil behandelt ein logisches Modell, das nicht an eine bestimmte Datenbank gebunden ist
    • Geschäftsanforderungen werden unabhängig von MySQL, Postgres, klassischen relationalen Servern, NoSQL und Cloud-Datenbanken modelliert
  • Der spätere Teil zeigt einen möglichen Ansatz, um das logische Modell in physische Tabellen zu überführen
    • Für Systeme mit nicht extrem anspruchsvollen Anforderungen kann dies als brauchbare Designmethode gelten

Problemumfang: Kernfunktionen für Termine in Google Calendar

  • Das Zielsystem ist ein Mehrbenutzersystem; nutzerbezogene Daten werden nur minimal modelliert
  • Events können Attribute wie Titel, Beschreibung und Ort haben, der komplexeste Teil sind jedoch Uhrzeit und Datum
  • Die zu modellierenden Events umfassen folgende Unterschiede
    • Ganztägige Events und zeitbasierte Events
    • Wiederkehrende und nicht wiederkehrende Events
    • Ganztägige Events, die sich über mehrere Tage erstrecken
    • Zeitbasierte Events, die mit Zeitzonen verknüpft sind und deren Start- und Endzeit auf unterschiedlichen Daten oder in unterschiedlichen Zeitzonen liegen können
  • Wiederkehrende Events umfassen folgende Formen
    • Täglich oder alle N Tage wiederkehrend
    • Wöchentlich an bestimmten Wochentagen wiederkehrend, auch mit Intervallen von zwei Wochen oder mehr
    • Monatlich an einem bestimmten Datum oder an einem Wochentag in einer bestimmten Woche des Monats wiederkehrend
    • Jährlich wiederkehrend
    • Unbegrenzt, bis zu einem bestimmten Datum oder nur für eine bestimmte Anzahl von Wiederholungen
  • Eine bestimmte Instanz eines wiederkehrenden Events kann auf ein anderes Datum bzw. eine andere Uhrzeit verschoben oder gelöscht werden
  • Auch nachdem bereits einige Events vergangen sind, muss der wiederkehrende Termin selbst geändert werden können

Anforderungen mit Ankern, Attributen und Links ausdrücken

  • Die Modellierung beginnt damit, zuerst Anker (anchors) zu finden
    • Anker sind Objekte wie User oder Event, die zählbar sind und in die Datenbank aufgenommen werden können
    • Wenn man natürlich sagen kann: „There are 200 Users in our database“ oder „When this button is clicked, a new DayEvent is created“, kann man es als Anker betrachten
  • Attribute speichern konkrete Informationen zu einem Anker
    • User hat ein E-Mail-Attribut
    • DayEvent hat Name, Startdatum und Enddatum
    • Auch ein Event an einem einzelnen Datum speichert Startdatum und Enddatum mit demselben Wert und wird so in derselben Struktur wie mehrtägige Events behandelt
  • Wenn zwei Anker miteinander in Beziehung stehen, verwendet man keinen Attributwert, sondern einen Link
    • „Welcher User hat ein DayEvent erstellt?“ ist kein logisches Attribut, bei dem man die User-ID direkt in DayEvent ablegt, sondern ein Link zwischen User und DayEvent
    • Links verwenden die Kardinalitäten 1:N, M:N und 1:1; ihre Bedeutung in beide Richtungen wird mit zwei Sätzen validiert
  • Zwischen User und DayEvent gibt es einen 1:N-Link
    • Ein User kann mehrere DayEvents erstellen
    • Ein DayEvent wird von genau einem User erstellt

Zeitbasierte Events und Timezone-Behandlung

  • Für zeitbasierte Events werden die Anker Timezone und TimeEvent ergänzt
  • Das Timezone-Modell ist für Zwecke des Tutorials minimal gehalten und enthält nur einen menschenlesbaren Namen als Attribut
    • Beispielwert: Europe/Kyiv
    • In echten Zeitzonendefinitionen bräuchte man UTC-Offset, Sommerzeit-Status, Beginn und Ende der DST, UTC-Offset während der DST, historische Definitionen sowie Aktiv-/Veraltet-Status; dies bleibt jedoch eine separate Aufgabe
  • TimeEvent enthält Name, lokales Startdatum und lokale Startzeit sowie lokales Enddatum und lokale Endzeit
    • Beispielwerte: 2024-01-14 12:30, 2024-01-14 13:15
  • Zeiten werden nicht nur in UTC gespeichert, sondern als vom Benutzer eingegebene lokale Zeit
    • Ein Billardspiel am 6. September 2058 von 09:30 bis 11:00 Uhr in der Zeitzone Cologne sollte beispielsweise genau so gespeichert werden, wie der Benutzer es eingegeben hat, weil der UTC-Offset zu diesem Zeitpunkt heute noch nicht bekannt ist
    • Wenn sich später lokale Gesetze ändern, muss eine entsprechende Anpassung möglich sein
  • TimeEvent hat jeweils einen 1:N-Link zur Timezone für die Start- und die Endzeitzone
    • Wie beim Beispiel eines Flugtickets kann ein Flug von Amsterdam nach London Start- und Ankunftszeiten in unterschiedlichen Zeitzonen haben
    • Die meisten zeitbasierten Events haben dieselbe Start- und Endzeitzone, für den allgemeinen Fall werden jedoch immer beide angegeben

Wiederkehrende ganztägige Events modellieren

  • Wiederkehrende ganztägige Events werden dargestellt, indem DayEvent um wiederholungsbezogene Attribute und Links ergänzt wird
  • Die Wiederholungsfrequenz wird als Attribut vom Typ either/or/or geführt
    • Mögliche Werte sind daily, weekly, monthly, annually
    • Ist kein Wert gesetzt, gilt das Event als nicht wiederkehrend
  • Das Wiederholungsintervall ist ein ganzzahliges Attribut, das nur „bei wiederkehrenden Events“ Bedeutung hat
    • Beispielwert: 2
    • Es wird im Sinne von alle 2 Tage, alle 2 Wochen oder alle 2 Monate verwendet
  • Für monatliche Wiederholungen gibt es ein separates Auswahl-Attribut
    • same_day, um am selben Datum zu wiederholen
    • same_weekday, um am Wochentag derselben Woche des Monats wie das ursprüngliche Datum zu wiederholen
  • Bestimmte Wochentage für wöchentliche Wiederholungen werden nicht als String-Array-Attribut behandelt, sondern als Anker DayOfTheWeek mit M:N-Link modelliert
    • Beispiel-IDs für DayOfTheWeek: Mon, Tue, Wed, Thu, Fri, Sat, Sun
    • Ein DayEvent kann an mehreren DayOfTheWeek auftreten, und ein DayOfTheWeek kann mehrere DayEvents enthalten
  • Auch die Endbedingung für die Wiederholung wird als Attribut geführt
    • forever
    • until_date
    • N_repetitions
    • Bei until_date wird ein Enddatumsattribut ergänzt
    • Bei N_repetitions wird ein Attribut für die Anzahl der Wiederholungen ergänzt

Slots für Rendering und Änderungen einzelner Instanzen

  • Wenn wiederkehrende Events nur als ein einziges ursprüngliches Event gespeichert werden, können Abfragen zum Finden der Events, die in einer bestimmten Wochenansicht angezeigt werden sollen, komplex werden
  • Für das Bildschirm-Rendering und Änderungen einzelner Instanzen wiederkehrender Events wird das Konzept eines Slot eingeführt
    • DaySlot repräsentiert eine ganztägige Event-Instanz an einem bestimmten Datum
    • TimeSlot repräsentiert eine zeitbasierte Event-Instanz an einem bestimmten Datum und zu einer bestimmten Uhrzeit
  • DaySlot enthält Datum und Skip-Status
    • Das Datum eines bestimmten Slots kann geändert werden
    • Wird ein Meeting in einer bestimmten Woche abgesagt, kann der entsprechende DaySlot als skipped markiert werden
  • DayEvent und DaySlot haben einen 1:N-Link
    • Ein DayEvent kann mehrere DaySlots erzeugen
    • Ein DaySlot entspricht genau einem DayEvent
    • Auch für nicht wiederkehrende DayEvents wird immer ein DaySlot erzeugt, um den Rendering-Code zu vereinfachen
  • Bei unendlich wiederkehrenden Events stellt sich die Frage nach dem Bereich, für den Slots erzeugt werden
    • Für ein jährlich auf Dauer wiederkehrendes Event wie einen Geburtstag kann man Slots bis zu einer willkürlichen Grenze wie 100 Jahre erzeugen
    • Alternativ kann man sie on demand erzeugen, wenn der Nutzer eine Kalenderseite in ferner Zukunft anfordert
  • Bei Datumsberechnungen ist Vorsicht geboten
    • Geburtstag am 29. Februar
    • Monatliches Event am 31. jedes Monats
    • In solchen Fällen muss entschieden werden, ob die Nutzung untersagt wird oder ob das Event um einen Tag nach vorn oder hinten verschoben wird

TimeSlot und Zeitzonen

  • Auch bei wiederkehrenden zeitbasierten Events wird derselbe Ansatz wie bei ganztägigen Events angewendet und ein TimeSlot-Anker eingeführt
  • TimeSlot entspricht einer bestimmten Datums- und Zeitinstanz eines bestimmten Events; ein wiederkehrendes TimeEvent entspricht mehreren TimeSlots
  • Die Attribute von TimeSlot sind lokales Startdatum und lokale Startzeit, lokales Enddatum und lokale Endzeit sowie Skip-Status
  • Ein bestimmter TimeSlot kann auch auf einen anderen Tag verschoben werden, daher werden Start- und Endzeitinformationen separat vorgehalten
  • TimeSlot hat ebenfalls jeweils einen 1:N-Link zur Timezone für Start- und Endzeitzone
  • Zwischen TimeEvent und TimeSlot gibt es einen 1:N-Link; auch für nicht wiederkehrende TimeEvents wird ein TimeSlot erzeugt

Fertiges logisches Modell

  • Die bisher definierten Anker sind insgesamt 7
    • User
    • Timezone
    • DayEvent
    • TimeEvent
    • DayOfTheWeek
    • DaySlot
    • TimeSlot
  • Die Attribute bestehen aus User-E-Mail, Timezone-Name, Name/Startdatum/Enddatum/Wiederholungsinformationen von DayEvent, Name/Start- und Endlokalzeit von TimeEvent sowie Auftretenszeitpunkt und skipped-Status von DaySlot und TimeSlot
  • Die Links werden insgesamt zu 10 zusammengefasst
    • User und DayEvent, User und TimeEvent
    • Timezone sowie Start- und Endzeitzone von TimeEvent
    • DayEvent und DayOfTheWeek, TimeEvent und DayOfTheWeek
    • DayEvent und DaySlot, TimeEvent und TimeSlot
    • Timezone sowie Start- und Endzeitzone von TimeSlot

In SQL-Tabellen überführen

  • Das physische Design verwendet zu Lehrzwecken die Strategie eine Tabelle pro Anker
  • Das logische Modell enthält 7 Anker, 21 Attribute und 10 Links
  • Üblicherweise ergäbe die Summe aus Anzahl der Anker und Anzahl der M:N-Links 9 Tabellen; im finalen Design wird DayOfTheWeek jedoch speziell behandelt und keine physische Tabelle dafür erstellt
  • Die finalen SQL-Tabellen sind insgesamt 8
    • users
    • timezones
    • day_events
    • time_events
    • day_slots
    • time_slots
    • day_event_dows
    • time_event_dows
  • 1:N-Links werden als fremdschlüsselartige Spalten in der Tabelle auf der N-Seite aufgenommen
    • day_events.user_id
    • time_events.user_id
    • time_events.start_timezone_id
    • time_events.end_timezone_id
    • day_slots.day_event_id
    • time_slots.time_event_id
    • time_slots.start_timezone_id
    • time_slots.end_timezone_id
  • M:N-Links werden als separate Tabellen angelegt
    • day_event_dows verknüpft DayEvent mit Wochentagen
    • time_event_dows verknüpft TimeEvent mit Wochentagen
  • Physische Typen werden passend zu den logischen Typen gewählt
    • Strings als VARCHAR
    • Datum als DATE
    • Lokales Datum mit Uhrzeit als DATETIME
    • yes/no als TINYINT UNSIGNED
    • Verflochtene Attribute, die nur bedingt Bedeutung haben, verwenden Typen, die NULL erlauben
  • NULL und Sentinel-Werte werden nicht als Konzepte des logischen Modells, sondern des physischen Schemas behandelt

Indizes und ausgelassene Attribute

  • Im Beispiel-SQL-Schema fehlen Indizes, die aus Sicht erfahrener Datenbankentwickler nötig wären
    • Beispielsweise könnte day_events.user_id einen Index benötigen
  • Welche Spalten oder Spaltenkombinationen indiziert werden sollten, hängt davon ab, wie die Anwendung die Tabellen abfragt
  • Zum Thema Indizes kann Use The Index, Luke herangezogen werden
  • Während der Beschreibung des logischen Schemas wurden einige Attribute ausgelassen, weil sie ähnlichen Mustern folgen
    • Benutzername
    • Passwort-Hash des Benutzers
    • Event-Ort
    • Liste eingeladener Personen
  • Ausgelassene Datenelemente können auf dieselbe Weise in die Tabelle des logischen Modells ergänzt und anschließend im SQL-Schema berücksichtigt werden

Gesamtablauf

  • Mit Freitext beginnen, der das Geschäftsproblem beschreibt
  • Eine Liste der Anker erstellen
  • Eine Liste der Attribute erstellen und die Bedeutung jedes Attributs klar in Frageform formulieren
  • Eine Liste der Links erstellen und mit Sätzen prüfen, ob die Kardinalität stimmt
  • Falls nötig, auf Basis des logischen Modells ein grafisches Schema erstellen
  • Das physische Modell erstellen, indem Tabellennamen, Spaltennamen und physische Datentypen eingetragen werden
  • Mit den Informationen aus dem vorherigen Schritt das SQL-Schema als CREATE TABLE-Statements schreiben
  • Das Schema an den Datenbankserver übermitteln, Tippfehler korrigieren und erneut übermitteln
  • Das logische Modell mit dem Team teilen

1 Kommentare

 
GN⁺ 2024-07-25
Hacker-News-Kommentare
  • Wenn ich ein beliebiges Event aus meinem Kalender als iCalendar serialisiere, sind das etwa 740 Byte. Selbst ein extrem voller Kalender mit Events alle 15 Minuten zwischen 9 und 17 Uhr hat über ein ganzes Jahr nur 11.680 Einträge, also rund 8 MB.
    Deshalb wirkt das wie ein Problem, bei dem es viel besser sein könnte, Kalender einfach per sequenziellem Scan zu implementieren, statt ein Schema zu entwerfen. Wenn man den iCalendar-Parser so optimiert, dass er den gedumpten Event-Bereich mit Durchsatz im GB/s-Bereich durchsucht, lässt sich selbst der obige Worst Case in einstelligen Millisekunden scannen.
    Parser-Optimierung ist ein viel einfacheres Problem, das man einmal löst, als ein schlechtes Datenmodell zu ändern oder zu erweitern, nachdem es sich auf viele Nutzer ausgebreitet hat. Und da die erste Aufgabe eines neuen Datenmodells ohnehin wahrscheinlich der Import/Export von iCalendar ist, wirkt das wie ein ziemlich guter Kompromiss.

    • Müsste man dann nicht Bereichssuchen wie BETWEEN ... AND ... in SQL wieder neu bauen? Dasselbe gilt für das Finden der Events der Nutzer 1, 2 und 3.
      In einer echten Anwendung wird es ohnehin schon so etwas wie Nutzerkonten in einer relationalen Datenbank geben; plötzlich muss man dann Events in einem Verzeichnis scannen und die Ergebnisse anschließend mit Datenbankeinträgen verknüpfen.
      Für eine bestimmte Anwendung kann das passen, aber es gibt bestimmte Aufgaben, in denen Datenbanken wirklich gut sind, und deshalb sind sie eine gute Wahl. Mit passenden Indizes dürfte ein ähnlicher oder besserer Durchsatz möglich sein. Es sei denn, man baut eine clevere Verzeichnisstruktur für Events – das ist im Grunde ein eindimensionaler Index, während man in einer Datenbank Indizes über mehrere Dimensionen und Kombinationen von Dimensionen anlegen kann.
      Am Ende stimmt es, und es ist eine Frage des Kompromisses.
    • iCalendar wurde als Austauschformat entworfen, nicht als Speicherformat für schnellen Zugriff auf Kalenderdaten.
      Dem Format sieht man sein Alter an; man merkt, dass es entworfen wurde, bevor XML/JSON „heiß“ wurden.
      Siehe: https://en.wikipedia.org/wiki/ICalendar
    • Man kann es zwar ohne DBMS machen, aber die Daten brauchen trotzdem ein gutes Schema, und das sollte kein Bündel von iCalendar-Records sein. Zum Beispiel gibt es statt stabiler Nutzer-IDs nur änderbare und wiederkehrende E-Mail-Adressen.
    • So ein Ansatz könnte auch eine sauberere Lösung für das im Artikel erwähnte Problem der unendlichen Zeitslots liefern.
  • Ein Artikel darüber, wie man in Anwendungen mit wiederkehrenden Terminen umgeht; mir persönlich hat er die Augen geöffnet. Unbedingt lesenswert: https://github.com/bmoeskau/Extensible/blob/master/recurrenc...

    • Interessant ist, dass die Ratschläge des Originalartikels und dieses Artikels einander widersprechen.
      Der Originalartikel sagt, man solle zu jedem Datum immer die Zeitzone speichern, der verlinkte Artikel sagt, man solle alles nach UTC umwandeln. In diesem Punkt stimme ich dem Originalartikel zu.
      Der Originalartikel sagt, man solle für jedes Event eine Datenbankzeile erzeugen, der verlinkte Artikel sagt, man solle das nicht tun. In diesem Punkt stimme ich dem verlinkten Artikel zu.
  • Mein größter Reinfall in einem Vorstellungsgespräch war, als ich ein einfaches Buchungssystem bauen und dabei auch wiederkehrende Buchungen behandeln sollte.
    Seit den ersten Uni-Jahren war ich beim Versuch, etwas per Code hinzubekommen, nicht mehr so verloren und verwirrt. Bis heute bekomme ich erst einmal Angst, wenn ich mit Datum/Zeit arbeiten muss; aus irgendeinem Grund rastet das in meinem Kopf nicht richtig ein.

    • Die Designfrage „Entwirf ein Buchungssystem, aber mit wiederkehrenden Buchungen“ ist ähnlich wie „Schreibe eine Funktion, die eine Liste von Strings sortiert, aber sie muss für beliebige UTF-8-Strings und alle Locales die jeweiligen alphabetischen Sortierkonventionen einhalten“.
      Es wirkt oberflächlich einfach, wird aber unmöglich komplex, sobald man versucht, es in der realen Welt allgemein funktionierend zu machen.
    • Mach dir nicht zu viele Vorwürfe. Ich bekam einmal die Aufgabe, den Kalender eines CMS zu verbessern und deutlich mehr Funktionen zu unterstützen, und wäre daran fast zerbrochen. Damals hatte ich schon etwa acht Jahre Berufserfahrung.
      Das ist ein trügerisch schwieriges Problem und erfordert hervorragende Datenmodellierungsfähigkeiten.
  • Die Fähigkeit, Systeme zu modellieren, wird unterschätzt. In einer neuen Domäne sollte man mit einer Analyse des gesamten Problems beginnen, um sowohl die statische Struktur des Systems, also das Klassenmodell, als auch das dynamische Verhalten, also die Use Cases, zu erfassen.
    Wenn man direkt in ein statisches Datenbankmodell springt, übersieht man leicht das dynamische Verhalten. Bei solchen einfachen CRUD-Apps mag das in Ordnung sein, bei komplexeren Systemen kann es ein großer Fehler sein.

    • Als Data Scientist hatte ich einige Male in Interviews überraschend große Schwierigkeiten mit scheinbar einfachen Fragen wie „Wie würdest du das Schema dafür bauen?“.
      Die letzte Frage, an die ich mich erinnere, war, wie man eine Produkttabelle mit Coupons aufbauen würde. Zuerst dachte ich, zwei Tabellen würden reichen, aber muss man nicht auch die Historie behalten? Dann muss man Datum/Uhrzeit pro Produkt und Coupon speichern und aktualisieren. Jetzt muss man auch an Tabellenindizes denken und sich fragen, ob ein Join zum Ermitteln des rabattierten Preises eine gute Methode ist. Die meisten Coupons können pro Person nur einmal genutzt werden – wie zum Teufel implementiert man das?
      Vermutlich wollten sie nur eine einfache Produkt- + Coupon-Tabelle, aber ich habe mich allein ewig in immer wildere Details hineingesteigert.
    • Wie sieht das Ergebnis einer solchen Analyse aus? Ich wäre an Referenzlinks interessiert, etwa zu Beispieldokumenten oder Buchkapiteln.
  • Ich finde, das ist eine gut gewählte Domäne, um Modellierung zu zeigen, und ein guter Einstiegsartikel.
    Der Begriff „anchor“ fühlt sich etwas seltsam an, aber die Erklärung ist sehr konkret und bodenständig, wie ein echter Anker, daher funktioniert er wohl gut genug.
    Das Konzept, Attribute über Fragen zu definieren, ist solide. Zu oft springen wir direkt zu einer minimalen Menge von Spalten-/Attributnamen, ohne zu definieren, welche Fragen wir beantworten wollen; damit bekommt man die Unschärfe im Kopf des Kunden nicht heraus. Fragebasierte Attributdefinition ist ein guter Weg, schnell Klarheit zu gewinnen.

    • Der Begriff „anchor“ ist von Anchor Modeling (https://en.wikipedia.org/wiki/Anchor_modeling) geerbt. „Entity“ ist weit verbreitet, aber ich wollte ihn nicht verwenden, weil er unnötigen Ballast und Annahmen mitbringen kann.
      Außerdem ist der Begriff stark überladen. In der Informatik ist im Grunde alles entweder ein Objekt oder eine Entität.
      Die Rückmeldung, dass das Konzept, Attribute über Fragen zu definieren, solide ist, ist eine wichtige Bestätigung für die Tragfähigkeit dieses Ansatzes.
  • Zeitzonen verdrehen einem besonders rund um Umstellungszeitpunkte den Kopf
    Angenommen, eine Zeitzone springt bei der Sommerzeit eine Stunde nach vorn und bei der Rückkehr zur Normalzeit eine Stunde zurück
    Wenn die Zeit eine Stunde nach vorn überspringt, kann ein einstündiges Event auf dem Bildschirm so aussehen, als würde es sich über 2 Stunden erstrecken, und diese zweite Stunde ist unerreichbar oder existiert nicht
    Wenn die Zeit eine Stunde zurückgestellt wird, kann ein einstündiges Event wie 2 Stunden oder wie 0 Stunden aussehen
    Zeitzonen sind ein menschengemachtes Konstrukt, also sollte man Werte nicht hardcoden. Irgendwann ändern sie sich

    • Wenn man dabei auch noch Bewegung berücksichtigt, wird das Nachverfolgen von Zeit noch interessanter. Zum ersten Mal habe ich das erlebt, als ich auf einem Schiff, das mehrere Tage auf See war, die Zeit nachverfolgen musste
      Man kann wiederholt in beide Richtungen Zeitzonen wechseln, auch die Datumsgrenze überqueren, und es ist möglich, dass das lokale Startdatum/die lokale Startzeit nach dem lokalen Enddatum/der lokalen Endzeit liegt
    • Soll das heißen, wir sollten Kalender komplett in UTC und ohne Zeitzonen bauen? Ich stimme zu, dass Zeitzonen von uns gemacht sind, aber sie wurden für eine bessere regionale Organisation geschaffen. Wir arbeiten mit Kunden weltweit, und alle verwenden Zeitzonen. Persönlich wirkt das auf mich wie eine ziemlich absurde Forderung
      Besser wäre es, sich darauf zu konzentrieren, in den wenigen Regionen, die noch Sommerzeit verwenden, das Konzept der Sommerzeit abzuschaffen. Gerade bei der Planung von Terminen nach der nächsten Umstellung verursacht das die meiste Verwirrung zwischen Zeitzonen
  • Ich möchte für ein Event nicht zwei Datumswerte speichern. Es ist einfacher, Startzeit und Dauer des Events zu speichern
    Dadurch wird die Logik zum Aktualisieren von Events einfacher. Die Endzeit kann jederzeit aus Startzeit und Dauer berechnet werden

    • Ehrlich gesagt: Man kann alle drei speichern, also Start, Ende und Dauer, und je nach Zweck das verwenden, was man braucht. Man braucht nur einen einzigen Eintritts-/Aktualisierungspunkt, der die alternativen Darstellungen synchron hält
    • Dieser Ansatz kann bei der Datenbank-Performance Probleme verursachen. Bei jeder Abfrage muss die Dauer ad hoc berechnet werden
    • Gilt das umgekehrt nicht genauso? Wenn man Start und Ende hat, kann man die Dauer einfach berechnen
  • Ich habe früher einmal an einer Kalenderanwendung mit wiederkehrenden Terminen gearbeitet. Nach viel Recherche entschieden wir uns, RRules zu verwenden, um sie darzustellen, und waren sehr zufrieden damit. Diese frühe Arbeit habe ich noch in einer Agentur gemacht
    Als ich später fest zu dem Unternehmen wechselte, war ich erstaunt zu sehen, dass ein Auftragnehmer einer anderen Firma RRules entfernt und stattdessen Event-Instanzen ad hoc erstellt und gelöscht hatte. Das war kaum fehlertolerant: Ein Skript, das nebenbei noch andere Aufgaben erledigte und gelegentlich fehlschlug, konnte dann das Erstellen neuer Events verpassen. Dadurch fehlten bei monatlich wiederkehrenden Events einzelne Monate
    Es war extrem frustrierend, dass jemand etwas entfernte, das mit viel Nachdenken und Recherche entstanden war, ohne selbst annähernd so viel Aufwand zu investieren. Nach ein paar Wochen in diesem Unternehmen war klar, dass der CEO vom Engineering-Team erwartete, nach seinen Vorstellungen ständig Funktionen zu produzieren, die niemand nutzte, und wegen der Unsicherheit am Arbeitsmarkt blieb ich traurigerweise 2 Jahre dort
    Nebenbei: Als ich später nachsah, fand ich auf Glassdoor offensichtlich gefälschte Bewertungen, die vom CEO geschrieben waren, alle im gleichen Stil und ohne ein einziges negatives Wort; das war wirklich bitter. Ich und mehrere Bekannte, die dort gearbeitet hatten, mochten ihn nicht, aber immerhin ist es ein Trost, dass ich in dieser Firma einige meiner besten Essays geschrieben habe. Der CTO war auch hoffnungslos

  • Ich habe einmal ein Kalender- und Ressourcensteuerungs-Backend für eine Low-Code-Plattform implementiert
    Das Control war sehr stark anpassbar und bot neben mehreren Ansichten wie Tages-, Monats- und Jahresansicht auch eine Ressourcenansicht. Ressourcen konnten mit Custom Groups gebucht und nach Plugin, Ressourcen-ID usw. gruppiert werden. In der Datenquelle definierte man „plugins“ sowie Start-/Endspalten, Titelspalte und Ressourcenspalte. Ressourcen konnten aus einem Fremdschlüssel oder einer 1:1-Beziehung stammen, aber auch aus einer 1:N-Beziehung einer „Child“-Datenquelle oder aus derselben Datenquelle/Tabelle
    Außerdem implementierten wir verschiedene Terminserien, etwa monatlich, wöchentlich, an bestimmten Wochentagen oder täglich, und man konnte auswählen, welche Spaltenwerte kopiert werden sollten. Terminkonflikte haben wir ebenfalls behandelt; Konflikte konnten etwa nur dann als solche gelten, wenn dieselbe Ressource gebucht wurde. Vor und nach Terminen ließ sich außerdem ein Puffer konfigurieren, in dem keine anderen Termine liegen durften
    Wegen der europäischen Zeitzonen und Sommer-/Winterzeit war das manchmal herausfordernd, aber es war eine ziemlich interessante Arbeit

  • Was ich mir für Google Calendar wünsche, ist nur ein Änderungsprotokoll des Kalenders selbst. Bitte fügt das endlich der Datenbank hinzu