Wann ist primitive Obsession kein Codegeruch?


22

Ich habe in letzter Zeit viele Artikel gelesen, die primitive Obsession als Code-Geruch beschreiben.

Es gibt zwei Vorteile, wenn man primitive Obsessionen vermeidet:

  1. Dadurch wird das Domänenmodell expliziter. Beispielsweise kann ich mit einem Geschäftsanalysten über eine Postleitzahl anstelle einer Zeichenfolge sprechen, die eine Postleitzahl enthält.

  2. Die gesamte Validierung findet an einer Stelle statt in der gesamten Anwendung.

Es gibt viele Artikel, die beschreiben, wann es sich um einen Codegeruch handelt. Zum Beispiel kann ich den Vorteil der Beseitigung der primitiven Obsession für eine Postleitzahl wie diese sehen:

public class Address
{
    public ZipCode ZipCode { get; set; }
}

Hier ist der Konstruktor des ZipCodes:

public ZipCode(string value)
    {
        // Perform regex matching to verify XXXXX or XXXXX-XXXX format
        _value = value;
    }

Sie würden das DRY- Prinzip brechen, indem Sie diese Validierungslogik überall dort einsetzen, wo eine Postleitzahl verwendet wird.

Was ist jedoch mit den folgenden Objekten:

  1. Geburtsdatum: Vergewissern Sie sich, dass das Geburtsdatum größer als der Mindate und kleiner als das heutige Datum ist.

  2. Gehalt: Überprüfen Sie, dass größer oder gleich Null ist.

Würden Sie ein DateOfBirth-Objekt und ein Salary-Objekt erstellen? Der Vorteil ist, dass Sie bei der Beschreibung des Domänenmodells darüber sprechen können. Ist dies jedoch ein Fall von Überentwicklung, da es nicht viele Validierungen gibt? Gibt es eine Regel, die beschreibt, wann und wann primitive Obsessionen beseitigt werden sollen, oder sollten Sie dies nach Möglichkeit immer tun?

Ich schätze, ich könnte einen Typalias anstelle einer Klasse erstellen, was bei Punkt eins oben helfen würde.


8
"Sie würden das DRY-Prinzip brechen, wenn Sie diese Validierungslogik überall dort einsetzen, wo eine Postleitzahl verwendet wird." Das ist nicht wahr. Die Validierung sollte erfolgen, sobald die Daten in Ihr Modul eingegeben wurden . Wenn es mehr als einen "Einstiegspunkt" gibt, sollte die Validierung in einer wiederverwendbaren Einheit erfolgen , und das muss nicht der DTO sein (und sollte es auch nicht sein) ...
Timothy Truckle

1
Wie gibst du dem Konstruktor "mindate" und "today date", DateOfBirthdamit er es vergleicht?
Caleth

11
Ein weiterer Vorteil beim Erstellen benutzerdefinierter Typen ist die Typensicherheit. Wenn Sie Salaryund DistanceGegenstand haben, können Sie sie nicht versehentlich austauschbar verwenden. Sie können, wenn sie beide vom Typ sind double.
Scroog1

3
@ w0051977 Ihre Aussage (wie ich sie verstanden habe) implizierte, dass alles andere als die Validierung im DTOs-Konstruktor gegen DRY verstoßen würde. Tatsächlich ist die Validierung sollte außerhalb sein die DTO ...
Timothy Truckle

2
Für mich ist alles eine Frage des Umfangs. Wenn Sie Primitiven einen weiten Bereich geben, gibt es zahlreiche Möglichkeiten, wie sie missbraucht und missbraucht werden können. Sie möchten ihnen im Allgemeinen einen engeren Rahmen geben. Eine Möglichkeit, dies zu tun, besteht darin, eine Klasse zu entwerfen, die ein Konzept darstellt, indem ein primitives Element verwendet wird, das privat als internes Element gespeichert wird, um es zu implementieren. Jetzt ist der Umfang des Grundelements eng und es ist unwahrscheinlich, dass es missbraucht / misshandelt wird, und Sie können Invarianten effektiv aufrechterhalten. Aber wenn der Anwendungsbereich des Primitivs am Anfang eng war, könnte dies übertrieben sein und eine Menge zusätzlicher Kopplung und Code einführen, die beibehalten werden müssen.

Antworten:


17

Primitive Obsession verwendet primitive Datentypen, um Domänenideen darzustellen.

Das Gegenteil wäre "Domain Modeling" oder vielleicht "Over Engineering".

