Condividi tramite



Febbraio 2019

Volume 34 Numero 2

Il presente articolo è stato tradotto automaticamente.

[The Working Programmer]

La codifica di tipo Naked: utenti Naked

Dal Ted Neward | Febbraio 2019

Ted NewardL'ultima parte, ho presentato per il Framework di oggetti Naked (NOF), un framework che esegue la ricerca per nascondere da subito tutte le operazioni per la persistenza dell'interfaccia utente e i dati di oggetti, lasciando per gli sviluppatori di concentrarsi esclusivamente sulla creazione di oggetti di dominio il modo in cui sono ora sempre a scuola , prima di apprendimento di MVC e API Web e HTTP e SQL e database connessione di gestione e dependency injection e tutte le altre cose che cose che consumano la maggior parte del nostro tempo ed energia. È una buona idea, se funziona, ma l'ultimo articolo non sovraccaricare esattamente con le funzionalità. In questo articolo analizzerò un'analisi approfondita in ciò che è possibile definire una classe con NOF e modo in cui che viene convertito nell'interfaccia utente e database di persistenza.

Concetti naked

Prima di entrare troppo lontano nel codice, tuttavia, è possibile acquisire familiarità con alcuni termini NOF, perché fornirà una certa quantità di informazioni relative a come i autori e responsabili della manutenzione dei visualizzare tutto il mondo.

Prima di tutto, al centro dell'intera esperienza sono oggetti di dominio, ovvero gli oggetti che rappresentano lo stato e il comportamento del sistema. In NOF, qualsiasi "plain old C# oggetto" può essere un oggetto di dominio, purché segue alcune regole in modo che NOF può offrire il supporto è necessario: le proprietà devono essere virtuali. tutti i membri della raccolta devono essere inizializzati. e NOF sconsiglia costruttori perché l'oggetto in memoria può avere un ciclo di vita diverso rispetto a cui si è abituati a. Parlerò questa informazioni in un secondo momento.

Non tutto ciò che si adatta bene il paradigma di oggetto, tuttavia. Spesso sono i comportamenti che operano su oggetti, ma non appartengono particolarmente bene all'interno di uno. Piuttosto che prova a forzare i comportamenti in oggetti in modo arbitrario, NOF fornisce il supporto per i servizi, che presentano comportamenti "esterno" degli oggetti, ad esempio creazione, recupero o altre operazioni su oggetti di dominio. Servizi possono inoltre essere utilizzato come un gateway di servizi di sistema esterno come server di posta elettronica.

Dalla prospettiva dell'utente, l'interfaccia utente deve fornire i comportamenti che gli utenti possono attivare e questi sono denominati collettivamente le azioni, che spesso corrispondono ai menu nell'interfaccia utente. Le azioni possono essere individuate (o "ha contribuito con") da una varietà di origini, ma in genere verrà rilevati mediante Reflection con gli oggetti di dominio o i servizi e visualizzati nell'interfaccia utente, come illustrato. È possibile utilizzare gli attributi personalizzati per adattare la maggior parte di questa individuazione e la visualizzazione, quando e dove necessario e si verrà esaminato informazioni di questo man mano che Procedo.

Questo sarà tutto più chiaro tramite codice, in modo che... si è?

Conferenza naked

