Dieser Artikel wurde maschinell übersetzt.

Programmiererpraxis

Erste Schritte mit Oak: Datenvalidierung und Zusammenfassung

Ted Neward

Ted NewardFür drei Spalten jetzt ich habe bereits erkundet den "Dynamik-y" Objekt-Ansatz, den Eiche an der Web-Anwendung-Raum bringt, und es war eine interessante Fahrt, komplett mit ein paar Herausforderungen der lang gehegte Überzeugungen über wie Webanwendungen erstellt werden müssen (oder über die Plattform, auf der sie gebaut sind). Aber jeder Fahrt irgendwann zu Ende gegangen muss, und es an der Zeit ist, meine Erforschung der Eiche einpacken. Ich muss herausfinden, wie man sicherstellen, dass Daten in das System vom Benutzer tatsächlich gute Daten für den Anfang.

Aber zuerst...

Kommentar

Wenn Sie zurück und sehen Sie sich das System, wie ich letztes Mal aufgehört, ergibt versucht einen Kommentar hinzufügen ein weiterer diese hilfreiche Fehler dieser Zeit, die Sie darüber informiert, dass "Blog.Controllers.Blog keine Definition für"AddComment."" Im Gegensatz zu dem, was man in einem statisch typisierte System geschehen — wo das Fehlen dieser Methode wäre einen Kompilierungsfehler auf der Vorderseite des Kreislaufs kompilieren/bereitstellen/Run trip — in einem dynamischen System wird nicht diese Fehler gesehen werden, bis sie tatsächlich versucht haben. Einige dynamische Sprache-Befürworter behaupten, dies ist Teil des Charmes der dynamischen Sprachen und sicherlich keinen zu kümmern alles konsistent im gesamten System kann ein großer Segen sein, wenn der Verstand auf Feuer mit einer Idee ist und du musst nur diese Idee in die Welt raus. Aber die meisten Ruby on Rails-Entwickler, ich weiß, die größer als die typische Todo-Liste-Anwendung ein Projekt getan hast werden das erste zugeben, dass in einer dynamischen Sprache Anwendung umfangreiche Tests zum halten des Projekts Qualität hoch und des Entwicklers Vernunft stark entscheidend sind. Also testen muss ein Bestandteil jeder ernsthafte Versuch mit Eichenlaub.

Leider sobald ich sprechen über Tests beginnen, in mehrere Bereiche der Diskussion (Unit-Tests, Verhalten-Tests, Integrationstests, Testgetriebene Entwicklung und So weiter), die leicht ein weiteres halbes Dutzend magazine Ausgaben allein beanspruchen könnte anfangen, und ich will nicht die Büchse der Pandora hier zu knacken. Was auch immer Ihr Test Methodik oder Präferenz, es genügt zu sagen, dass Sie müssen haben eine Art Prüfung Präsenz in einer Eiche Anwendung (oder einer beliebigen Anwendung, sondern die Notwendigkeit ist viel höher in jeder dynamisch typisierte Umgebung), jedoch Sie testen möchten.

Inzwischen ist die AddComment-Methode immer noch vermisst.

Kommentar weg

In diesem speziellen Fall wenn der Benutzer einen Kommentar in die Ansicht eingibt, stellen es der HomeController Kommentare-Methode, welche so aussieht:

[HttpPost]
public ActionResult Comments(dynamic @params)
{
  dynamic blog = blogs.Single(@params.BlogId);
  blog.AddComment(@params);
  return RedirectToAction("Index");
}

Wie Sie sehen können, ist der Controller zunächst versteckt im BlogId Parameter kommen aus dem Formular, und dann benutzen, um den entsprechenden Blogeintrag über die einzige Methode auf der DynamicRepository finden Blog-ID abrufen Blog aufrufen.AddComment um den Kommentar zu speichern. (Wieder nur um die Punkte, "pro" und "Con" zu machen: Dieser Code ist seit dem zweiten Teil dieser Serie in Platz, und ich laufe gerade jetzt in der Tatsache, dass die AddComment-Methode bis jetzt existierte noch nicht.)

Es ist ziemlich einfach, diese Methode zu definieren; Fügen Sie auf der Blog-Klasse diese Methode:

void AddComment(dynamic comment)
{
  // Ignore addition if the body is empty
  if (string.IsNullOrEmpty(comment.Body)) return;
  // Any dynamic property on this instance can be accessed
  // through the "_" property
  var commentToSave = _.NewComment(comment);
  comments.Insert(commentToSave);
}

Das einzige wirkliche Fragezeichen in dieser Methode ist die Verwendung des Unterstrichs (_.NewComment(comment)), das ist ein Platzhalter für die "diese" Referenz. Der Unterstrich hat Kenntnis von der Dynamik der dieses Objekt, das der "diesen" Verweis würde nicht; anstatt die Unterschiede sorgen, kann der Unterstrich Sie alles verwenden würde "das", plus mehr.