Würden Sie ein DateOfBirth-Objekt und ein Salary-Objekt erstellen?

Die Einführung eines Salary-Objekts kann aus folgendem Grund sinnvoll sein: Zahlen stehen im Domain-Modell selten für sich, sie haben fast immer eine Dimension und eine Einheit. Normalerweise modellieren wir nichts Nützliches, wenn wir einer Zeit oder Masse eine Länge hinzufügen, und wir erzielen selten gute Ergebnisse, wenn wir Meter und Fuß mischen .

Bei DateOfBirth sind wahrscheinlich zwei Punkte zu beachten. Wenn Sie ein nicht-primitives Datum erstellen, können Sie zunächst alle seltsamen Aspekte der Datumsberechnung in den Mittelpunkt stellen. Viele Sprachen bieten eine sofort einsatzbereite Lösung. DateTime , java.util.Date . Dies sind domänenunabhängige Implementierungen von Datumsangaben, aber keine primitiven Elemente.

Zweitens DateOfBirthist nicht wirklich eine Datumszeit; Hier in den USA ist "Geburtsdatum" ein kulturelles Konstrukt / eine gesetzliche Fiktion. Wir neigen dazu, das Geburtsdatum anhand des lokalen Geburtsdatums einer Person zu messen . Bob, geboren in Kalifornien, könnte ein "früheres" Geburtsdatum haben als Alice, geboren in New York, obwohl er der jüngere von beiden ist.

Gibt es eine Regel, die beschreibt, wann und wann primitive Obsessionen beseitigt werden sollen oder sollten Sie dies nach Möglichkeit immer tun?

Sicher nicht immer; an den grenzen sind anwendungen nicht objektorientiert . Primitive werden häufig verwendet, um das Verhalten in Tests zu beschreiben .


1
Der erste Kommentar nach dem Zitat oben scheint keine Folge zu sein. Darüber hinaus wird nur das Thema der Frage neu formuliert. Ansonsten ist es eine gute Antwort, aber ich finde das wirklich ablenkend.
JimmyJames

Weder C # DateTime noch java.util.Date sind geeignete zugrunde liegende Typen für DateOfBirth.
Kevin Cline

Vielleicht ersetzen java.util.Datedurchjava.time.LocalDate
Koray Tugay

7

Um ehrlich zu sein: es kommt darauf an.

Es besteht immer die Gefahr, dass Ihr Code überarbeitet wird. Wie weit verbreitet sind Geburtsdatum und Gehalt? Verwenden Sie sie nur in drei eng gekoppelten Klassen oder werden sie in der gesamten Anwendung verwendet? Würden Sie sie "nur" in ihren eigenen Typ / Klasse einkapseln, um diese eine Einschränkung zu erzwingen, oder können Sie sich mehr Einschränkungen / Funktionen vorstellen, die tatsächlich dazugehören?

Nehmen wir zum Beispiel Gehalt: Haben Sie Operationen mit "Gehalt" (z. B. Umgang mit verschiedenen Währungen oder vielleicht eine toString () - Funktion)? Überlegen Sie, was Gehalt ist / tut, wenn Sie es nicht als einfaches Grundelement betrachten, und es besteht eine gute Chance, dass Gehalt seine eigene Klasse ist.


Ist ein Typ-Alias ​​eine gute Alternative?
w0051977

@ W0051977 Ich stimme mit Charonx überein und Typ Alias ​​könnte eine Alternative sein
Techagrammer

@ w0051977 Ein Typ-Alias ​​kann eine Alternative sein, wenn das primäre Ziel darin besteht, eine strikte Eingabe zu erzwingen und explizit anzugeben, was ein bestimmter Wert ist (Gehalt), um eine versehentliche Zuweisung von "Float-Dollars" (pro Stunde, Woche, Monat) zu vermeiden "Floatgehalt" (pro Monat? Jahr?). Es kommt wirklich darauf an, was Sie brauchen.
CharonX

@CharonX, ich glaube, eine Dezimalstelle sollte für ein Gehalt verwendet werden und kein Float. Sind Sie einverstanden?
w0051977

@ w0051977 Wenn Sie einen guten Dezimaltyp haben, ist dieser bevorzugt, ja. (Ich arbeite gerade an einem C ++ - Projekt, daher stehen Boolesche Werte, Ganzzahlen und Gleitkommazahlen im Vordergrund meines Gedankens.)
CharonX

