2009-02-09 9 views
5

Angenommen, ich habe ein Objekt, das eine Person darstellt, mit Getter- und Setter-Methoden für die E-Mail-Adresse der Person. Die Setter-Methode Definition könnte wie folgt aussehen:Wie gehen Sie mit Strings um, die strukturiert sind?

setEmailAddress(String emailAddress) 
    { 
    this.emailAddress = emailAddress; 
    } 

Aufruf person.setEmailAddress(0), dann, einen Typfehler erzeugen würde, aber Aufruf person.setEmailAddress("asdf") würde nicht - obwohl „asdf“ in keiner Weise Adresse eine gültige E-Mail ist.

Nach meiner Erfahrung sind so genannte Strings fast nie beliebige Folgen von Zeichen, ohne Beschränkung auf Länge oder Format. URIs kommen mir in den Sinn - genauso wie Straßenadressen, Telefonnummern und Vornamen ... Sie haben die Idee. Diese Datentypen werden jedoch meistens als "nur Zeichenfolgen" gespeichert.

zu meiner Person Objekt zurückkehrend, nehme ich an setEmailAddress() ändern wie so

setEmailAddress(EmailAddress emailAddress) 
    // ... 

wo EmailAddress eine Klasse ... für dessen Konstruktor eine String-Darstellung einer E-Mail-Adresse. Habe ich etwas gewonnen?

OK, so eine E-Mail-Adresse ist ein schlechtes Beispiel. Was ist mit einer URI-Klasse, die eine Zeichenfolgendarstellung eines URI als Konstruktorparameter akzeptiert und Methoden zum Verwalten dieses URI bereitstellt - den Pfad festlegen, einen Abfrageparameter abrufen usw. Die Gültigkeit der Quellzeichenfolge wird wichtig.

Also frage ich euch alle, wie gehen Sie mit Strings um, die Struktur haben? Und wie machen Sie Ihre strukturellen Erwartungen an Ihren Schnittstellen deutlich?

Vielen Dank.

Antwort

2

Willkommen in der Programmierwelt!

Ich glaube nicht, dass Ihre Frage ein Symptom für einen Fehler auf Ihrer Seite ist. Vielmehr ist es ein Grundproblem, das in vielen Gestalten in der Programmierwelt erscheint. Zeichenfolgen mit einer gewissen Struktur und , die bedeuten, werden zwischen verschiedenen Subsystemen einer Anwendung weitergegeben und jedes Subsystem kann nur viel Parsing und Validierung durchführen.

Das Problem der E-Mail-Adresse, zum Beispiel der Überprüfung, ist ziemlich schwierig. Die regulären Ausdrücke, die verschiedene Personen anbieten, die zum Beispiel eine E-Mail-Adresse akzeptieren, sind im Allgemeinen entweder "zu eng" (nicht alles akzeptieren) oder "zu locker" (illegale Dinge akzeptieren).The first google hit für ‚regex‚E-Mail-Adresse‘‘, zum Beispiel sagt:

Der reguläre Ausdruck ich die meisten Feedback erhalten, nicht auf „Bug“ Berichte zu erwähnen, ist diejenige, die Sie rechts auf finden Homepage dieser Site: \ b [A-Z0-9 ._% + -] + @ [A-Z0-9 .-] +. [AZ] {2,4} \ b Analysieren Sie diesen regulären Ausdruck mit RegexBuddy . Dieser reguläre Ausdruck, I Anspruch, stimmt mit jeder E-Mail-Adresse überein. Am meisten des Feedbacks ich widerrufe, dass Anspruch durch Anzeigen einer E-Mail-Adresse , dass diese Regex nicht übereinstimmt.

Tatsache ist das, was ist oder keine gültige E-Mail-Adresse ist ein komplexes Problem, eine, die ein bestimmtes Programm könnte oder vielleicht nicht will, zu lösen. Das Problem der URLs ist noch schlimmer, besonders angesichts der Möglichkeit von bösartigen URLs.