Beachten Sie, wie Sie die Dynamik des Systems extrem sparsam im Code werden kann. Die Formularparameter werden erfasst, in einem benannten Bundle in "@params" kommen in den Controller, und die sind ohne Auspacken davon direkt in Add­Kommentar, die wiederum übergibt sie in NeuerKommentar, die ein dynamisches Objekt daraus erstellt, und das resultierende Objekt wird einfach in die Kommentare DynamicRepository eingefügt. Woher kommen die Namen der Eigenschaften des Objekts? Aus dem HTML-Formular stammt, die all dies.

Wacky, hm? Fast fühlt sich an wie Sie faul sind oder so.

Wie auch immer, geben sie einen Lauf, und sicher genug, jetzt Kommentare hinzugefügt werden.

Mich zu überprüfen

Wie geschrieben, aber das System hat ein schwerwiegendes Manko (Na ja, nach Ihren Anforderungen, wie auch immer): Es ist durchaus zulässig, dass zwei Blog-Einträge zu den exakten gleichen Titel haben, und das ist nicht OK. (Leser vielleicht verwirrt, die man zu lesen, der mit dem Titel "LOL Kittehs" oder eines mit dem Titel "LOL Kittehs.") Daher benötigen Sie eine Möglichkeit zur Durchsetzung einer Art Eindeutigkeit für den Code, so dass Benutzer nicht versehentlich in Duplikat mit dem Titel Blogeinträgen geschaffen.

In einem traditionellen Web-Framework wäre dies eine zweiteilige Arbeit. Zunächst müsste das Modellobjekt (Blog) definieren eine Art "Fragen mich, wenn ich gültig bin"-Methode, die ich aus Mangel an etwas wirklich originelles IsValid nennen werde, und eine Definition der genannten Validierung innerhalb des Objekts, das nenne ich überprüft. Und, wie man aus der Art vermuten könnte die Associates-Methode gearbeitet, um helfen, definieren die Verbindung zwischen Blog und Kommentare-Objekte (d. h., es ist ein vordefinierter Name für die Eiche weiß aussehen), die überprüft-Methode funktioniert auf die gleiche Weise — wenn ein Objekt eine Methode überprüft definiert, dann Eiche rufen die bereits definierten IsValid-Methode auf das Objekt, das wiederum wird suchen Sie nach einer Methode überprüft und bitten es für alle Bedingungen, die dieses Objekt gültig machen.

Im Code sieht das so aus:

IEnumerable<dynamic> Validates()
{
  // And define the association
  // For other examples of validations, check out the Oak wiki
  yield return new Uniqueness("Name", blogs);
}

Wieder sehen Sie die Verwendung eines Streams von Objekten, die Validierungsanforderungen gab zurück als IEnumerable < dynamische > beschreiben in den Stream, die Benutzung der "Yield return" Anlage von c# generiert werden. Und, wie mit der Schema-Klasse vom letzten Mal die Möglichkeit, dies zu erweitern, tack nur auf zusätzliche Elemente, die "Rendite zurückgegebenen," wie folgt:

IEnumerable<dynamic> Validates()
{
  // And define the association
  // For other examples of validations check out the Oak wiki
  yield return new Uniqueness("Name", blogs);
  yield return new Length("Name") { Minimum=10, Maximum=199 };
}

Das Oak-Wiki definiert, die vollständige Liste und die Verwendung von Validierung-Objekten, aber einige der wesentlichen sind:

  • Präsenz: Ein Feld ist nicht optional und muss auf das Objekt vorhanden sein.
  • Akzeptanz: Ein Feld für das Objekt muss einen bestimmten Wert enthalten, z. B. ein LegalDocument-Objekt mit einem TypedOutAcceptance-Feld, in dem der Benutzer die Zeichenfolge eingegeben "Ich akzeptiere" zur Angabe, er akzeptiert die gesetzlichen Beschränkungen.
  • Ausschluss: Ein Feld kann nicht bestimmte Werte enthalten.
  • Aufnahme: Ein Feld muss einer aus einer Reihe bestimmter Werte sein.
  • Format: Die universell einsetzbare reguläre Ausdrücke (mit der Microsoft .NET Framework Regex-Klasse) Validierung.
  • Numericality: Ziemlich alles zu tun mit numerischen Werten, einschließlich markiert ein Feld als "ganze Zahl nur," größer -­und weniger-als Beschränkungen oder einfache gerade/ungerade-Tests.
  • Bedingte: Die Catch-All "Notluke" für eine Validierung nicht abgedeckt anderswo — ein Feld muss eine Bedingung mit einem Lambda-Funktion beschrieben erfüllen.