5

Eine mögliche Faustregel kann von der Ebene des Programms abhängen. Für die Domain (DDD) aka Entities Layer (Martin, 2018) könnte dies auch bedeuten, "Primitive für alles zu vermeiden, was ein Domain- / Geschäftskonzept darstellt". Die Begründungen lauten wie im OP: ein aussagekräftigeres Domänenmodell, die Validierung von Geschäftsregeln, die explizite Darstellung impliziter Konzepte (Evans, 2004).

Ein Typ-Alias ​​kann eine einfache Alternative sein (Ghosh, 2017) und bei Bedarf zu einer Entitätsklasse umgestaltet werden. Zum Beispiel können wir zunächst , dass verlangen Salarysei >=0, und später entscheiden, nicht zuzulassen $100.33333oben und etwas $10,000,000(was den Client bankrott wäre). Die Verwendung von NonnegativePrimitiven zur Darstellung Salaryund anderer Konzepte würde dieses Refactoring erschweren.

Das Vermeiden von Grundelementen kann auch dazu beitragen, eine Überentwicklung zu vermeiden. Angenommen, wir müssen Gehalt und Geburtsdatum in einer Datenstruktur kombinieren , um z. B. weniger Methodenparameter zu haben oder Daten zwischen Modulen zu übertragen. Dann können wir ein Tupel mit Typ verwenden (Salary, DateOfBirth). In der Tat ist ein Tupel mit Primitiven (Nonnegative, Nonnegative)nicht informativ, während einige aufgeblähte class EmployeeDataFelder unter anderem die erforderlichen Felder verbergen würden. Die Signatur in say calcPension(d: (Salary, DateOfBirth))ist fokussierter als in calcPension(d: EmployeeData), was gegen das Prinzip der Schnittstellentrennung verstößt. Ebenso class SalaryAndDateOfBirthscheint ein Spezialist umständlich und ist wahrscheinlich ein Overkill. Später können wir eine Datenklasse definieren. Tupel und elementare Domänentypen lassen uns solche Entscheidungen aufschieben.

In einer äußeren Schicht (z. B. GUI) kann es sinnvoll sein, die Entitäten auf ihre einzelnen Grundelemente zu "zerlegen" (z. B. in ein DAO einzufügen). Dies verhindert, dass Domänenabstraktionen in äußere Schichten gelangen, wie in Martin (2018) vertreten.

Literaturverzeichnis
E. Evans, "Domain-Driven Design", 2004
D. Ghosh, "Functional and Reactive Domain Modeling", 2017
RC Martin, "Clean architecture", 2018


+1 für alle Referenzen.
w0051977

4

Lieber unter primitiver Obsession leiden oder Architekturastronaut sein ?

Beide Fälle sind pathologisch, in einem Fall gibt es zu wenig Abstraktionen, was zu einer Wiederholung führt und leicht dazu führt, dass ein Apfel für eine Orange gehalten wird, und in dem anderen Fall haben Sie vergessen, bereits damit aufzuhören und Dinge zu erledigen, was es schwierig macht, etwas zu erledigen .

Wie fast immer möchten Sie Mäßigung, einen hoffentlich gut durchdachten Mittelweg.

Denken Sie daran, dass eine Eigenschaft zusätzlich zu einem Typ einen Namen hat. Außerdem kann das Zerlegen einer Adresse in ihre Bestandteile zu einschränkend sein, wenn immer auf die gleiche Weise vorgegangen wird. Nicht die ganze Welt ist in der Innenstadt von NY.


3

Wenn Sie eine Gehaltsklasse hatten, könnte diese über Methoden wie ApplyRaise verfügen.

Auf der anderen Seite muss Ihre ZipCode-Klasse nicht über eine interne Validierung verfügen, um zu vermeiden, dass die Validierung überall dort dupliziert wird, wo eine ZipCodeValidator-Klasse injiziert werden kann. Wenn Ihr System also sowohl für US- als auch für UK-Adressen ausgeführt werden soll, können Sie die einfach injizieren korrekter Validator und wenn Sie auch AUS-Adressen bearbeiten müssen, können Sie einfach einen neuen Validator hinzufügen.

Wenn Sie Daten über EntityFramework in eine Datenbank schreiben müssen, müssen Sie außerdem wissen, wie mit Gehalt oder Postleitzahl umgegangen wird.