Idealerweise können Sie eine Bibliothek oder einen Systemaufruf haben, der Probleme dieser Art löst, anstatt selbst etwas zu tun (Microsoft Windows ruft ein benutzerdefiniertes Dialogfeld auf, damit der Benutzer eine Datei auswählen oder erstellen kann, da die Dateinamen überprüft werden) ein weiteres kniffliges Problem). Aber Sie können nicht immer damit rechnen, dass Sie einen passenden Systemaufruf für eine bestimmte "aussagekräftige Zeichenfolge" haben.

Ich würde sagen, dass es keine generische Lösung für das Problem der Strings-mit-Struktur gibt. Es ist vielmehr ein grundlegendes Problem, das beim Entwerfen Ihrer Anwendung angezeigt wird. In dem Prozess von gathering requirements für Ihre Anwendung sollten Sie bestimmen, welche Daten die Anwendung einnimmt und wie sinnvoll, dass Daten an die Anwendung sein werden. Und das ist der Punkt, an dem die Dinge schwierig werden, da Sie vielleicht die Möglichkeit bemerken, dass die App so wächst, wie es Ihrem Chef oder Kunden vielleicht nicht eingefallen ist - oder dass die App tatsächlich auf eine Weise wächst, an die niemand von Ihnen gedacht hat. So muss die Anwendung eine kleine flexibler als was scheint das Minimum, aber nur ein wenig sein. Es sollte auch nicht so flexibel sein, dass Sie stecken bleiben.

Nun, wenn Sie entscheiden, dass Sie eine gegebene Zeichenfolge validieren/interpretieren müssen usw., kann das Einfügen dieser Zeichenfolge in ein Objekt oder einen Hash ein guter Ansatz sein - dies ist eine Möglichkeit, um sicherzustellen, dass Ihre Schnittstelle klar ist. Aber die schwierige Sache ist die Entscheidung, wie viel Validierung oder Interpretation Sie benötigen.

Diese Entscheidungen zu treffen, ist also eine Kunst - hier gibt es keine dogmatischen Antworten.

+0

Ursprünglich akzeptierte ich Morendils Antwort, aber nach einigem Nachdenken und Nachlesen habe ich beschlossen, deins zu akzeptieren. Es ist nicht so, dass ich mit Morendil nicht einverstanden bin, aber Ihre Antwort ist allgemeiner, weniger dogmatisch und eher im Einklang mit der Art von Diskussion, die ich anregen wollte. Vielen Dank! – Metaphile

2

Dies ist ein ziemlich häufiges Problem, das unter den Titel 'validation' fällt - es gibt viele Möglichkeiten, Texteingabe zu validieren, eine der häufigsten ist Regular Expressions.

Sie könnten auch die integrierte System.Net.MailAddress-Klasse in Betracht ziehen, da diese eine Validierung für E-Mail-Adressen bietet.

1

Strings sind Strings. Wenn Sie Ihre Strings intelligenter als durchschnittliche Strings benötigen, dann ist es eine gute Idee, sie in ein strukturelles Objekt zu zerlegen, wie Sie es beschreiben. Ich würde eine Regex verwenden, um das zu tun.

0

Nun, wenn Sie mehrere verschiedene Dinge mit einem EmailAddress-Objekt ausführen möchten, müssen diese anderen Aktionen nicht überprüfen, ob es sich um eine gültige E-Mail-Adresse handelt, da das EmailAddress-Objekt garantiert eine gültige Zeichenfolge hat. Sie könnten eine Exception in den Konstruktor werfen oder eine Factory-Methode oder eine andere "One True Methodology" -Ansatz verwenden, die Sie verwenden.

+0

Ich würde empfehlen, eine Ausnahme auf Validierungsfehler zu werfen - Ausnahmen sind für Ausnahmefälle, und schlechte Benutzereingaben sind definitiv * nicht * außergewöhnlich. Ich scheue mich auch davor, Ausnahmen in Konstruktoren zu werfen, aber das ist aus meinen eigenen Gründen. –

+0

Rechts. :) Wie immer hängt alles von Ihrer speziellen Propagandamarke ab. – BobbyShaftoe

+0

* zuckt mit den Schultern * Best Practices, Propaganda; wie auch immer du es nennen willst. ;) Lol –

9

"Strings mit Struktur" sind ein Symptom des allgemeinen Code-Geruchs "Primitive Obsession".