Die letzte Bedingung ist nicht wirklich eine Validierung geben, in und von sich selbst, sondern ein Feature präsentieren auf den meisten (wenn nicht alle) von den anderen Arten der Validierung und verdient deshalb ein wenig mehr Erläuterung. Stellen Sie sich ein Order-Objekt, für Bestellungen in einem herkömmlichen e-Commerce-System. Bei diesen Systemen ist eine Kreditkartennummer nur erforderlich, wenn der Benutzer eine Kreditkarte zur Zahlung verwenden möchte. Ebenso ist eine Adresse, an die das Produkt versenden nur erforderlich, wenn der Benutzer etwas anderes als digitaler Download gekauft. Diese beiden Möglichkeiten sind ordentlich in Form von zwei bedingte Überprüfungen, wie in Abbildung 1.

Abbildung 1 Bedingte Validierung

public class Order : DynamicModel
{
  public Order()
  {
  }
  public IEnumerable<dynamic> Validates()
  {
    yield return new Presence("CardNumber") {
      If = d => d.PaidWithCard()
    };
    yield return new Presence("Address") {
      Unless = d => d.IsDigitalPurchase()
    };
  }
  public bool PaidWithCard()
  {
    // Could use This().PaymentType instead
    return _.PaymentType == "Card";
  }
  public bool IsDigitalPurchase()
  {
    // Could use This().ItemType instead
    return _.ItemType == "Digital";
  }
}

Jedes der bedingten Objekte macht Verwendung einer Eigenschaft für die Präsenz-Objekt — zusammen mit einen Lambda-Ausdruck, der einen wahr/falsch-Wert ergibt — an, ob das Vorhandensein erfolgreich überprüft. Im ersten Fall gibt Präsenz (Pass) d.PaidWithCard, eine lokale Methode, die true zurückgegeben, wenn das PaymentType-Feld "Karte," gleich true zurückgibt. Im zweiten Fall Präsenz gibt true zurück, wenn IsDigitalPurchase gibt true zurück, was bedeutet, dass keine Adresse handelt es sich um einen digitalen Artikel, notwendig ist.

All dies sind bereit für den Einsatz mit jedem Eiche DynamicModel abgeleitetes Objekt, und, wie erwähnt in der vorherigen Spalte (msdn.microsoft.com/magazine/dn519929) und in der Einleitung dieses Jahres, der DynamicModel -­abgeleitetes Objekt muss nicht explizit definieren Sie die Felder, die diese Überprüfungen zu verweisen. Diese Überprüfungen nicht ausreichen, um die Aufgabe sein, übrigens, werden diese alle in die Validations.cs-Datei im Ordner Eiche des gestaffelten Projekts definiert. Es ist ziemlich einfach, eine neue zu definieren, falls gewünscht: Nur von Oak.Validation erben Sie, und definieren Sie mindestens eine Validate-Methode, die wahr/falsch zurückgibt. Die Ausschluss-Validierung ist beispielsweise:

public class Exclusion : Validation
{
  public Exclusion(string property)
    : base(property)
  {
  }
  public dynamic[] In { get; set; }
  public bool Validate(dynamic entity)
  {
    return !In.Contains(PropertyValueIn(entity) as object);
  }
}

Die In-Eigenschaft in diesem Code ist das Feld, in dem die ausgeschlossenen Werte gespeichert werden; Darüber hinaus ist dies ziemlich einfach. Wenn eine beschreibende Fehlermeldung enthalten sein muss, stellt die Validierung einer Basiseigenschaft ErrorMessage, in denen eine beschreibende Meldung für den Einsatz gespeichert werden kann, wenn die Validierung fehlschlägt bereit.

(Für diejenigen, die über die "Verbände" in den Datenbank-Diskussionen letzte Mal neugierig sind, sind diese in Association.cs im selben Ordner definiert, abgeleitet von Oak.Association, und — wie zu erwarten — sind etwas schwieriger zu erklären. Glücklicherweise hat Eiche die meisten der traditionellen relationalen Verbände bereits definiert, es sollte nicht so viel Notwendigkeit hier anpassen.)

Stücke aus Eiche