Es gibt keine eindeutige Antwort darauf, wo die Grenze zwischen intelligenten Klassen gezogen werden sollte, aber ich werde sagen, dass ich Geschäftslogik wie die Validierung auf Geschäftslogikklassen verlagere, bei denen die Datenklassen scheinbar reine Daten sind um besser mit EntityFramework zu arbeiten.

Bei der Verwendung von Typ-Aliasen sollte der Name des Elements / der Eigenschaft alle erforderlichen Informationen zum Inhalt enthalten, damit ich keine Typ-Aliasen verwende.


Ist ein Typ-Alias ​​eine gute Alternative?
w0051977

2

(Was ist die Frage wahrscheinlich wirklich)

Wann ist die Verwendung des primitiven Typs kein Codegeruch?

(Antworten)

Wenn der Parameter keine Regeln enthält, verwenden Sie einen primitiven Typ.

Verwenden Sie den primitiven Typ für:

htmlEntityEncode(string value)

Verwenden Sie ein Objekt für:

numberOfDaysSinceUnixEpoch(SimpleDate value)

Das letztere Beispiel haben Regeln darin, das heißt das Objekt SimpleDatebesteht aus Year, Monthund Day. Durch die Verwendung von Object kann in diesem Fall das Konzept der SimpleDateGültigkeit in das Objekt eingeschlossen werden.


1

Abgesehen von den kanonischen Beispielen für E-Mail-Adressen oder Postleitzahlen, die an anderer Stelle in dieser Frage angegeben sind, kann das Umgestalten außerhalb von Primitive Obsession besonders hilfreich sein, wenn Entity-IDs verwendet werden (siehe https://andrewlock.net/using-strongly-typed-entity -ids-to-avoid-primitive-obsession-part-1 / für ein Beispiel, wie es in .NET gemacht wird).

Ich habe die Anzahl verloren, wie oft sich ein Fehler eingeschlichen hat, weil eine Methode die folgende Signatur hatte:

int leaveId = 12345;
int submitterId = 23456;
int approverId = 34567;

SubmitLeaveApplication(leaveId, approverId, submitterId);

public void SubmitLeaveApplication(int leaveId, int submitterId, int approverId) {
  // implementation here
}

Kompiliert einwandfrei, und wenn Sie Ihre Unit-Tests nicht rigoros durchführen, besteht dies möglicherweise auch. Ordnen Sie diese Entitäts-IDs jedoch in domänenspezifische Klassen um, und hey presto, Kompilierungsfehler:

LeaveId leaveId = 12345;
SubmitterId submitterId = 23456;
ApproverId approverId = 34567;

SubmitLeaveApplication(leaveId, approverId, submitterId);

public void SubmitLeaveApplication(LeaveId leaveId, SubmitterId submitterId, ApproverId approverId) {
  // implementation here
}

Stellen Sie sich vor, diese Methode skaliert auf 10 oder mehr Parameter, alle intDatentypen ( unabhängig vom Geruch der langen Parameterliste ). Es wird noch schlimmer, wenn Sie zum Austauschen zwischen Domänenobjekten und DTOs so etwas wie AutoMapper verwenden und ein Refactoring durchführen wird vom automagischen Mapping nicht erfasst.


0

Sie würden das DRY-Prinzip brechen, indem Sie diese Validierungslogik überall dort einsetzen, wo eine Postleitzahl verwendet wird.

Wenn Sie jedoch mit vielen verschiedenen Ländern und deren unterschiedlichen Postleitzahlensystemen zu tun haben, können Sie eine Postleitzahl nur dann validieren, wenn Sie das betreffende Land kennen. Ihre ZipCodeKlasse muss also auch das Land speichern.

Aber speichern Sie das Land dann separat als Teil Addressder Postleitzahl (zu der auch die Postleitzahl gehört) und als Teil der Postleitzahl (zur Validierung)?

  • Wenn Sie dies tun, verletzen Sie auch DRY. Selbst wenn Sie es nicht als DRY-Verletzung bezeichnen (weil jede Instanz einem anderen Zweck dient), verbraucht es unnötigerweise zusätzlichen Speicher, und es öffnet sich die Tür für Fehler, wenn die beiden Länderwerte unterschiedlich sind (was sie logischerweise niemals sollten) Sein).
    • Oder alternativ müssen Sie die beiden Datenpunkte synchronisieren, um sicherzustellen, dass sie immer gleich sind. Dies legt nahe, dass Sie diese Daten wirklich an einem einzigen Punkt speichern sollten, um den Zweck zu umgehen.
  • Wenn Sie dies nicht tun, dann ist es keine ZipCodeKlasse, sondern eine AddressKlasse, die wieder eine enthält, string ZipCodewas bedeutet, dass wir den Kreis geschlossen haben.