Die Abhilfe besteht darin, genau auf Duplizierung im Code zu achten, der Teile dieser Strukturen validiert oder manipuliert. Beim ersten Hinweis auf Duplizierung - aber nicht vorher - extrahieren Sie eine Klasse, die die Struktur kapselt und dort Validierungen und Abfragen findet.

+0

+1 - sehr weiser Rat. –

+0

ahhhhh nicht die "code smell" Phrase ... <- runs and hides – BobbyShaftoe

+0

Ja, Sie können fast immer die Struktur Ihres Codes verbessern, indem Sie die häufigsten primitiven typisierten Variablen in neue Typen einbinden. –

0

Persönlich mag ich die Idee des starken Schreibens, also wenn ich noch in solchen Sprachen arbeiten würde, würde ich mit dem Stil Ihres zweiten Beispiels gehen.Die einzige Sache, die ich ändern würde, könnte eine "Cast-like" Struktur sein, wie EmailAddressFromString(String), die ein neues EmailAddress Objekt erzeugte (oder eine Anpassung lieferte, wenn die Zeichenfolge nicht richtig war), da ich ein bisschen bin ein Fan der Anwendung Ungarische Notation.

Dieses ganze Problem ist übrigens von Joel in http://www.joelonsoftware.com/articles/Wrong.html ziemlich gut abgedeckt, wenn Sie interessiert sind.

1

Reguläre Ausdrücke sind Ihr Freund, wenn es darum geht, Strings zu formatieren. Sie können jedes Teil auch separat in einer Struktur speichern, um zu vermeiden, dass Sie jedes Mal, wenn Sie sie verwenden möchten, reguläre Ausdrücke verwenden müssen. z.B.

struct EMail 
{ 
    String BeforeAt = "johndoe123"; 
    String AfterAt = "gmail.com"; 
} 

Struct URL 
{ 
    String Protocol = "http"; 
    String Domain = "sub.example.com"; 
    String Path = "stuff/example.html"; 
} 
0

ich mit den Anrufen einverstanden stark das Objekt zu geben, aber für diejenigen Fälle, wo Sie aus einer Zeichenfolge zu einem Objekt sind Parsen, die Antwort ist einfach: Fehlerbehandlung.

Es gibt zwei Wege, um Fehler zu umgehen: Ausnahmen und Bedingungen zurückzukehren. Im Allgemeinen sollten Sie eine Fehlermeldung erhalten, wenn Sie schlecht formatierte Daten erwarten. Für Fälle, in denen die Eingabe nicht erwartet wird, würde ich eine Ausnahme auslösen. Beispielsweise könnten Sie eine schlecht gestaltete E-Mail-Adresse wie "bob" anstelle von "[email protected]" eingeben. Für Nullwerte können Sie jedoch eine Ausnahme auslösen, da Sie nicht versuchen sollten, eine E-Mail-Adresse zu erstellen, die nicht null ist.

Zurück zu Ihrer Frage, ich glaube, Sie gewinnen etwas durch die Codierung einer Struktur in ein Objekt. Insbesondere müssen Sie nur überprüfen, dass die Zeichenfolge eine gültige E-Mail-Adresse an einem bestimmten Ort darstellt, z. B. den Konstruktor. An anderer Stelle kann Ihr Code frei davon ausgehen, dass ein EmailAddress-Objekt gültig ist, und Sie müssen sich nicht auf fragwürdige Klassen mit Namen wie 'EmailHelper' oder ähnlichem verlassen.

0

Ich persönlich denke nicht, dass die Eingabe der E-Mail-Adresse als EmailAddress stark ist, in diesem Fall.

Um Ihre E-Mail-Adresse erstellen Sie werden, früher oder später, haben wie etwas zu tun:

EmailAddress(String email) 

oder Setter

SetEmailAddress(String email) 

In beiden Fällen werden Sie das bestätigen müssen E-Mail-String-Eingabe, die Sie wieder in das ursprüngliche Validierungsproblem versetzt.

Ich würde, wie andere darauf hingewiesen haben, reguläre Ausdrücke verwenden.

Eine EmailAddress-Klasse wäre nützlich, wenn Sie bestimmte Operationen mit Ihren gespeicherten Informationen später ausführen möchten (sagen Sie nur Domain-Namen, solche Sachen).

Verwandte Themen