Angel \”Java\” Lopez on Blog

June 29, 2011

AjModel: Model by Code (Part 2) Models and Repositories

Filed under: .NET, AjModel, ASP.NET MVC, C Sharp, Software Development — ajlopez @ 10:50 am

Previous Post

I was working on my AjModel project. You can download the source code from my AjCodeKatas Project under trunk/AjModel. I added a Model class, and enhanced Entity Model and Property Model:

The model refers all the entity models I want to have in the coded model. AjModel enrich the already coded classes of your model, adding information like human descriptions, legends, etc. The idea is to generate automatically a UI for the coded model, for different technologies. The enhanced model could have nothing new, and AjModel should generate the initial UI, at runtime. The enhanced model could be consumed from differents UI technologies: the “proof of concept” application is an ASP.NET MVC one.

There is a fluent interface for EntityModel, and PropertyModel. There are extension methods, and wrappers/builders, like:

Some usage examples, borrowed from my tests:

EntityModel<Customer> model = new EntityModel<Customer>();
FluentEntityModel<Customer> fluentModel = new FluentEntityModel<Customer>(model);
fluentModel.Name("BusinessCustomer")
    .SetName("BusinessCustomers")
    .Descriptor("Business Customer")
    .SetDescriptor("Business Customers");
//..
Model model = new Model();
var entityModel = model.ForEntity<Customer>();
entityModel.Descriptor("Business Customer")
    .SetDescriptor("Business Customers");
//..
Model model = new Model();
model.ForEntity<Customer>().Property(
    c => c.Name,
    pm => pm.Descriptor("Customer Name")
            .Description("The Customer Name")
);

Where pm is a FluentPropertyModel.

In the UI process, I want to retrieve an entity by its identity. Or I need to get a list of entities to build a grid. Then, I need something to manage the entities, as a list. I implemented repositories in a context, to be implemented by different technologies. The current implementation is an in-memory list:

I’m planning to write adapter examples to NHibernate, Entity Framework, but those ideas are still in blueprints ;-)

Usage examples:

this.entityModel = new EntityModel<Customer>();
this.domain = new SimpleDomain();
this.repository = new Repository<Customer>(this.entityModel, this.domain.Customers);

Note that the repository is a typed one, using generics. And it needs an entity model, and (in the current implementation) an IList to manage. The context contains a list of repositories:

var entityModel = new EntityModel<Customer>();
var domain = new SimpleDomain();
var repository = new Repository<Customer>(entityModel, domain.Customers);
var context = new Context();
context.AddRepository(this.repository);
var repo = context.GetRepository("Customer");

SimpleDomain is a class I created for tests:

public class SimpleDomain
{
    public SimpleDomain()
    {
        this.Customers = new List<Customer>();
        for (int k = 1; k <= 10; k++)
        {
            Customer customer = new Customer()
            {
                Id = k,
                Name = string.Format("Customer {0}", k)
            };
            this.Customers.Add(customer);
        }
    }
    public IList<Customer> Customers { get; set; }
    public ProductList Products { get; set; }
}

A model can be created using a class like SimpleDomain. It discovers IList public properties:

var model = new Model(typeof(SimpleDomain));
var entityModel = model.GetEntityModel("Customer");
Assert.IsNotNull(entityModel);
entityModel = model.GetEntityModel("Product");
Assert.IsNotNull(entityModel);

I plan to add all types in an assembly that satisfied a predicate, like having “Entities” in their namespaces.

Entities can be added and retrieved to/from a repository:

Customer entity = new Customer() { Id = 1000 };
this.repository.AddEntity(entity);
Customer newEntity = this.repository.GetEntity(1000);

And they can be removed, too.

Entity model has the info to create new entities from values: a feature I will use in the UI:

EntityModel<Person> model = new EntityModel<Person>();
IDictionary<string, object> values = new Dictionary<string, object>()
{
    { "Id", 1 },
    { "FirstName", "Joe" },
    { "LastName", "Doe" },
    { "Age", "30" }
};
object entity = model.NewEntity(values);

In the next posts, I will discuss MVC UI implementation. All is work in progress, but the project is taking shape. And I having fun coding it ;-)

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

June 16, 2011

AjModel, Model by Code (Part 1) Inception

Filed under: .NET, AjModel, ASP.NET MVC, C Sharp, Software Development — ajlopez @ 11:12 am

Next Post

I’m a big proponent of raise the level of abstraction, separate problems from solutions. One of my project, AjGenesis, is dedicated to design free models that can produce (via code generation) applications in different platforms and technologies. Now, I want to explore another way: instead of code generation, I want to use simple runtime code to define and use an enhanced model.

First ideas

It’s natural to have a model (domain model, business model, you can name it):

You can have main classes (entities), associations, collection associations, services with methods, etc. And you can build all these artifacts using TDD, or not. But these artifacts ARE the system core. But you need to enhance the model, if you want to expose in a user interface. An example from AjGenesis:

<Entity>
    <Name>Customer</Name>
    <Description>Customer</Description>
    <SetName>Customers</SetName>
    <Descriptor>Customer</Descriptor>
    <SetDescriptor>Customers</SetDescriptor>
    <SqlTable>customers</SqlTable>
    <Properties>
	<Property>
	    <Name>Id</Name>
	    <Description>Id</Description>
	    <Type>Id</Type>
	    <SqlType>int</SqlType>
	</Property>
	<Property>
	    <Name>Name</Name>
	    <Description>Name</Description>
	    <Type>Text</Type>
	    <SqlType>varchar(200)</SqlType>
	    <Required>true</Required>
	</Property>
    </Properties>