Manchmal scheinen die Teile einer Bibliothek wirklich cool, aber Hindernisse entgegenstehen, übernehmen die ganze Sache und Sie wünschte, Sie könnte einen kleinen Teil davon Rippen und weiter. Während es in der Regel besser, Eiche als Ganzes zu verwenden ist, unterstützt es die Idee der Rippen Bits davon (z. B. die dynamische Datenbank-Teile, oder vielleicht gerade die dynamische Objekt-Teile, namens Gemini, die ich in der Ausgabe vom August 2013 abgedeckt, bei msdn.microsoft.com/magazine/dn342877) und verwenden sie eigenständig, ohne den Rest des Systems. Die Eiche-GitHub-Seite zum Thema (bit.ly/1cjGuou) hat die NuGet-Pakete für jeden der die eigenständige Eiche Teile, reproduziert hier (zum Zeitpunkt des Schreibens) für Ihre Bequemlichkeit:

  • Installationspaket Eiche: Das ist die volle Eiche Suite, es umfasst MVC Modell Sammelmappen, Schemagenerierung, Eiche-DynamicModel und unterstützende Klassen, eine geänderte Version der Massive (DynamicRepository) und der Eiche Kern dynamische konstruieren Gemini.
  • Installationspaket Eiche-Json: Dies ist der Teil der Eiche im Hinblick auf JSON Serialisierung (kann in anderen APIs verwendet werden).
  • Installationspaket Kambium: Dies ist der Teil der Eiche, das schließt die MVC-spezifische Komponenten und schließt Schemagenerierung. Kambium enthält die Eiche DynamicDb, DynamicModel, eine geänderte Version der Massive (dynamische­Repository) und die Eiche Kern-Dynamik konstruieren Gemini.
  • Installationspaket Samen: Dies ist die Schema-Generation aus Eiche. Dieses NuGet-Paket enthält auch die geänderte Version der Massive (zum Beispieldaten einfügen). Es enthält das MVC-Modell-Sammelmappen oder Eiche DynamicModel oder unterstützende Klassen nicht.
  • Installationspaket Zwillinge: Dadurch wird nur das Kern dynamisches Konstrukt installiert, auf dem alle die dynamische Güte in Eiche aufbaut.

Bevor Sie versuchen, eine davon in Stücken, würde ich vorschlagen, versucht die ganze Erfahrung, um ein Gefühl für wie jeder von ihnen in das größere Bild passen zu erhalten.

Vorteile, Kosten und Schmerzen

Wie aus diesen vier Spalten abgeleitet werden könnte, gibt es bestimmte Vorteile zu der Möglichkeit, nur "improvisieren" und arbeiten mit einem mehr dynamisch typisierte System. Ohne Frage Kosten und Schmerzen löst in einem solchen System (vor allem für die unvorsichtigen, und die nicht verwendete zu schreiben Tests) zum Vorschein, sondern erfahren auch, wer die meisten diehard statisch typisierte Fanatiker sind einige wertvollen Ideen von einem System wie Eiche. Noch wichtiger ist, Eiche kann ein äußerst wertvolles Werkzeug für das Prototyping die frühe Entwicklung eines Systems, wenn das Objektmodell noch sehr veränderlich und nicht definiert ist. Bestes von allen, dank der zugrunde liegenden Plattform Eiche (d. h. .NET), wird es durchaus möglich, darauf bauen eine MVC-app in Eiche in den frühen Phasen, dann langsam flipping Teile davon über eine statisch typisierte (und somit Compiler überprüft und Compiler erzwungen) geht, wie die Einzelheiten der Anwendung Get mehr eng gesperrt.

Persönlich, ohne Zweifel, ist Eiche ein cooles kleines Projekt. Meiner Meinung nach ist dies eine jener Zeiten, wenn eine ganze Reihe von interessanten Funktionen und Ideen kommen aus einem ziemlich klein (relativ gesehen) Paket. Eiche, geht auf jeden Fall in meinem persönlichen Werkzeugkasten Tricks.

Viel Spaß beim Programmieren!

Ted Neward , Geschäftsführer von Neward & Associates LLC, hat mehr als 100 Artikel geschrieben und als Autor und Mitautor ein Dutzend Bücher verfasst, darunter „Professional F# 2.0“ (Wrox 2010). Er ist ein F#-MVP und spricht auf Konferenzen in der ganzen Welt. Er berät und hilft regelmäßig – Sie können ihn unter ted@tedneward.com erreichen, wenn Sie möchten, dass er in Ihrem Team mitarbeitet, oder lesen Sie seinen Blog unter http://blogs.tedneward.com.

Unser Dank gilt dem folgenden technischen Experten für die Durchsicht dieses Artikels: Amir Rajan (Initiator des Oak-Projekts)
Amir Rajan ist der Schöpfer der Eiche. Er ist aktives Mitglied der Entwicklungsgemeinschaft und verfügt über Expertise in ASP.NET MVC, HTML5, REST-Architekturen, Ruby, JavaScript/CoffeeScript, NodeJS, iOS/ZielC und f#. Rajan ist eine wahre Polyglot mit einer unerschütterlichen Leidenschaft für Software. Er ist auf Twitter bei @amirrajan und im Internet unter github.com/amirrajan, amirrajan.net und improvingenterprises.com.