Skip to content

afra demo application

felix-b edited this page Oct 11, 2016 · 2 revisions

NOTE: This page is still being written

DISCLAIMER: This documentation refers to milestone Boda, which is currently in early stages of development. Some or all of the features mentioned here may not yet exist, or be unstable.

Milestone Afra demo application

This page demonstrates how much can be done with just a declaration of a simple domain model, and a minimal UIDL spec - all together less than 300 lines of code.

Code listings presented on this page are based on planned features of milestone Boda, while the screenshots are taken from a similar application built on NWheels milestone Afra, which can be found here: https://github.com/felix-b/NWheels/tree/afra/Source/NWheels.Samples.MyMusicDB.

The next sections contain:

  • Code of the domain model (using the DDD framework)
  • Code of client app UIDL spec (using the UIDL framework)
  • Contents of the app.json file
  • Screenshots of the database
  • Screenshots of a web UI app

Code of domain model (using DDD framework)

The following code is based on planned features of milestone Boda.

using System;
using System.Collections.Generic;
using NWheels.Api.Ddd;

namespace MyMusicDB
{
    [DomainModel.BoundedContext]
    public class MusicDBContext
    {
        protected virtual EntityRepository<Genre> Genres { get; }
        protected virtual EntityRepository<Artist> Artists { get; }
        protected virtual EntityRepository<Album> Albums { get; }
        protected virtual EntityRepository<Track> Tracks { get; }
    }
    
    //------------------------------------------------------------------------------------------------------------------

    [DomainModel.Entity(IsAggregateRoot = true)]
    public class Genre
    {
        [DomainModel.EntityId(AutoGenerated = true)]
        public virtual int Id { get; protected set; }

        [DomainModel.Invariant.Required, DomainModel.Invariant.Unique]
        public virtual string Name { get; set; }
		
        public class Reference : EntityReference<Genre, int> { }
    }

    //------------------------------------------------------------------------------------------------------------------
	
    [DomainModel.Entity(IsAggregateRoot = true)]
    public class Artist
    {
        [DomainModel.EntityId(AutoGenerated = true)]
        public virtual int Id { get; protected set; }

        [DomainModel.Invariant.Required, DomainModel.Invariant.Unique]
        public virtual string Name { get; set; }

        [DomainModel.Invariant.Required, DomainModel.Semantic.MultilineText]
        public virtual string Description { get; set; }

        public virtual ISet<GenreAssociation> Genres { get; }

        public class Reference : EntityReference<Artist, int> { }
    }

    //------------------------------------------------------------------------------------------------------------------
	
    [DomainModel.ValueObject]
    public class GenreAssociation
    {
        [DomainModel.Relation.AggregationParent]
        public virtual Genre.Reference Genre { get; set; }

        public virtual bool IsPrimary { get; set; }

        public virtual bool IsRecommended { get; set; }
    }


    //------------------------------------------------------------------------------------------------------------------
	
    [DomainModel.Entity(IsAggregateRoot = true)]
    public class Album
    {
        [DomainModel.EntityId(AutoGenerated = true)]
        public virtual int Id { get; protected set; }

        public virtual Artist.Reference Artist { get; set; }

        [DomainModel.Invariant.Required, DomainModel.Invariant.UniquePerParents(nameof(Artist))]
        public virtual string Name { get; set; }

        [DomainModel.Semantic.Year, DomainModel.Invariant.Past]
        public virtual int ReleaseYear { get; set; }

        [DomainModel.Invariant.Required, DomainModel.Semantic.MultilineText]
        public virtual string Description { get; set; }

        [DomainModel.Semantic.ImageUrl]
        public virtual string CoverImageUrl { get; set; }

        [DomainModel.Relation.Composition]
        public virtual IList<Track.Reference> Tracks { get; set; }

        public class Reference : EntityReference<Album, int> { }
    }

    //-----------------------------------------------------------------------------------------------------------------

    [DomainModel.Entity(IsAggregateRoot = true)]
    public class Track
    {
        [DomainModel.EntityId(AutoGenerated = true)]
        public virtual int Id { get; protected set; }

        [DomainModel.Invariant.Required, DomainModel.Invariant.UniquePerParents(nameof(Album))]
        public virtual string Name { get; set; }

        [DomainModel.Relation.CompositionParent]
        public virtual Album.Reference Album { get; set; }

        [DomainModel.Invariant.Positive, DomainModel.Semantic.OrderBy]
        public virtual int TrackNumber { get; set; }

        [DomainModel.Invariant.Positive]
        public virtual TimeSpan Length { get; set; }

        [DomainModel.Invariant.Required, DomainModel.Semantic.MultilineText]
        public virtual string Description { get; set; }

        public virtual string AlbumText 
        { 
            get 
            {
                return $"{Album.Instance.Artist.Instance.Name}, {Album.Instance.Name} ({Album.Instance.ReleaseYear})"; 
            } 
        }

        public class Reference : EntityReference<Track, int> { }
    }
}

Code of clent app UIDL spec (using UIDL framework)

TBD (check back soon)

Contents of app.json file

TBD (check back soon)

Screenshots of database (MongoDB)

Album document collection

Artist document collection

Screenshots of a web client app

Login screen

Dashboard screen

Entity CRUD screen - grid

Entity CRUD screen - form

User account CRUD screen - grid

User account CRUD screen - form

System log screen - summary view

System log screen - thread view

System log screen - thread view with error

Background

Architecture

Feature Explorer

Platform Frameworks

  1. Kernel Layer
  2. Platform Layer
  3. Scalability & Availability Layer

Application Frameworks

  1. Domain-Driven Design
  2. Processing Workflows
  3. User Interface
  4. Data representation
  5. Semantic Logging & Data Collection
  6. Testing

Building Block Domains

  1. Infrastructure Domains
  2. Business Domains

Technology Stacks

  1. Database
  2. User Interface
  3. Communication Endpoints
  4. Scalability
  5. Services/Libraries

Developer Tools & Resources

  1. Developer Tools
  2. nwheels.org powered by NWheels
  3. Popular communities
  4. Books and videos

Contributors

Clone this wiki locally