Nella serie MEAN, ho utilizzato un esempio di dominio semplice (relatori recapito interventi a una conferenza) come sfondo per la compilazione di codice e sembra ragionevole usare lo stesso esempio qui, se per nessuna altra ragione anziché confrontare mele da Apple. Man mano che procede di modelli di dominio, sarà piuttosto semplice: Relatori costituiti da nome, cognome, age, gli argomenti (C#, Visual Basic, Java, JavaScript, TypeScript e C++) e la classificazione Media (da zero a cinque), per iniziare. In un secondo momento è possibile aggiungere presentazioni, che avranno un titolo e descrizione, quando viene visualizzato come configurare le relazioni tra oggetti, ma è possibile mantenerla semplice per il momento.

Come accennato nell'ultimo articolo, inizierò con il file ZIP modello degli, come i valore di inizializzazione da cui iniziare, scaricare in modo che tramite il collegamento in GitHub degli progetto README (bit.ly/2PMojiQ), decomprimere il file in una sottodirectory appena creata, e aprire la soluzione in Visual Studio. A questo punto aprire il nodo del progetto Template.Model ed eliminare i file Student.cs ed ExampleService.cs; non si vuole archiviare dopo che tutti gli studenti. Ciò che si desidera archiviare siano relatori (e presentazioni successive, ma sarà trattato il refactoring in un secondo momento, per vedere come NakedObjects supporterà il refactoring).

Per maggiore chiarezza, devo eseguire un paio di aspetti per supportare gli altoparlanti come un tipo di dominio in un progetto di oggetti Naked: È necessario creare il tipo di dominio. È necessario verificare di che avere un oggetto del Repository per ottenere e crearle; È necessario assicurarsi che un repository viene resa disponibile per il framework di oggetti Naked per generare i menu. e, infine, è necessario (oppure, per essere onesti, da) per effettuare il seeding del database con alcuni degli altoparlanti.

Oggetti del relatore

Compilare la classe relatore è effettivamente il più semplice i quattro passaggi. Nel progetto Template.Model, creare un file Speaker.cs e in tale file, all'interno dello spazio dei nomi Template.Model, creare una classe pubblica denominata relatore. Relatori sono definiti (per il momento) dal nome, cognome e l'età, quindi, creare tre proprietà per questi, ma contrassegnarli "virtuali"; si tratta in modo che in fase di esecuzione NakedObjects può rallentare alcuni comportamenti aggiuntivi nella posizione (tramite una sottoclasse) che esegue il comando magic desiderato.

Aggiungiamo qualche complessità per il relatore, tuttavia. Prima di tutto, è spesso necessario un identificatore non correlato alla dominio per gli oggetti archiviati in un database che può essere usato come chiave primaria, senza consentire agli utenti di utilizzare o modificare tale identificatore. Nel sistema NakedObjects, è possibile contrassegnare qualsiasi proprietà con un attributo personalizzato "NakedObjectsIgnore" in modo che non verrà visualizzato nell'interfaccia utente, aggiungiamo un numero intero proprietà "Id" (nuovo virtuale) che è contrassegnato con questo attributo. Inoltre, non comune per creare una proprietà che è "calcolata" con altri elementi di dati, quindi, aggiungiamo una proprietà di sola lettura "FullName" che consente di concatenare il nome e cognome. Poiché NakedObjects non dovrà essere responsabile per la modifica all'interfaccia utente in questo, senza dover essere virtuale.

Al termine, deve essere lasciata con codice simile al seguente:

public class Speaker
{
  [NakedObjectsIgnore]
  public virtual int Id { get; set; }

  public virtual string FirstName { get; set; }
  public virtual string LastName { get; set; }
  public virtual int Age { get; set; }

  [Title]
  public string FullName { get { return FirstName + " " + LastName; } }
}

Fin qui tutto bene.

Repository del relatore

Un oggetto repository, per chi non ha familiarità con il modello, è essenzialmente un oggetto che rappresenta l'accesso al database, che fornisce le chiamate di metodo semplice per le richieste di database standard. Nel sistema NakedObjects, un oggetto del repository è un tipo di servizio, ovvero un oggetto riconosciuto in particolare da NakedObjects come un oggetto che non è un oggetto di dominio, ma può fornire elementi dell'interfaccia utente e il comportamento per conto del sistema. In questo caso, il repository fornirà alcune voci di menu per il recupero di relatori all'esterno del database, ordinati, ad esempio, in base al cognome.

In pratica, un servizio NakedObject è semplicemente un'altra classe, ma potrebbe avere qualcosa non la classe dell'altoparlante: un riferimento a un oggetto IDomainObjectContainer, ovvero un oggetto fornito dal framework NakedObjects che a sua volta consente di accedere al resto del sistema. Nella documentazione di NakedObjects viene assegnato l'elenco dei servizi di sistema disponibili, ma in particolare che mi interessano due elementi: il metodo NewTransientInstance, che consente di costruire un nuovo oggetto relatore e collegarla vantaggi il resto del NakedObjects infrastruttura per l'utilizzo; e il metodo di istanze, che restituirà il set completo di relatore oggetti dal database. Di conseguenza, un SpeakerRepository minimo è simile a quanto illustrato in figura 1.

Figura 1 la classe SpeakerRepository

public class SpeakerRepository
{
  public IDomainObjectContainer Container { set; protected get; }

  public Speaker CreateNewSpeaker()
  {
    // 'Transient' means 'unsaved' - returned to the user
    // for fields to be filled in and the object saved.
    return Container.NewTransientInstance<Speaker>();
  }

  public IQueryable<Speaker> AllSpeakers()
  {
    return Container.Instances<Speaker>();
  }
}

Si noti che entrambi i metodi istanze e il NewTransientInstance sono funzioni generiche, accettando il tipo di oggetto che cui stanno lavorando come parametro di tipo per la chiamata di funzione. (Si tratta di
necessaria perché il DomainObjectContainer possibile e verrà usato per un'ampia gamma di tipi di oggetti di dominio diverso, non solo gli altoparlanti.)

Un repository che crea una nuova voce appena e ottiene un elenco di tutti gli elementi non è particolarmente utile, rimane invariata. è spesso opportuno recuperare gli oggetti con determinati quelle escluse, o in un ordine particolare. Qui è dove la potenza di LINQ ed Entity Framework all'interno di framework NakedObjects rende la sua presenza ritenuto. Poiché il metodo AllSpeakers restituisce un'interfaccia IQueryable, è possibile usare i metodi LINQ per filtrare e/o ordinare gli oggetti restituiti, in modo che se desidera trovare relatori in base al cognome, è possibile semplicemente aggiungere tale metodo alla classe di repository, l'utilizzo di LINQ in base alle esigenze filtrare i risultati :

public class SpeakerRepository
{
  // ... as before

  public IQueryable<Speaker> FindSpeakerByLastName(string name)
  {
    return AllSpeakers().
      Where(c => c.LastName.ToUpper().Contains(name.ToUpper()));
  }
}

Qualsiasi che scopo, LINQ, è possibile esprimere come un metodo nel repository.

Contesto del relatore

Due altre attività di manutenzione dettagli: che è necessario occuparsi: È necessario configurare il DbContext di Entity Framework che verrà usato dal motore di persistenza NakedObject e devo per associare il SpeakerRepository nell'interfaccia utente in modo posso avere voci di menu per creare nuove voci, trovare gli altoparlanti esistenti e così via.

Il primo viene trovato nel progetto Template.DataBase, nella finestra di ExampleDbContext.cs file (il cui nome è possibile modificare se è importante per l'utente), nella classe ExampleDbContext. Come proprietà pubbliche su tale classe, un DbSet dovrà disporre di parametri per il tipo di voce denominato "Relatori", nel modo seguente:

namespace Template.DataBase
{
  public class ExampleDbContext : DbContext
  {
    public ExampleDbContext(string dbName,
      IDatabaseInitializer<ExampleDbContext> initializer) : base(dbName)
    {
      Database.SetInitializer(initializer);
    }

    public DbSet<Speaker> Speakers { get; set; }
  }
}

Aggiunta di più tipi di oggetti di dominio di primo livello per il sistema, sarà necessario aggiungere ulteriori proprietà qui che restituiscono un elemento DbSet, ma per ora, questo è tutto ciò che devo.

Se si desidera eseguire l'inizializzazione con alcune voci per avviare il database, è necessario aprire il progetto Template.SeedData e trovare il ExampleDbInitializer.cs file e scrivere il metodo di inizializzazione (che è già definito in tale file) per aggiungere alcuni oggetti di relatore di violare il ExampleDbContext (l'oggetto è appena stato rielaborato nel paragrafo precedente) tramite i relatori DbSet, come illustrato nella figura 2.

Aggiunta di oggetti di relatore a DbContex la figura 2

public class ExampleDbInitializer : 
  DropCreateDatabaseIfModelChanges<ExampleDbContext>
{
  private ExampleDbContext Context;
  protected override void Seed(ExampleDbContext context)
    {
    this.Context = context;

    Context.Speakers.Add(new Speaker() {
      FirstName = "Ted", LastName = "Neward", Age = 47
    });
  }
}

Si tratta di semplice codice di Entity Framework, in modo che qualsiasi trattazione dettagliata su come modificare i criteri di creazione/eliminazione del database rientrano in set di documentazione di Entity Framework.

È l'ultima posizione in cui che si desidera inserire il codice nel progetto Template.Server, nel file NakedObjectsRunSettings.cs; Questo codice è una raccolta di registrazione "hook" o "suggerimenti" per il sistema NakedObjects, che descrive cosa è necessario conoscere il NakedObjectsFramework. Ad esempio, se si decide che "Template.Model" è un terribile dello spazio dei nomi per gli oggetti modello per questa app conference, quindi è possibile modificarla, purché il ModelNamespaces di questo NakedObjectsRunSettings rifletta anche il nome modificato.

Per quanto riguarda il SpeakerRepository, è necessario comunicarlo NakedObjects, aggiungerlo alla matrice del tipo "Servizi". Se desidera che i metodi SpeakerRepository accessibili tramite un'opzione di menu, anche necessario indicare NakedObjects per esaminare il SpeakerRepository per le azioni da utilizzare come voci di menu, quindi, devo includerlo come parte della matrice di voci di menu restituiti dal metodo MainMenus , come illustrato nella figura 3.

Figura 3 NakedObjects impostazioni esecuzione test

public class NakedObjectsRunSettings
{
  // ...

  private static Type[] Services
  {
    get
    {
      return new Type[] {
        typeof(SpeakerRepository)
      };
    }
  }

  // ...

  public static IMenu[] MainMenus(IMenuFactory factory)
  {
    return new IMenu[] {
      factory.NewMenu<SpeakerRepository>(true, "Menu")
    };
  }
}
}

Dopo che queste modifiche sono presenti, posso attivate i progetti, visualizziamo il client e creare alcune voci. Si noti che viene visualizzata la proprietà FullName, costituito da FirstName e LastName, ma non viene visualizzato l'Id. Inoltre, grazie al metodo FindSpeakersByLastName sul SpeakerRepository, è possibile cercare voci in base al cognome e se viene restituito più di uno, il client riconosce automaticamente come presentare un elenco di queste impostazioni che può essere selezionato per lavoro individuale.

Conclusioni

Si noti che in nessun punto di questo articolo ha eseguire alcuna operazione per il modello. Progetto client, che rappresenta il punto. L'interfaccia utente viene costruito a partire dagli oggetti di dominio e servizi, con informazioni aggiuntive fornite dagli attributi personalizzati (che verrà illustrata più nei prossimi articoli). La persistenza, in modo analogo, costituita dalla struttura e i metadati che consente di individuare il framework tra i tipi.

Cosa è necessario vedere, ora in poi, è come NOF gestisce gli scenari più complessi di dominio, ovvero come relatori presenza di un elenco di oggetti che si può parlare e una raccolta di poter trasmettere le presentazioni, e come presenta un'interfaccia utente per tali. Nel prossimo articolo, esaminerò alcuni di questi argomenti. Nel frattempo, tuttavia... buona codifica!


Ted Neward è un consulente polytechnology basato su Seattle, relatore e mentore. Ha scritto una considerevole quantità di articoli, creati e una dozzina libri ed legge tutto il mondo. Contattarlo all'indirizzo ted@tedneward.com o il suo blog blogs.tedneward.com.


Discutere di questo articolo nel forum di MSDN Magazine