</Entity>

This abstract model has attributes like Name, SetName to be uses as names in code generation, and Descriptor, Description to be used in interface (user communication) code generation. These additional attributes is part of I named “Enhanced Model”: a model with additional properties, information that help to describe the model in human terms. Maybe, I could add some additional data (SQL field lengths, etc), to be used in persistence, but it is not a target in my initial steps:

Interface models depend of the base technology to use. Once the enhanced model describe the entities and properties in user terms, view models can be built based on such information. And if the “human name” of an entity or property is missing, the code name can be used. There is “default” data and behavior in an enhanced model: use the model, Luke! In the following paragraphs are code that shows the way to enhance the model. But one key design decision is: if the model is not enhanced, I could generate all the interface from the plain model.

Some code

Then, I began to code AjModel. You can see my progress in my AjCodeKatas Project under trunk/AjModel. My first enhanced models are dedicated to Entities (main objects in the model) and their Properties:

This is a test model class, a simple Customer:

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
    public string Notes { get; set; }
}

Then, one test:

[TestMethod]
public void GetProperties()
{
    EntityModel model = new EntityModel(typeof(Customer));
    var properties = model.Properties;
    Assert.IsNotNull(properties);
    Assert.AreEqual(4, properties.Count);
    Assert.AreEqual("Id", properties.First().Name);
    Assert.AreEqual("Name", properties.Skip(1).First().Name);
    Assert.AreEqual("Address", properties.Skip(2).First().Name);
    Assert.AreEqual("Notes", properties.Skip(3).First().Name);
}

Upcoming: ServiceModel (describing services), and Model (containing the list of Entity and Service Models). More properties in EntityModel, like .Descriptor, .SetDescriptor, etc.

Each interface model depends of the final technology. As a proof of concept, I started to define an ASP.NET MVC interface model, in AjModel.WebMvc project. There is an EntityController, now dedicated to Customer:

public ActionResult Index()
{
    var model = new EntityListViewModel();
    model.Entities = Domain.Instance.Customers;
    model.EntityModel = new EntityModel(typeof(Customer));
    return View(model);
}

Domain.Instance.Customers is a in-memory list of customers. Some code in view:

<h2>
    <%= this.Model.Title %></h2>
<table>
    <tr>
        <% foreach (var property in this.Model.EntityModel.Properties)
           {
        %>
        <th>
            <%= Html.Encode(property.Name) %>
        </th>
        <%} %>
    </tr>
    <% foreach (var entity in this.Model.Entities)
       { %>
       <tr>
       <% foreach (var property in this.Model.EntityModel.Properties)
          { %>
          <td><%= property.GetValue(entity) %></td>
       <%} %>
       </tr>
    <%} %>
</table>

Next steps

I want to have a fluent interface like:

model.ForEntity<Customer>()
      .Descriptor("Customer")
      .SetDescriptor("Customers")

And I want to use Expression<Func…> to leverage code validation (define properties by code instead by name):

model.ForEntity<Customer>()
     .ForProperty(c => c.Name)
         .Description("Customer Name")
         .IsRequired()

Or something like:

model.ForEntity<Customer>()
     .Property(c => c.Name,
          pm => pm.Description("Customer Name")
                  .IsRequired()
        )
     .Property(c => c.Address,
          pm => pm.Description("Customer Address")
        )

where pm is a PropertyModel. .ForProperty returns a PropertyModel fluent interface. But .Property returns a fluent EntityModel builder, so it uses the second parameter to extended the selected property.

But no committed code in repo, yet. You know, I’m working in my free time, I’m still need to work, family fortune dissolved in Montecarlo tables ;-)

Code Generation vs Runtime

I’m still prefer code generation from an free-defined model: it makes a clear distinction of the problem and the technological solution. And it can be easily adapted to the changes of technologies and language (Java vs Scala vs C# vs … whatever upcoming combination.. ;-). But most developers prefer to work with code. That's the reason for this experiment. Since late nineties, I know morphic  in Smalltalk world (thanks to SUGAR Smalltalk User Group Argentina meetings, now defunct) See History of Morphic. And Naked Objects is another way to expose the model to the user/developer. See Naked Objects, Wikipedia. I read:

1. All business logic should be encapsulated onto the domain objects. This principle is not unique to naked objects: it is just a strong commitment to encapsulation.

2. The user interface should be a direct representation of the domain objects, with all user actions consisting, explicitly, of creating or retrieving domain objects and/or invoking methods on those objects. This principle is also not unique to naked objects: it is just a specific interpretation of an object-oriented user interface (OOUI).

The original idea in the naked objects pattern arises from the combination of these two, to form the third principle:

3. The user interface should be created 100% automatically from the definition of the domain objects. This may be done using several different technologies, including source code generation; implementations of the naked objects pattern to date have favoured the technology of reflection.

The naked objects pattern was first described formally in Richard Pawson's PhD thesis[1] which includes a thorough investigation of various antecedents and inspirations for the pattern including, for example, the Morphic user interface.

This century, I found Magritte.

Now, it’s time to explore the runtime/reflection way in .NET. Pros: developers can enhanced the model using their IDEs and code; their can create new interface models. Cons: it's limited to the underlying technology, in my case: .NET; new dynamic interface models can be hard to create; custom extension by manual code could be not easy.

Ok, enough for today, back to coding (and to work).

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

The Shocking Blue Green Theme. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 57 other followers