Beispielsweise kann ich mit einem Geschäftsanalysten über eine Postleitzahl anstelle einer Zeichenfolge sprechen, die eine Postleitzahl enthält.

Der Vorteil ist, dass Sie bei der Beschreibung des Domänenmodells darüber sprechen können.

Ich verstehe Ihre zugrunde liegende Behauptung nicht, dass Sie, wenn eine Information einen bestimmten Variablentyp hat, irgendwie verpflichtet sind, diesen Typ zu erwähnen, wenn Sie mit einem Geschäftsanalysten sprechen.

Warum? Warum können Sie nicht einfach über "die Postleitzahl" sprechen und den bestimmten Typ komplett weglassen? Welche Art von Gesprächen führen Sie mit Ihrem (nicht technischen!) Geschäftsanalysten, bei denen die Art der Immobilie für das Gespräch ausschlaggebend ist?

Woher ich komme, sind Postleitzahlen immer numerisch. Wir haben also die Wahl, wir könnten es als intoder als speichern string. Wir neigen dazu, eine Zeichenfolge zu verwenden, da keine mathematischen Operationen für die Daten zu erwarten sind, aber noch nie von einem Geschäftsanalysten angegeben wurde, dass es sich um eine Zeichenfolge handeln muss. Diese Entscheidung ist dem Entwickler überlassen (oder wohl dem technischen Analysten, obwohl er sich meiner Erfahrung nach nicht direkt mit dem Problem auseinandersetzt).

Ein Geschäftsanalyst kümmert sich nicht um den Datentyp, solange die Anwendung das tut, was von ihr erwartet wird.


Validierung ist ein schwieriges Unterfangen, da es sich auf das stützt, was Menschen erwarten.

Zum einen stimme ich dem Validierungsargument nicht zu, um zu zeigen, warum primitive Besessenheit vermieden werden sollte, da ich nicht der Meinung bin, dass (als universelle Wahrheit) Daten immer zu jeder Zeit validiert werden müssen.

Was ist zum Beispiel, wenn dies eine kompliziertere Suche ist? Was passiert, wenn Sie bei der Validierung keine einfache Formatprüfung durchführen, sondern eine externe API kontaktieren und auf eine Antwort warten? Möchten Sie Ihre Anwendung wirklich dazu zwingen, diese externe API für jedes von ZipCodeIhnen instanziierte Objekt aufzurufen ?
Vielleicht ist es eine strenge Geschäftsanforderung, und dann ist es natürlich gerechtfertigt. Dies ist jedoch keine universelle Wahrheit. Es wird viele Anwendungsfälle geben, in denen dies eher eine Belastung als eine Lösung darstellt.

Als zweites Beispiel, wenn Sie Ihre Adresse in ein Formular eingeben, ist es üblich, Ihre Postleitzahl vor Ihrem Land einzugeben. Es ist zwar schön, ein sofortiges Feedback zur Validierung in der Benutzeroberfläche zu haben, aber es würde mich (als Benutzer) tatsächlich behindern, wenn die Anwendung mich auf ein "falsches" Postleitzahlformat aufmerksam macht, da die eigentliche Ursache des Problems (z. B.) darin besteht Mein Land ist nicht das Land, das standardmäßig ausgewählt ist. Daher wurde die Validierung für das falsche Land durchgeführt.
Es ist die falsche Fehlermeldung, die den Benutzer ablenkt und unnötige Verwirrung stiftet.

Genauso wie die ständige Validierung keine universelle Wahrheit ist, sind es auch meine Beispiele. Es ist kontextabhängig . Einige Anwendungsdomänen erfordern vor allem eine Datenüberprüfung. In anderen Domänen steht die Validierung nicht so weit oben auf der Prioritätenliste, da der damit verbundene Aufwand im Widerspruch zu den tatsächlichen Prioritäten steht (z. B. Benutzererfahrung oder die Möglichkeit, fehlerhafte Daten zunächst zu speichern, damit sie korrigiert werden können, anstatt sie niemals zuzulassen) gelagert)

Geburtsdatum: Vergewissern Sie sich, dass das Geburtsdatum größer als der Mindate und kleiner als das heutige Datum ist.
Gehalt: Überprüfen Sie, dass größer oder gleich Null ist.

Das Problem bei diesen Validierungen ist, dass sie unvollständig, redundant sind oder auf ein viel größeres Problem hinweisen .

Das Überprüfen, ob ein Datum größer als der Mindate ist, ist überflüssig. Der Mindate bedeutet wörtlich, dass es das kleinstmögliche Datum ist. Und wo ziehen Sie die relevante Linie? Was bringt es, zu verhindern, DateTime.MinDateaber zu erlauben DateTime.MinDate.AddSeconds(1)? Sie wählen einen bestimmten Wert aus, der im Vergleich zu vielen anderen Werten nicht besonders falsch ist.

Mein Geburtstag ist der 2. Januar 1978 (ist es nicht, aber nehmen wir an, es ist es). Angenommen, die Daten in Ihrer Bewerbung sind falsch. Stattdessen heißt es, dass ich Geburtstag habe:

  • 1. Januar 1978
  • 1. Januar 1722
  • 1. Januar 2355

Alle diese Daten sind falsch. Keiner von ihnen ist "richtiger" als der andere. Ihre Validierungsregel würde jedoch nur eines dieser drei Beispiele aufgreifen.

Sie haben auch den Kontext, wie Sie diese Daten verwenden, vollständig weggelassen. Wenn dies zB in einem Geburtstagserinnerungs-Bot verwendet wird, würde ich sagen, dass die Validierung sinnlos ist, da es keine besonders schlechten Konsequenzen gibt, wenn ein falsches Datum eingegeben wird.
Handelt es sich hingegen um Regierungsdaten und benötigen Sie das Geburtsdatum, um die Identität einer Person zu bestätigen (und wenn Sie dies nicht tun, hat dies schlimme Konsequenzen, z. B. die Verweigerung der sozialen Sicherheit einer Person), ist die Richtigkeit der Daten von größter Bedeutung und muss vollständig überprüft werden Überprüfen Sie die Daten. Die vorgeschlagene Validierung, die Sie jetzt haben, ist nicht ausreichend.

Für ein Gehalt gibt es einen gesunden Menschenverstand, der nicht negativ sein kann. Wenn Sie jedoch realistisch davon ausgehen, dass unsinnige Daten eingegeben werden, würde ich vorschlagen, dass Sie die Quelle dieser unsinnigen Daten untersuchen. Denn wenn Sie nicht vertrauen können, dass sie sensible Daten eingeben, können Sie auch nicht vertrauen, dass sie korrekte Daten eingeben .

Wenn stattdessen das Gehalt von Ihrer Bewerbung berechnet wird und es irgendwie möglich ist, eine negative (und korrekte) Zahl zu erhalten, ist es besser Math.Max(myValue, 0), negative Zahlen in 0 umzuwandeln, als die Validierung nicht zu bestehen. Denn wenn Ihre Logik entscheidet, dass das Ergebnis eine negative Zahl ist, bedeutet ein Fehlschlagen der Validierung, dass die Berechnung erneut durchgeführt werden muss, und es besteht kein Grund zu der Annahme, dass beim zweiten Mal eine andere Zahl erstellt wird.
Und wenn es zu einer anderen Zahl kommt, können Sie wiederum vermuten, dass die Berechnung nicht konsistent ist und daher nicht als vertrauenswürdig eingestuft werden kann.

Dies soll nicht heißen, dass die Validierung nicht nützlich ist. Aber sinnlose Validierung ist schlecht, weil sie Mühe kostet, während sie ein Problem nicht wirklich löst, und den Menschen ein falsches Sicherheitsgefühl vermittelt.


Das Geburtsdatum einer Person kann tatsächlich nach dem aktuellen Datum liegen, wenn ein Baby gerade in einer Zeitzone geboren wird, die bereits auf den nächsten Tag verschoben wurde. Und ein Krankenhaus könnte "erwartete Geburtsdaten" in einer Datenbank speichern, die Monate in der Zukunft sein könnte. Möchten Sie einen anderen Typ dafür?
gnasher729

@ gnasher729: Ich bin mir nicht ganz sicher, ob ich folge, anscheinend stimmen Sie mir zu (die Validierung ist kontextbezogen und nicht allgemein korrekt), aber die Formulierung Ihres Kommentars legt nahe, dass Sie der Meinung sind, dass ich nicht einverstanden bin. Oder lese ich falsch?
Flater
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.