<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://community.devexpress.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>eXpress App Framework Team</title><link>http://community.devexpress.com/blogs/eaf/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2007.1 SP1 (Build: 30415.43)</generator><item><title>XCRM: Activities</title><link>http://community.devexpress.com/blogs/eaf/archive/2008/10/09/xcrm-activities.aspx</link><pubDate>Thu, 09 Oct 2008 08:46:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:236495</guid><dc:creator>Roman Eremin</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/eaf/rsscomments.aspx?PostID=236495</wfw:commentRss><comments>http://community.devexpress.com/blogs/eaf/archive/2008/10/09/xcrm-activities.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;This post is one in a series about &lt;/em&gt;&lt;a href="http://community.devexpress.com/blogs/eaf/archive/tags/DC/default.aspx"&gt;&lt;em&gt;our work on Domain Components (DC) framework&lt;/em&gt;&lt;/a&gt;&lt;em&gt; and related component libraries. I’m just describing what we are working on, what problems we are facing and what results we&amp;#39;ve got so far.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;This post is entirely devoted to Activities. It&amp;#39;s more interesting to design Activities, because they are more complex than other components that I described earlier. There are three points I consider when designing Activities:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;There can be many Activity types: a phone call, email, meeting/appointment, task, campaign activity or case/service activity. &lt;/li&gt;    &lt;li&gt;An Activity has an owner - a person who is assigned to perform the Activity. The person should be able to see all his/her activities in one list. &lt;/li&gt;    &lt;li&gt;An Activity can be related to a Contact, Account, Lead, Opportunity, MarketingCampaign or any other “main” entity record in the system. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Let&amp;#39;s go through all these points:&lt;/p&gt;  &lt;p&gt;1. We can divide all Activities into two basic categories:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Event &lt;/li&gt; &lt;/ul&gt;  &lt;p style="padding-left:30px;"&gt;An Activity that has clear start and end points. Generally, Events can be scheduled on a calendar. So, the system should be able to show all Events in one Calendar view.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Task &lt;/li&gt; &lt;/ul&gt;  &lt;p style="padding-left:30px;"&gt;A less time-bound Activity than the Event. It may have a DueDate only.&lt;/p&gt;  &lt;p&gt;Simple CRM systems work with Tasks and Events simultaneously. More complex systems distinguish these Activity types, so they can track specialized information, like a phone number for a call. &lt;/p&gt;  &lt;p&gt;In our application, let’s define a Task and Event. In addition, let&amp;#39;s create specialized Activities: a Phone Call, as a variation of the Task Activity, and an Appointment, as a variation of the Event Activity. Here are the tests that express these requirements:&lt;/p&gt;  &lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;Test&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public void &lt;/span&gt;ActivityTypesTest() {
    &lt;span style="color:#2b91af;"&gt;ICall &lt;/span&gt;call = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;ICall&lt;/span&gt;&amp;gt;();
    &lt;span style="color:#2b91af;"&gt;IAppointment &lt;/span&gt;appointment = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;IAppointment&lt;/span&gt;&amp;gt;();
    &lt;span style="color:#2b91af;"&gt;ITask &lt;/span&gt;task = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;ITask&lt;/span&gt;&amp;gt;();
    &lt;span style="color:#2b91af;"&gt;IEvent &lt;/span&gt;eventObj = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;IEvent&lt;/span&gt;&amp;gt;();

    &lt;span style="color:#2b91af;"&gt;IList&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;IActivity&lt;/span&gt;&amp;gt; allActivities = ObjectSpace.GetObjects&amp;lt;&lt;span style="color:#2b91af;"&gt;IActivity&lt;/span&gt;&amp;gt;(&lt;span style="color:blue;"&gt;null&lt;/span&gt;);
    &lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.AreEqual(4, allActivities.Count);
    &lt;span style="color:#2b91af;"&gt;IList&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;IEvent&lt;/span&gt;&amp;gt; allEvents = ObjectSpace.GetObjects&amp;lt;&lt;span style="color:#2b91af;"&gt;IEvent&lt;/span&gt;&amp;gt;(&lt;span style="color:blue;"&gt;null&lt;/span&gt;);
    &lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.AreEqual(2, allEvents.Count);
}&lt;/pre&gt;

&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IActivity &lt;/span&gt;{
    &lt;span style="color:blue;"&gt;string &lt;/span&gt;Subject { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
    &lt;span style="color:blue;"&gt;…&lt;/span&gt;
    &lt;span style="color:#2b91af;"&gt;IActivityTarget &lt;/span&gt;RelatedTo { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
}
&lt;span style="color:blue;"&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IEvent &lt;/span&gt;: &lt;span style="color:#2b91af;"&gt;IActivity &lt;/span&gt;{
    &lt;span style="color:#2b91af;"&gt;DateTime &lt;/span&gt;StartTime { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
    &lt;span style="color:#2b91af;"&gt;DateTime &lt;/span&gt;EndTime { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
    &lt;span style="color:blue;"&gt;bool &lt;/span&gt;AllDayEvent { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;public enum &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;TaskPriority &lt;/span&gt;{ Low, Medium, High }

[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;ITask &lt;/span&gt;: &lt;span style="color:#2b91af;"&gt;IActivity &lt;/span&gt;{
    &lt;span style="color:#2b91af;"&gt;TaskPriority &lt;/span&gt;Priority { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
    &lt;span style="color:#2b91af;"&gt;DateTime &lt;/span&gt;DueDate { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
}&lt;/pre&gt;

&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;ICall &lt;/span&gt;: &lt;span style="color:#2b91af;"&gt;ITask &lt;/span&gt;{
}&lt;/pre&gt;

&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IAppointment &lt;/span&gt;: &lt;span style="color:#2b91af;"&gt;IEvent &lt;/span&gt;{
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;I don’t call the RegisterDC method in this test, because I&amp;#39;ve moved all Activity registrations to the SetUp method (it is called before a test is started by NUnit):&lt;/p&gt;

&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;SetUp&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public override void &lt;/span&gt;SetUp() {
    &lt;span style="color:blue;"&gt;base&lt;/span&gt;.SetUp();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;ILead&lt;/span&gt;&amp;gt;();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;ICampaign&lt;/span&gt;&amp;gt;();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;IContact&lt;/span&gt;&amp;gt;();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;IAccount&lt;/span&gt;&amp;gt;();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;IOpportunity&lt;/span&gt;&amp;gt;();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;IEvent&lt;/span&gt;&amp;gt;();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;IAppointment&lt;/span&gt;&amp;gt;();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;ITask&lt;/span&gt;&amp;gt;();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;ICall&lt;/span&gt;&amp;gt;();
    Generate();
}&lt;/pre&gt;

&lt;p&gt;Note that I don&amp;#39;t register the IActivity. This is a base abstract interface that cannot be instantiated in our system.&lt;/p&gt;

&lt;p&gt;2. An Activity has an owner – usually the system&amp;#39;s user. The owner may have a list of Activities:&lt;/p&gt;

&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;ITestUser &lt;/span&gt;: &lt;span style="color:#2b91af;"&gt;IActivityOwner &lt;/span&gt;{
}&lt;/pre&gt;

&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;TestFixture&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public class &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;ActivityTests &lt;/span&gt;: &lt;span style="color:#2b91af;"&gt;BaseTest &lt;/span&gt;{
    …
    [&lt;span style="color:#2b91af;"&gt;Test&lt;/span&gt;]
    &lt;span style="color:blue;"&gt;public void &lt;/span&gt;ActivityOwnershipTest() {
        &lt;span style="color:#2b91af;"&gt;ITask &lt;/span&gt;blogAboutDC = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;ITask&lt;/span&gt;&amp;gt;();
        &lt;span style="color:#2b91af;"&gt;ITestUser &lt;/span&gt;romanEremin = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;ITestUser&lt;/span&gt;&amp;gt;();
        blogAboutDC.Owner = romanEremin;
        &lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.AreEqual(blogAboutDC, romanEremin.Activities[0]);
    }
}&lt;/pre&gt;

&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IActivityOwner &lt;/span&gt;{
    &lt;span style="color:#2b91af;"&gt;IList&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;IActivity&lt;/span&gt;&amp;gt; Activities { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; }
}&lt;/pre&gt;

&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IActivity &lt;/span&gt;{
    &lt;span style="color:blue;"&gt;…&lt;/span&gt;
    &lt;span style="color:#2b91af;"&gt;IActivityOwner &lt;/span&gt;Owner { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;3. An Activity can be related to a Contact, Account and any other “main” record in the system. Some systems allow you to link Activities to several records of different type, but I guess this is just a workaround to make programming easier. Our DC framework should be flexible, so I will design it in “the right way”:&lt;/p&gt;

&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;Test&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public void &lt;/span&gt;ActivityRelationTest() {
    &lt;span style="color:#2b91af;"&gt;IAccount &lt;/span&gt;account = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;IAccount&lt;/span&gt;&amp;gt;();
    &lt;span style="color:#2b91af;"&gt;IContact &lt;/span&gt;contact = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;IContact&lt;/span&gt;&amp;gt;();
    &lt;span style="color:#2b91af;"&gt;ILead &lt;/span&gt;lead = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;ILead&lt;/span&gt;&amp;gt;();
    &lt;span style="color:#2b91af;"&gt;IOpportunity &lt;/span&gt;opportunity = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;IOpportunity&lt;/span&gt;&amp;gt;();
    &lt;span style="color:#2b91af;"&gt;ITask &lt;/span&gt;task = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;ITask&lt;/span&gt;&amp;gt;();

    task.RelatedTo = account &lt;span style="color:blue;"&gt;as &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IActivityTarget&lt;/span&gt;;
    &lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.IsNotNull(account.Activities);
    &lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.AreEqual(task, account.Activities[0]);
    task.RelatedTo = contact &lt;span style="color:blue;"&gt;as &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IActivityTarget&lt;/span&gt;;
    &lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.AreEqual(task, contact.Activities[0]);
    task.RelatedTo = lead &lt;span style="color:blue;"&gt;as &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IActivityTarget&lt;/span&gt;;
    &lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.AreEqual(task, lead.Activities[0]);
    task.RelatedTo = opportunity &lt;span style="color:blue;"&gt;as &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IActivityTarget&lt;/span&gt;;
    &lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.AreEqual(task, opportunity.Activities[0]);
}&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make this test pass, I should define the IActivityTarget interface. Only the components that implement this interface will be able to be added to the “related to” list:&lt;/p&gt;

&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IActivityTarget &lt;/span&gt;{
    &lt;span style="color:#2b91af;"&gt;IList&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;IActivity&lt;/span&gt;&amp;gt; Activities { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; }
}&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IActivity &lt;/span&gt;{
    &lt;span style="color:blue;"&gt;…&lt;/span&gt;
    &lt;span style="color:#2b91af;"&gt;IActivityTarget &lt;/span&gt;RelatedTo { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
}&lt;/pre&gt;

&lt;p&gt;Note that I have not declared a requirement that I want to be able to see all Activity Targets in one list. In that instance, we would have to create a common table for them somehow, and this might be a major restriction on possible use cases of Activities.&lt;/p&gt;

&lt;p&gt;I don’t require all IActivityTarget implementers to be in one list, but I still need to be able to edit the RelatedTo field in a UI. This editor should let end-users locate an object of one of predefined types. CRM systems tend to achieve this by adding a combo box with object types. In this instance, end-users first select the type, and then the object of this type:&lt;/p&gt;

&lt;p&gt;&lt;img title="dc5-01" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="206" alt="dc5-01" src="http://community.devexpress.com/blogs/eaf/dc5-01_47A3ABD7.png" width="499" border="0" /&gt; &lt;/p&gt;

&lt;p&gt;As far as I know,&amp;#160; we don’t have an editor of this kind yet. So, I&amp;#39;ve written down a task to implement this editor and added a test that describes this scenario. To tell you the truth, the XpoBuilder has trouble with this test. Let me explain in more detail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to persist a reference to the interface that is implemented in several classes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here, we have a case of &lt;a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html"&gt;leaky abstraction&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Object-Relational_impedance_mismatch"&gt;impedance mismatch&lt;/a&gt; and that sort of thing. The fact is that a relational database is not mapped to the OO world easily. In our case – how would you manually implement the scenario where an Activity can be related to one of several records, say, Account or Contact? I see two ways (note that we exclude the requirement that the Contact and Account must have the same base).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The first approach - Multiple associations.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Make two associations:&lt;/p&gt;

&lt;p&gt;&lt;img title="dc5-02" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="346" alt="dc5-02" src="http://community.devexpress.com/blogs/eaf/dc5-02_71A3A9FF.png" width="718" border="0" /&gt; &lt;/p&gt;

&lt;p&gt;The implementation of the IActivity.RelatedTo property will look like this:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;public &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IActivityTarget &lt;/span&gt;RelatedTo {
    &lt;span style="color:blue;"&gt;get &lt;/span&gt;{
        &lt;span style="color:blue;"&gt;if &lt;/span&gt;(Contact != &lt;span style="color:blue;"&gt;null&lt;/span&gt;) &lt;span style="color:blue;"&gt;return &lt;/span&gt;Contact;
        &lt;span style="color:blue;"&gt;if &lt;/span&gt;(Account != &lt;span style="color:blue;"&gt;null&lt;/span&gt;) &lt;span style="color:blue;"&gt;return &lt;/span&gt;Account;
        &lt;span style="color:blue;"&gt;return null&lt;/span&gt;;
    }
    &lt;span style="color:blue;"&gt;set &lt;/span&gt;{
        Contact = &lt;span style="color:blue;"&gt;null&lt;/span&gt;;
        &lt;span style="color:blue;"&gt;if &lt;/span&gt;(&lt;span style="color:blue;"&gt;value is &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;Contact&lt;/span&gt;) {
            Contact = &lt;span style="color:blue;"&gt;value as &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;Contact&lt;/span&gt;;
            Account = &lt;span style="color:blue;"&gt;null&lt;/span&gt;;
            &lt;span style="color:blue;"&gt;return&lt;/span&gt;;
        }
        &lt;span style="color:blue;"&gt;if &lt;/span&gt;(&lt;span style="color:blue;"&gt;value is &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;Account&lt;/span&gt;) {
            Contact = &lt;span style="color:blue;"&gt;null&lt;/span&gt;;
            Account = &lt;span style="color:blue;"&gt;value as &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;Account&lt;/span&gt;;
            &lt;span style="color:blue;"&gt;return&lt;/span&gt;;
        }
    }
}&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This code is ugly, but other than that it looks fine – the Contact and Account have a list of Activities. An Activity allows you to access a Contact or Account as IActivityTarget. But let’s make a simple change. Let&amp;#39;s add the Active property to the IActivityTarget interface:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IActivityTarget &lt;/span&gt;{
    &lt;span style="color:#2b91af;"&gt;IList&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;IActivity&lt;/span&gt;&amp;gt; Activities { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; }
    &lt;span style="color:blue;"&gt;bool &lt;/span&gt;Active { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
}&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;XPO will not be able to apply a criteria “[RelatedTo.Active] = true” to Activities on the server, because the RelatedTo is not an FK field and cannot be used in a simple SQL query.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The second approach - Intermediate table.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create an intermediate table for the IActivityTarget interface:&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;img title="dc5-03" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="362" alt="dc5-03" src="http://community.devexpress.com/blogs/eaf/dc5-03_3F115C06.png" width="896" border="0" /&gt; &lt;/p&gt;

&lt;p&gt;In this instance, the implementation of the IActivityTarget interface in the Account and Contact would redirect all calls to the aggregated ActivityTarget class:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;public &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IList&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;IActivity&lt;/span&gt;&amp;gt; Activities {
    &lt;span style="color:blue;"&gt;get &lt;/span&gt;{ &lt;span style="color:blue;"&gt;return &lt;/span&gt;ActivityTarget.Activities; }
}&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adding extra properties to the IActivityTarget interface won’t be a problem:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IActivityTarget &lt;/span&gt;{
    &lt;span style="color:#2b91af;"&gt;IList&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;IActivity&lt;/span&gt;&amp;gt; Activities { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; }
    &lt;span style="color:blue;"&gt;bool &lt;/span&gt;Active { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
}&lt;/pre&gt;

&lt;p&gt;... because these properties will be contained in the ActivityTarget class, and the Contact and Account will redirect calls to it:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;public bool &lt;/span&gt;Active {
    &lt;span style="color:blue;"&gt;get &lt;/span&gt;{ &lt;span style="color:blue;"&gt;return &lt;/span&gt;ActivityTarget.Active; }
    &lt;span style="color:blue;"&gt;set &lt;/span&gt;{ ActivityTarget.Active = &lt;span style="color:blue;"&gt;value&lt;/span&gt;; }
}&lt;/pre&gt;

&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But this approach yields another problem – since we hide an indirection, any Activity-related criteria for, say, a Contact (“Activities.Count &amp;gt; 0”) will not be evaluated on the server, because there is no association between the Contact and Activity. As an alternative, we could translate “Activites.Count” to “ActivityTarget.Activities.Count”. This translation might not be very obvious and would lead to problems.&lt;/p&gt;

&lt;p&gt;As you can see, that is something for XPO developers to think about. I’m going to talk to them and consider the approach we should use... &lt;/p&gt;

&lt;p&gt;Good news! XPO can use persistent aliases to map the Account’s Activities to its ActivityTarget.Actvities. So, we will use the Intermediate Table approach with aliases, and we might not have problems related to criteria. My Activity components can work as is and I can proceed further while waiting for the XpoBuilder to generate what I want.&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=236495" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XAF/default.aspx">XAF</category><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/DC/default.aspx">DC</category><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XCRM/default.aspx">XCRM</category></item><item><title>XCRM: Marketing Campaigns and Customer support</title><link>http://community.devexpress.com/blogs/eaf/archive/2008/10/07/xcrm-marketing-campaigns-and-customer-support.aspx</link><pubDate>Tue, 07 Oct 2008 12:01:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:236665</guid><dc:creator>Roman Eremin</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/eaf/rsscomments.aspx?PostID=236665</wfw:commentRss><comments>http://community.devexpress.com/blogs/eaf/archive/2008/10/07/xcrm-marketing-campaigns-and-customer-support.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;This post is one in a series about &lt;/em&gt;&lt;a href="http://community.devexpress.com/blogs/eaf/archive/tags/DC/default.aspx"&gt;&lt;em&gt;&lt;span style="color:#800080;"&gt;our work on Domain Components (DC) framework&lt;/span&gt;&lt;/em&gt;&lt;/a&gt;&lt;em&gt; and related component libraries. I&amp;rsquo;m just describing what we are working on, what problems we are facing and what results we&amp;#39;ve got so far.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Marketing Campaigns&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A Marketing Campaign has no relationships. However, a Lead and Opportunity may reference a Campaign:&lt;/p&gt;
&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;Test&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public void &lt;/span&gt;CampaignRelationships() {
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;ILead&lt;/span&gt;&amp;gt;();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;ICampaign&lt;/span&gt;&amp;gt;();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;IContact&lt;/span&gt;&amp;gt;();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;IAccount&lt;/span&gt;&amp;gt;();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;IOpportunity&lt;/span&gt;&amp;gt;();
    Generate();
    &lt;span style="color:#2b91af;"&gt;ICampaign &lt;/span&gt;campaign = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;ICampaign&lt;/span&gt;&amp;gt;();
    campaign.Name = &lt;span style="color:#a31515;"&gt;&amp;quot;Playboy back cover&amp;quot;&lt;/span&gt;;
    &lt;span style="color:#2b91af;"&gt;ILead &lt;/span&gt;lead = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;ILead&lt;/span&gt;&amp;gt;();
    &lt;span style="color:#2b91af;"&gt;IOpportunity &lt;/span&gt;opportunity = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;IOpportunity&lt;/span&gt;&amp;gt;();
    lead.Campaign = campaign;
    opportunity.Campaign = campaign;
}&lt;/pre&gt;
&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;ICampaign &lt;/span&gt;{
    &lt;span style="color:blue;"&gt;string &lt;/span&gt;Name { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
}&lt;/pre&gt;
&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;ILead &lt;/span&gt;{
    &lt;span style="color:blue;"&gt;…&lt;/span&gt;
    &lt;span style="color:#2b91af;"&gt;ICampaign &lt;/span&gt;Campaign { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
}&lt;/pre&gt;
&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IOpportunity&lt;/span&gt; {
    &lt;span style="color:blue;"&gt;…&lt;/span&gt;
    &lt;span style="color:#2b91af;"&gt;ICampaign &lt;/span&gt;Campaign { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Instead of adding the Campaign reference property to both the ILead and IOpportunity components, I could add the ICampaignResult interface and inherit the ILead and IOpportunity from it. But I think, this is overkill. However, if one more class references the Campaign, and business logic is supplied for this reference, I&amp;#39;ll choose this approach. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cases (customer support incidents)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A Case is a record about a user&amp;#39;s inquiry or problem. It is linked to an Account and/or a Contact. If the Contact is set, the Account is initialized from the Contact&amp;rsquo;s Account, if any:&lt;/p&gt;
&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;Test&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public void &lt;/span&gt;CaseRelationships() {
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;IContact&lt;/span&gt;&amp;gt;();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;IAccount&lt;/span&gt;&amp;gt;();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;ICase&lt;/span&gt;&amp;gt;();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;IOpportunity&lt;/span&gt;&amp;gt;();
    Generate();
    &lt;span style="color:#2b91af;"&gt;IContact &lt;/span&gt;roman = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;IContact&lt;/span&gt;&amp;gt;();
    roman.FirstName = &lt;span style="color:#a31515;"&gt;&amp;quot;Roman&amp;quot;&lt;/span&gt;;
    roman.LastName = &lt;span style="color:#a31515;"&gt;&amp;quot;Eremin&amp;quot;&lt;/span&gt;;
    &lt;span style="color:#2b91af;"&gt;IAccount &lt;/span&gt;dx = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;IAccount&lt;/span&gt;&amp;gt;();
    dx.Name = &lt;span style="color:#a31515;"&gt;&amp;quot;DevExpress&amp;quot;&lt;/span&gt;;

    &lt;span style="color:#2b91af;"&gt;ICase &lt;/span&gt;case1 = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;ICase&lt;/span&gt;&amp;gt;();
    case1.Subject = &lt;span style="color:#a31515;"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;;
    case1.Contact = roman;
    &lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.IsNull(case1.Account);

    &lt;span style="color:#2b91af;"&gt;ICase &lt;/span&gt;case2 = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;ICase&lt;/span&gt;&amp;gt;();
    case2.Subject = &lt;span style="color:#a31515;"&gt;&amp;quot;2&amp;quot;&lt;/span&gt;;
    case2.Account = dx;
    &lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.IsNull(case2.Contact);

    roman.Account = dx;
    &lt;span style="color:#2b91af;"&gt;ICase &lt;/span&gt;case3 = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;ICase&lt;/span&gt;&amp;gt;();
    case3.Subject = &lt;span style="color:#a31515;"&gt;&amp;quot;3&amp;quot;&lt;/span&gt;;
    case3.Contact = roman;
    &lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.AreEqual(dx, case3.Account);
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;ICase &lt;/span&gt;{
    &lt;span style="color:blue;"&gt;string &lt;/span&gt;Subject { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
    &lt;span style="color:#2b91af;"&gt;IAccount &lt;/span&gt;Account { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
    &lt;span style="color:#2b91af;"&gt;IContact &lt;/span&gt;Contact { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To make this test pass we need an extra code, in addition to the interface. We need domain logic for the ICase to initialize the ICase.Account property by the ICase.Contact&amp;#39;s Account:&lt;/p&gt;
&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainLogic&lt;/span&gt;(&lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color:#2b91af;"&gt;ICase&lt;/span&gt;))]
&lt;span style="color:blue;"&gt;public class &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;CaseLogic &lt;/span&gt;{
    &lt;span style="color:blue;"&gt;public static void &lt;/span&gt;AfterChange_Contact(&lt;span style="color:#2b91af;"&gt;ICase &lt;/span&gt;self) {
        &lt;span style="color:blue;"&gt;if &lt;/span&gt;(self.Contact != &lt;span style="color:blue;"&gt;null &lt;/span&gt;&amp;amp;&amp;amp; self.Account == &lt;span style="color:blue;"&gt;null&lt;/span&gt;) {
            self.Account = self.Contact.Account;
        }
    }
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here is how we are planning to add domain logic to the classes that are generated by the XpoBuilder. We are going to use naming conventions. If the XpoBuilder finds a method named &amp;ldquo;AfterChange_XXX&amp;rdquo;, it tries to call this method in the generated setter of a XXX property. We&amp;#39;ll probably&amp;nbsp;add the attribute-based binding in the future.&lt;/p&gt;
&lt;p&gt;A Case should have a human-readable ID that can be used in communications to quickly reference the Case. This ID should be generated only once, when a new object is beeing created.&amp;nbsp;In addtion, the ID property should be read-only, but persistent.&lt;/p&gt;
&lt;p&gt;Here is one more DC design challenge: how domain logic can specify the initial value of a read-only property? Should I add an AfterConstruction method to the business logic to set a value? But in this instance, I&amp;#39;ll have to provide&amp;nbsp;some system interfaces to call the ID&amp;rsquo;s setter. So,&amp;nbsp;I think it is better to implement the Init_XXX domain logic methods that will allow you to set a property&amp;#39;s&amp;nbsp;initial value&amp;nbsp;for a&amp;nbsp;newly created object.&lt;/p&gt;
&lt;p&gt;Since the ID property doesn&amp;#39;t have a setter, it won&amp;#39;t be persisted by default. To make&amp;nbsp;this property&amp;nbsp;persistent, I&amp;#39;ve decided to decorate it with the PersistentDc attribute. It could make sence to call&amp;nbsp;this attribute Persistent, but in XAF&amp;nbsp;this name&amp;nbsp;conflicts with XPO&amp;rsquo;s Persistent attribute.&amp;nbsp;So, it will be PersistentDc for now, and&amp;nbsp;we will see what to do with it later.&lt;/p&gt;
&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;ICase &lt;/span&gt;{
    [&lt;span style="color:#2b91af;"&gt;PersistentDc&lt;/span&gt;]
    &lt;span style="color:blue;"&gt;string &lt;/span&gt;ID { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; }
    &lt;span style="color:blue;"&gt;…&lt;/span&gt;
}&lt;/pre&gt;
&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainLogic&lt;/span&gt;(&lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color:#2b91af;"&gt;ICase&lt;/span&gt;))]
&lt;span style="color:blue;"&gt;public class &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;CaseLogic &lt;/span&gt;{
    &lt;span style="color:blue;"&gt;public static string &lt;/span&gt;Init_ID(&lt;span style="color:#2b91af;"&gt;ICase &lt;/span&gt;self) {
        &lt;span style="color:green;"&gt;//ToDo: Change to &amp;quot;select count(*)+1 from case&amp;quot; analog
        &lt;/span&gt;&lt;span style="color:blue;"&gt;return &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;Guid&lt;/span&gt;.NewGuid().ToString();
    }
    &lt;span style="color:blue;"&gt;…&lt;/span&gt;
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is a very simplistic implementation. I will return with a more realistic code, as soon we have a proper infrastructure.&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=236665" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XAF/default.aspx">XAF</category><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/DC/default.aspx">DC</category><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XCRM/default.aspx">XCRM</category></item><item><title>SDN Conference next week</title><link>http://community.devexpress.com/blogs/eaf/archive/2008/10/03/sdn-conference-next-week.aspx</link><pubDate>Fri, 03 Oct 2008 20:50:33 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:237052</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/eaf/rsscomments.aspx?PostID=237052</wfw:commentRss><comments>http://community.devexpress.com/blogs/eaf/archive/2008/10/03/sdn-conference-next-week.aspx#comments</comments><description>&lt;p&gt;Just a quick note: I&amp;#39;ll be speaking at the &lt;a href="http://www.sdc.nl/Default.aspx?tabid=36&amp;amp;language=en-US"&gt;SDN Conference&lt;/a&gt; in Noordwijkerhout in the Netherlands next week. We&amp;#39;re not exhibiting there, but of course I&amp;#39;ll be looking out for DevExpress customers nevertheless - so if you&amp;#39;re there, make sure to say hi! Of course I&amp;#39;ll also appreciate you coming to my sessions on F# :-)&lt;/p&gt;
&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=237052" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/Events/default.aspx">Events</category></item><item><title>XCRM: Leads and opportunities</title><link>http://community.devexpress.com/blogs/eaf/archive/2008/10/03/xcrm-leads-and-opportunities.aspx</link><pubDate>Fri, 03 Oct 2008 05:00:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:236658</guid><dc:creator>Roman Eremin</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/eaf/rsscomments.aspx?PostID=236658</wfw:commentRss><comments>http://community.devexpress.com/blogs/eaf/archive/2008/10/03/xcrm-leads-and-opportunities.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;This post is one in a series about &lt;/em&gt;&lt;a href="http://community.devexpress.com/blogs/eaf/archive/tags/DC/default.aspx"&gt;&lt;em&gt;&lt;span style="color:#a475b5;"&gt;our work on Domain Components (DC) framework&lt;/span&gt;&lt;/em&gt;&lt;/a&gt;&lt;em&gt; and related component libraries. I&amp;rsquo;m just describing what we are working on, what problems we are facing and what results we&amp;#39;ve got so far.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A Lead is not directly linked to a Contact or Account. It can be converted into an Account, Contact or Opportunity later. I&amp;rsquo;ll just capture the fact that the Lead class exists and may have some basic info:&lt;/p&gt;
&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;Test&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public void &lt;/span&gt;LeadsRelationships() {
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;ILead&lt;/span&gt;&amp;gt;();
    Generate();
    &lt;span style="color:#2b91af;"&gt;ILead &lt;/span&gt;romanFromDx = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;ILead&lt;/span&gt;&amp;gt;();
    romanFromDx.FirstName = &lt;span style="color:#a31515;"&gt;&amp;quot;Roman&amp;quot;&lt;/span&gt;;
    romanFromDx.LastName = &lt;span style="color:#a31515;"&gt;&amp;quot;Eremin&amp;quot;&lt;/span&gt;;
    romanFromDx.CompanyName = &lt;span style="color:#a31515;"&gt;&amp;quot;DevExpress&amp;quot;&lt;/span&gt;;
}&lt;/pre&gt;
&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;ILead &lt;/span&gt;{
    &lt;span style="color:blue;"&gt;string &lt;/span&gt;FirstName { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
    &lt;span style="color:blue;"&gt;string &lt;/span&gt;LastName { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
    &lt;span style="color:blue;"&gt;string &lt;/span&gt;CompanyName { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At this point, I&amp;rsquo;m not sure that the ILead should be inherited from the IPerson. So, I&amp;#39;ve just added the FirstName and LastName properties, and made a note to resolve this problem later.&lt;/p&gt;
&lt;p&gt;An Opportunity is a more probable possibility for business. It is related to an Account (who you want to sell to) and Product (what you want to sell). Simple CRM systems do not track products and prices, so I will leave them out in our CRM app. Here is the test for Opportunities:&lt;/p&gt;
&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;Test&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public void &lt;/span&gt;OpportunityAccountRelationships() {
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;IContact&lt;/span&gt;&amp;gt;();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;IAccount&lt;/span&gt;&amp;gt;();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;IOpportunity&lt;/span&gt;&amp;gt;();
    Generate();
    &lt;span style="color:#2b91af;"&gt;IAccount &lt;/span&gt;dx = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;IAccount&lt;/span&gt;&amp;gt;();
    dx.Name = &lt;span style="color:#a31515;"&gt;&amp;quot;DevExpress&amp;quot;&lt;/span&gt;;
    &lt;span style="color:#2b91af;"&gt;IOpportunity &lt;/span&gt;sellComponents = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;IOpportunity&lt;/span&gt;&amp;gt;();
    sellComponents.Name = &lt;span style="color:#a31515;"&gt;&amp;quot;Sell some third-party components to DX&amp;quot;&lt;/span&gt;;
    sellComponents.Account = dx;
    &lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.IsTrue(&lt;span style="color:#2b91af;"&gt;Enumerator&lt;/span&gt;.Exists&amp;lt;&lt;span style="color:#2b91af;"&gt;IOpportunity&lt;/span&gt;&amp;gt;(dx.Opportunities, sellComponents));
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To make this test pass I need the following:&lt;/p&gt;
&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IOpportunity&lt;/span&gt; {
    &lt;span style="color:blue;"&gt;string &lt;/span&gt;Name { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
    &lt;span style="color:#2b91af;"&gt;IAccount &lt;/span&gt;Account { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
}&lt;/pre&gt;
&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IAccount &lt;/span&gt;{
    &lt;span style="color:blue;"&gt;…&lt;/span&gt;
    &lt;span style="color:#2b91af;"&gt;IList&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;IOpportunity&lt;/span&gt;&amp;gt; Opportunities { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; }
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=236658" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XAF/default.aspx">XAF</category><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/DC/default.aspx">DC</category><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XCRM/default.aspx">XCRM</category></item><item><title>XCRM: Writing real-world CRM application</title><link>http://community.devexpress.com/blogs/eaf/archive/2008/10/01/xcrm-writing-real-world-crm-application.aspx</link><pubDate>Wed, 01 Oct 2008 09:00:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:236655</guid><dc:creator>Roman Eremin</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/eaf/rsscomments.aspx?PostID=236655</wfw:commentRss><comments>http://community.devexpress.com/blogs/eaf/archive/2008/10/01/xcrm-writing-real-world-crm-application.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;This post is one in a series about &lt;/em&gt;&lt;a href="http://community.devexpress.com/blogs/eaf/archive/tags/DC/default.aspx"&gt;&lt;em&gt;our work on Domain Components (DC) framework&lt;/em&gt;&lt;/a&gt;&lt;em&gt; and related component libraries. I&amp;rsquo;m just describing what we are working on, what problems we are facing and what results we&amp;#39;ve got so far.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#39;m starting to write a generic CRM application, to try the new &lt;a href="http://community.devexpress.com/blogs/eaf/archive/2008/03/04/reusable-domain-models-strikes-back.aspx"&gt;domain component (DC) technology&lt;/a&gt; and decide what classes should be included in our Domain Component technology. This application should be suitable for small business and extendable to support specific markets. While writing, I&amp;#39;m sure to find bottlenecks in XAF that we will have to fix.&lt;/p&gt;
&lt;p&gt;In general, a CRM application should be able to manage the following things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Contacts &lt;/li&gt;
&lt;li&gt;Accounts &lt;/li&gt;
&lt;li&gt;Leads &lt;/li&gt;
&lt;li&gt;Opportunities &lt;/li&gt;
&lt;li&gt;Products &lt;/li&gt;
&lt;li&gt;Appointments/Calendar/Tasks &lt;/li&gt;
&lt;li&gt;Service Requests &lt;/li&gt;
&lt;li&gt;Marketing Campaigns &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In addition, even a basic CRM system should have a security system that is aware of organization structure.&lt;/p&gt;
&lt;p&gt;To emphasize the most interesting design parts, I won&amp;#39;t detail every domain class. I will create most classes in brief form, and then extend them as required. In the first iteration, I will focus on class relationships.&lt;/p&gt;
&lt;p&gt;Contact. Can belong to an Account. So, it has the Account property.&lt;/p&gt;
&lt;p&gt;Account. Can belong to another Account. So, it has the ParentAccount and Subaccounts properties. In addition, it should have a Contacts list, and a PrimaryContact, which may not belong to the Contacts list.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m using TDD, so I will capture this knowledge in unit tests. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unit tests for Domain Components&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To write tests for domain components, I think I will need a DC infrastructure to be able to generate components from interfaces and business logic. I won&amp;#39;t use the entire XAF &amp;ndash; I will need only small parts of its services. Here is an example of a test:&lt;/p&gt;
&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IBasicTestThing &lt;/span&gt;{
    &lt;span style="color:blue;"&gt;string &lt;/span&gt;Name { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
}
[&lt;span style="color:#2b91af;"&gt;TestFixture&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public class &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;BasicTests &lt;/span&gt;: &lt;span style="color:#2b91af;"&gt;BaseTest &lt;/span&gt;{
    [&lt;span style="color:#2b91af;"&gt;Test&lt;/span&gt;]
    &lt;span style="color:blue;"&gt;public void &lt;/span&gt;TestBasicThing() {
        RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;IBasicTestThing&lt;/span&gt;&amp;gt;();
        Generate();
        &lt;span style="color:#2b91af;"&gt;IBasicTestThing &lt;/span&gt;thing1 = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;IBasicTestThing&lt;/span&gt;&amp;gt;();
        thing1.Name = &lt;span style="color:#a31515;"&gt;&amp;quot;abc&amp;quot;&lt;/span&gt;;
        ObjectSpace.CommitChanges();
        &lt;span style="color:#2b91af;"&gt;IBasicTestThing &lt;/span&gt;thing2 = ObjectSpace.FindObject&amp;lt;&lt;span style="color:#2b91af;"&gt;IBasicTestThing&lt;/span&gt;&amp;gt;(&lt;span style="color:blue;"&gt;null&lt;/span&gt;);
        &lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.AreEqual(&lt;span style="color:#a31515;"&gt;&amp;quot;abc&amp;quot;&lt;/span&gt;, thing2.Name);
    }
}
&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In all my tests, I&amp;#39;ll register and generate domain components, and use an ObjectSpace object. So, all my tests will be inherited from the BaseTest class that will provide the required services. Look how it&amp;#39;s implemented now:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;public class &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;BaseTest &lt;/span&gt;{
    &lt;span style="color:blue;"&gt;private &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IObjectSpace &lt;/span&gt;objectSpace;
    &lt;span style="color:blue;"&gt;private &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IObjectSpaceProvider &lt;/span&gt;osProvider;

    [&lt;span style="color:#2b91af;"&gt;SetUp&lt;/span&gt;]
    &lt;span style="color:blue;"&gt;public virtual void &lt;/span&gt;SetUp() {
        &lt;span style="color:#2b91af;"&gt;XafTypesInfo&lt;/span&gt;.Reset();
        osProvider = &lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;ObjectSpaceProvider&lt;/span&gt;(&lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;MemoryDataStoreProvider&lt;/span&gt;());
        objectSpace = osProvider.CreateObjectSpace();
    }
    &lt;span style="color:blue;"&gt;public void &lt;/span&gt;RegisterDC&amp;lt;T&amp;gt;() {
        &lt;span style="color:blue;"&gt;if &lt;/span&gt;(&lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(T).IsInterface) {
            &lt;span style="color:#2b91af;"&gt;XafTypesInfo&lt;/span&gt;.Instance.AddEntityToGenerate(&lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(T).Name, &lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(T));
        } &lt;span style="color:blue;"&gt;else &lt;/span&gt;{
            &lt;span style="color:#2b91af;"&gt;XafTypesInfo&lt;/span&gt;.Instance.RegisterEntity(&lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(T));
        }
    }
    &lt;span style="color:blue;"&gt;public &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IObjectSpace &lt;/span&gt;ObjectSpace {
        &lt;span style="color:blue;"&gt;get &lt;/span&gt;{ &lt;span style="color:blue;"&gt;return &lt;/span&gt;objectSpace; }
    }
    &lt;span style="color:blue;"&gt;public void &lt;/span&gt;Generate() {
        &lt;span style="color:#2b91af;"&gt;XafTypesInfo&lt;/span&gt;.Instance.GenerateEntities();
    }
}
&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The SetUp method cleans up the current type information, and creates an Object Space using a newly created Object Space Provider (using in-memory data store). The RegisterDC and Generate methods work with the XafTypesInfo system, like it&amp;#39;s performed in XAF.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Capturing domain knowledge in unit tests&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m ready to write a test for the Contact - Account relationship:&lt;/p&gt;
&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;Test&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public void &lt;/span&gt;ContactAccountRelationships() {
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;IContact&lt;/span&gt;&amp;gt;();
    RegisterDC&amp;lt;&lt;span style="color:#2b91af;"&gt;IAccount&lt;/span&gt;&amp;gt;();
    Generate();
    &lt;span style="color:#2b91af;"&gt;IContact &lt;/span&gt;roman = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;IContact&lt;/span&gt;&amp;gt;();
    roman.FirstName = &lt;span style="color:#a31515;"&gt;&amp;quot;Roman&amp;quot;&lt;/span&gt;;
    roman.LastName = &lt;span style="color:#a31515;"&gt;&amp;quot;Eremin&amp;quot;&lt;/span&gt;;
    &lt;span style="color:#2b91af;"&gt;IAccount &lt;/span&gt;dx = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;IAccount&lt;/span&gt;&amp;gt;();
    dx.Name = &lt;span style="color:#a31515;"&gt;&amp;quot;DevExpress&amp;quot;&lt;/span&gt;;

    dx.PrimaryContact = roman;
    &lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.IsNull(roman.Account);

    dx.Contacts.Add(roman);
    &lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.AreEqual(dx, roman.Account);

    &lt;span style="color:#2b91af;"&gt;IAccount &lt;/span&gt;xafTeam = ObjectSpace.CreateObject&amp;lt;&lt;span style="color:#2b91af;"&gt;IAccount&lt;/span&gt;&amp;gt;();
    xafTeam.ParentAccount = dx;
    &lt;span style="color:#2b91af;"&gt;Assert&lt;/span&gt;.IsTrue(&lt;span style="color:#2b91af;"&gt;Enumerator&lt;/span&gt;.Exists&amp;lt;&lt;span style="color:#2b91af;"&gt;IAccount&lt;/span&gt;&amp;gt;(dx.Subaccounts, xafTeam));
}
&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Enumerator is a helper class from the DevExpress.ExpressApp.Utils.dll assembly. It provides utility methods for the IEnumerable interface (similar extension methods already exist in .net 3.0).&lt;/p&gt;
&lt;p&gt;Here is the code that makes this test pass (remember &amp;ndash; I&amp;rsquo;m focused on relationships, so don&amp;rsquo;t tell me that the IContact should contain the IPerson interface) :&lt;/p&gt;
&lt;pre&gt;&lt;/pre&gt;
&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IAccount &lt;/span&gt;{
    &lt;span style="color:blue;"&gt;string &lt;/span&gt;Name { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }

    &lt;span style="color:#2b91af;"&gt;IAccount &lt;/span&gt;ParentAccount { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
    &lt;span style="color:#2b91af;"&gt;IList&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;IAccount&lt;/span&gt;&amp;gt; Subaccounts { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; }

    &lt;span style="color:#2b91af;"&gt;IContact &lt;/span&gt;PrimaryContact { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
    &lt;span style="color:#2b91af;"&gt;IList&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;IContact&lt;/span&gt;&amp;gt; Contacts { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; }
}
&lt;/pre&gt;
&lt;pre class="code"&gt;[&lt;span style="color:#2b91af;"&gt;DomainComponent&lt;/span&gt;]
&lt;span style="color:blue;"&gt;public interface &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;IContact &lt;/span&gt;{
    &lt;span style="color:#2b91af;"&gt;IAccount &lt;/span&gt;Account { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;No logic is required, because the XpoBuilder automatically generates the correct associations and XPO manages them. So, when I add &lt;strong&gt;roman&lt;/strong&gt; to the &lt;strong&gt;dx.Contacts&lt;/strong&gt; list, the &lt;strong&gt;roman.Account&lt;/strong&gt; property is initialized automatically.&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=236655" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XAF/default.aspx">XAF</category><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XPO/default.aspx">XPO</category><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/DC/default.aspx">DC</category><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XCRM/default.aspx">XCRM</category></item><item><title>DC: Implemented interfaces in BOModel</title><link>http://community.devexpress.com/blogs/eaf/archive/2008/10/01/dc-implemented-interfaces-in-bomodel.aspx</link><pubDate>Wed, 01 Oct 2008 06:00:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:236643</guid><dc:creator>Roman Eremin</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/eaf/rsscomments.aspx?PostID=236643</wfw:commentRss><comments>http://community.devexpress.com/blogs/eaf/archive/2008/10/01/dc-implemented-interfaces-in-bomodel.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;This post is one in a series about &lt;/em&gt;&lt;a href="http://community.devexpress.com/blogs/eaf/archive/tags/DC/default.aspx"&gt;&lt;em&gt;&lt;span style="color:#800080;"&gt;our work on Domain Components (DC) framework&lt;/span&gt;&lt;/em&gt;&lt;/a&gt;&lt;em&gt; and related component libraries. I&amp;rsquo;m just describing what we are working on, what problems we are facing and what results we&amp;#39;ve got so far.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;While playing with CRM domain models, I&amp;#39;ve got a component like this:&lt;/p&gt;
&lt;pre class="c#"&gt;	[DomainComponent]
	public interface IContact : IPersonalContactInfo, IPerson {
		IAccount Account { get; set; } 
	}&lt;/pre&gt;
&lt;p&gt;This led me to one more issue that prevents XAF from working with the new models. I found out that the BOModel node doesn&amp;rsquo;t provide information about implemented interfaces. I would like XAF to treat implemented interfaces as it currently treats base classes &amp;ndash; include base members into generated Views and reuse View Info provided for base classes.&lt;/p&gt;
&lt;p&gt;So, to start, I need information about implemented interfaces in the BOModel. To make a long story short &amp;ndash; here it is:&lt;/p&gt;
&lt;p&gt;&lt;img border="0" width="367" src="http://community.devexpress.com/blogs/eaf/DC4-01_0BE95DC6.png" alt="DC4-01" height="309" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" title="DC4-01" /&gt; &lt;/p&gt;
&lt;p&gt;The next step is to make members of the implemented interfaces visible in Views. &lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=236643" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XAF/default.aspx">XAF</category><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/DC/default.aspx">DC</category></item><item><title>DC: Thinking of base library</title><link>http://community.devexpress.com/blogs/eaf/archive/2008/09/30/dc-thinking-of-base-library.aspx</link><pubDate>Tue, 30 Sep 2008 08:31:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:236634</guid><dc:creator>Roman Eremin</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/eaf/rsscomments.aspx?PostID=236634</wfw:commentRss><comments>http://community.devexpress.com/blogs/eaf/archive/2008/09/30/dc-thinking-of-base-library.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;This post is one in a series about &lt;/em&gt;&lt;a href="http://community.devexpress.com/blogs/eaf/archive/tags/DC/default.aspx"&gt;&lt;em&gt;our work on Domain Components (DC) framework&lt;/em&gt;&lt;/a&gt;&lt;em&gt; and related component libraries. I&amp;rsquo;m just describing what we are working on, what problems we are facing and what results we&amp;#39;ve got so far.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The new Domain Components framework will let developers create reusable domain components. Obviously, we should supply our variant of the domain component library. Our library should be full enough to let XAF developers start fast, and to provide a common well-established base for domain component developers. At the same time, it should be flexible enough to let developers replace or extend the parts that they don&amp;rsquo;t like. &lt;/p&gt;
&lt;p&gt;I think, in the end, we will have our domain component library derived in two parts &amp;ndash; very specific base components, which will be reused across all other components, and common domain components, which can be replaced or extended as required. Let me illustrate this approach.&lt;/p&gt;
&lt;p&gt;Nearly every application needs information about a person. It can be just user information, or more detailed information on a customer, or very detailed information on a legal person. Obviously, there should be a base component Person, which will be referenced and reused by third-party domain components, and a real Person component, which contains more detailed information.&lt;/p&gt;
&lt;p&gt;Components that reference the base Person don&amp;#39;t need much information on it. So, it may contain a FullName and ShortName, and, in rare cases, Birthday and Gender:&lt;/p&gt;
&lt;pre class="c#"&gt;    public interface IPersonRef {
        string FullName { get; }
        string ShortName { get; }
        DateTime? Birthday { get; }
	Gender Gender { get; set; }
    }&lt;/pre&gt;
&lt;p&gt;A real Person component may have more properties: FirstName, MiddleName and LastName, or GivenName, Surname and FatherName (depends on the culture). We should provide the Person that is sufficient in common cases &amp;ndash; like this:&lt;/p&gt;
&lt;pre class="c#"&gt;	[DomainComponent]
	public interface IPerson : IPersonRef {
		string FirstName { get; set; }
		string MiddleName { get; set; }
		string LastName { get; set; }
	}&lt;/pre&gt;
&lt;p&gt;You can use your own IPersonRef descendant in your application, instead of the IPerson. In this instance, all domain components that depend on the IPersonRef interface will work. For this purpose, we will provide a way to tell the system that &amp;quot;in this application the IPersonRef should be resolved into the RomanEremin.DC.General.IRussianPerson component&amp;quot;.&lt;/p&gt;
&lt;p&gt;Now, we are at the genesis of creating a base domain component library, and considering an approach to implement a useful one. I think we should start writing a real-world application (this has been requested for some time). While writing, we will get core, common and application-specific components that can be included in our component library.&lt;/p&gt;
&lt;p&gt;What application should we write? I&amp;#39;m thinking of a generic CRM application. Most of us are intuitively familiar with applications of this type, so we won&amp;rsquo;t need to explain much, and most of us will be able to use it.&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=236634" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XAF/default.aspx">XAF</category><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XPO/default.aspx">XPO</category><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/DC/default.aspx">DC</category></item><item><title>DC: Interfaces and BOModel</title><link>http://community.devexpress.com/blogs/eaf/archive/2008/09/30/interfaces-and-bomodel.aspx</link><pubDate>Tue, 30 Sep 2008 08:29:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:236624</guid><dc:creator>Roman Eremin</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/eaf/rsscomments.aspx?PostID=236624</wfw:commentRss><comments>http://community.devexpress.com/blogs/eaf/archive/2008/09/30/interfaces-and-bomodel.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;This post is one in a series about &lt;/em&gt;&lt;a href="http://community.devexpress.com/blogs/eaf/archive/tags/DC/default.aspx"&gt;&lt;em&gt;our work on Domain Components (DC) framework&lt;/em&gt;&lt;/a&gt;&lt;em&gt; and related component libraries. I&amp;rsquo;m just describing what we are working on, what problems we are facing and what results we&amp;#39;ve got so far.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Now, while I&amp;rsquo;m waiting for the XPO team, who promised me to support new requirements, I&amp;#39;ve found one more problem. In my BOModel node, I can see the IDeveloper and INote interfaces, but I can&amp;#39;t see the IPerson interface. Since our ultimate goal is to provide the ability to create reusable domain components, I want to be able to set up all XAF-related aspects of the IPerson in the Application Model, and then reuse these settings in all places where the IPerson is implemented.&lt;/p&gt;
&lt;p&gt;But should I add all interfaces to the Application Model? What if the IDeveloper is inherited from the IDisposable, in addition to other interfaces? Should XAF add the IDisposable to the BOModel node? I guess not. There should be a way to mark the interfaces that are used for building entities later. I decided to add the DomainComponentAttribute that will serve as a mark:&lt;/p&gt;
&lt;pre class="c#"&gt;	[DomainComponent]
	public interface IPerson {
		string FirstName { get; set; }
		string MiddleName { get; set; }
		string LastName { get; set; }
		string FullName { get; }
		DateTime Birthday { get; set; }
		Gender Gender { get; set; }
	}&lt;/pre&gt;
&lt;p&gt;Now, after I&amp;#39;ve refacored the code that analyses types inside XAF, the interfaces that use the DomainComponent attribute are added to the BOModel node:&lt;/p&gt;
&lt;p&gt;&lt;img border="0" width="650" src="http://community.devexpress.com/blogs/eaf/DC3-01_76118282.png" alt="DC3-01" height="488" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" title="DC3-01" /&gt;&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=236624" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XAF/default.aspx">XAF</category><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XPO/default.aspx">XPO</category><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/DC/default.aspx">DC</category></item><item><title>Associations in DC</title><link>http://community.devexpress.com/blogs/eaf/archive/2008/09/29/associations-in-dc.aspx</link><pubDate>Mon, 29 Sep 2008 08:22:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:236340</guid><dc:creator>Roman Eremin</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/eaf/rsscomments.aspx?PostID=236340</wfw:commentRss><comments>http://community.devexpress.com/blogs/eaf/archive/2008/09/29/associations-in-dc.aspx#comments</comments><description>&lt;p&gt;This post is one in a series about &lt;a href="http://community.devexpress.com/blogs/eaf/archive/tags/DC/default.aspx"&gt;our work on Domain Components (DC) framework&lt;/a&gt; and related component libraries. I’m just describing what we are working on, what problems we are facing and what results we&amp;#39;ve got so far.&lt;/p&gt;  &lt;p&gt;In my previous post I was looking at INote interface:&lt;/p&gt;  &lt;pre class="c#"&gt;	public interface INote {
		string Text { get; set; }
		IItemWithNotes Owner { get; set; }
	}&lt;/pre&gt;

&lt;p&gt;There is another thing I don’t like in this code: I don’t want the INote interface to know about the IItemWithNotes interface. But currently in XPO I have to define back references. Why? Let me explain the problem. Look at the class structure below:&lt;/p&gt;

&lt;pre class="c#"&gt;    public class Developer : XPObject {
        private string name;
        public Developer(Session session) : base(session) { }
        public string Name {
            get { return name; }
            set { SetPropertyValue(&amp;quot;Name&amp;quot;, ref name, value); }
        }
        [Association]
        public XPCollection Notes { get { return GetCollection(&amp;quot;Notes&amp;quot;); } }
    }
    public class Note : XPObject {
        private string text;
        public Note(Session session) : base(session) { }
        public string Text {
            get { return text; }
            set { SetPropertyValue(&amp;quot;Text&amp;quot;, ref text, value); }
        }
    }&lt;/pre&gt;

&lt;p&gt;These classes won&amp;#39;t work correctly in XPO. In a relational database, a One-to-Many relation is performed by adding a foreign key to the table. For the classes above, you would create a table structure where the Note table has the foreign key column that stores a Developer&amp;#39;s OID:&lt;/p&gt;

&lt;p&gt;&lt;img title="DC2-01" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="203" alt="DC2-01" src="http://community.devexpress.com/blogs/eaf/DC2-01_14DC4275.png" width="653" border="0" /&gt; &lt;/p&gt;

&lt;p&gt;To retrieve the Notes that are associated with a particular Developer ID, you would write an SQL query like this: &amp;quot;&lt;strong&gt;select * from Note where Developer = &amp;lt;developer id&amp;gt;&lt;/strong&gt;&amp;quot;. XPO generates all queries for you. To generate the query I showed to you, XPO requires that the Note class has a property mapped to a foreign key column. In other words, the Note class should look like this:&lt;/p&gt;

&lt;pre class="c#"&gt;    public class Note : XPObject {
        private string text;
        private Developer developer;

        public Note(Session session) : base(session) { }
        public string Text {
            get { return text; }
            set { SetPropertyValue(&amp;quot;Text&amp;quot;, ref text, value); }
        }
        [Association]
        public Developer Developer {
            get { return developer; }
            set { SetPropertyValue(&amp;quot;Developer&amp;quot;, ref developer, value); }
        }
    }&lt;/pre&gt;

&lt;p&gt;In this instance, XPO will find both ends of the Developer-Note association and create all necessary constraints and foreign keys.&lt;/p&gt;

&lt;p&gt;But I’m working on the Domain Component library. My goal is to provide a framework for domain components – a puzzle&amp;#39;s independent pieces. While writing the Note component, I don’t want it to know how anybody uses it. For instance, it can be used in the following entity (I know this is not a good design, but I still think it should be possible to do so):&lt;/p&gt;

&lt;pre class="c#"&gt;    public interface IFullOfNotes {
        IList&amp;lt;INote&amp;gt; PublicNotes { get; }
        IList&amp;lt;INote&amp;gt; PrivateNotes { get; }
        IList&amp;lt;INote&amp;gt; DraftNotes { get; }
    }&lt;/pre&gt;

&lt;p&gt;To map the IFullOfNotes to the database, the Note table should have three foreign keys. If the XpoBuilder can generate back-reference (foreign key) properties automatically, our DC components will be much more flexible.&lt;/p&gt;

&lt;p&gt;So, I want to write the following code in my Notes library:&lt;/p&gt;

&lt;pre class="c#"&gt;	public interface IItemWithNotes {
		IList&amp;lt;INote&amp;gt; Notes { get; }
	}

	public interface INote {
		string Text { get; set; }
	}&lt;/pre&gt;

&lt;p&gt;I&amp;#39;ve added tests that express my desire. And again… I&amp;#39;m waiting for an answer from the XPO team. Stay tuned.&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=236340" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XPO/default.aspx">XPO</category><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/DC/default.aspx">DC</category></item><item><title>DC: One-to-many relationship</title><link>http://community.devexpress.com/blogs/eaf/archive/2008/09/26/dc-one-to-many-relationship.aspx</link><pubDate>Fri, 26 Sep 2008 07:38:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:236331</guid><dc:creator>Roman Eremin</dc:creator><slash:comments>18</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/eaf/rsscomments.aspx?PostID=236331</wfw:commentRss><comments>http://community.devexpress.com/blogs/eaf/archive/2008/09/26/dc-one-to-many-relationship.aspx#comments</comments><description>&lt;p&gt;In the &lt;a href="http://community.devexpress.com/blogs/eaf/archive/2008/09/25/writing-domain-components-framework-dc.aspx"&gt;first post&lt;/a&gt; of the series devoted to our new &lt;a href="http://community.devexpress.com/blogs/eaf/archive/2008/03/04/reusable-domain-models-strikes-back.aspx"&gt;domain component (DC) technology&lt;/a&gt;, I tried to show an interface-defined entity in a UI. &lt;/p&gt;  &lt;p&gt;I used some IPerson component as an example:&lt;/p&gt;  &lt;pre class="c#"&gt;	public enum Gender { Unknown, Male, Female }

	public interface IPerson {
		string FirstName { get; set; }
		string MiddleName { get; set; }
		string LastName { get; set; }
		string FullName { get; }
		DateTime Birthday { get; set; }
		Gender Gender { get; set; }
	}
	[DomainLogic(typeof(IPerson))]
	public class PersonLogic {
		public static string Get_FullName(IPerson self) {
			return self.FirstName + &amp;quot; &amp;quot; + self.LastName;
		}
	}&lt;/pre&gt;

&lt;p&gt;IPerson is a library interface that will be used as an entity rarely. In a real-world application, another entity is expected. For instance, it may be a Developer, the entity that implements the IPerson interface, in addition to other interfaces. Assume the Developer contains Notes. So, we add the INote and IItemWithNotes library interfaces:&lt;/p&gt;

&lt;pre class="c#"&gt;	public interface IItemWithNotes {
		IList&amp;lt;INote&amp;gt; Notes { get; }
	}

	public interface INote {
		string Text { get; set; }
		IItemWithNotes Owner { get; set; }
	}&lt;/pre&gt;

&lt;p&gt;Combining these two interfaces, we get the IDeveloper interface:&lt;/p&gt;

&lt;pre class="c#"&gt;	public interface IDeveloper : IPerson, IItemWithNotes{ 
	}&lt;/pre&gt;

&lt;p&gt;I change the entity registration code, which I showed in the previous post, to the following:&lt;/p&gt;

&lt;pre class="c#"&gt;		public override void Setup(XafApplication application) {
			XafTypesInfo.Instance.AddEntityToGenerate(&amp;quot;Developer&amp;quot;, typeof(IDeveloper));
			XafTypesInfo.Instance.GenerateEntities();
			base.Setup(application);
		}&lt;/pre&gt;

&lt;p&gt;If I run my application now, it won&amp;#39;t work. The problem is that I should map the INote interface to a real entity. Here, I have a design challenge: should XAF generate other entities for the Developer entity, or should it require that all Developer-related entities are registered manually? Currently, I think it is better to make a developer responsible for registering entities. First, it will give him direct control on what happens in the physical database. Second, our automatic logic can be wrong. So, I change the entity registration code again:&lt;/p&gt;

&lt;pre class="c#"&gt;		public override void Setup(XafApplication application) {
			XafTypesInfo.Instance.AddEntityToGenerate(&amp;quot;Developer&amp;quot;, typeof(IDeveloper));
			XafTypesInfo.Instance.AddEntityToGenerate(&amp;quot;Note&amp;quot;, typeof(INote));
			XafTypesInfo.Instance.GenerateEntities();
			base.Setup(application);
		}&lt;/pre&gt;

&lt;p&gt;After I made these changes, my application works:&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;img title="DC-06" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="522" alt="DC-06" src="http://community.devexpress.com/blogs/eaf/DC-06_39D26CB7.png" width="669" border="0" /&gt;&lt;/p&gt;

&lt;p&gt;Note that the FullName property is calculated properly. Remember that we declared this property with a getter only. However, we implemented the PersonLogic class that contains the Get_FullName method. When the XpoBuilder generated the implementation of the Developer object, it uses the Get_FullName method to generate the FullName property.&lt;/p&gt;

&lt;p&gt;As you can see in the screenshot above, the &amp;quot;Link&amp;quot; and &amp;quot;Unlink&amp;quot; Actions are available (they are circled). This means that the system thinks that a Note object can be created independently. I need a way to tell the XpoBuilder that the IItemWithNotes.Notes is an aggregated collection. I want to be able to write this:&lt;/p&gt;

&lt;pre class="c#"&gt;	public interface IItemWithNotes {
		[Aggregated]
		IList&amp;lt;INote&amp;gt; Notes { get; }
	}&lt;/pre&gt;

&lt;p&gt;I still can&amp;#39;t do that. So, I&amp;#39;ve written a test that shows what I need, and now I’m waiting for the Xpo team. I&amp;#39;ll focus on other problems with associations. Stay tuned.&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=236331" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XAF/default.aspx">XAF</category><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XPO/default.aspx">XPO</category><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/DC/default.aspx">DC</category></item><item><title>Writing Domain Components framework (DC)</title><link>http://community.devexpress.com/blogs/eaf/archive/2008/09/25/writing-domain-components-framework-dc.aspx</link><pubDate>Thu, 25 Sep 2008 06:55:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:236186</guid><dc:creator>Roman Eremin</dc:creator><slash:comments>13</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/eaf/rsscomments.aspx?PostID=236186</wfw:commentRss><comments>http://community.devexpress.com/blogs/eaf/archive/2008/09/25/writing-domain-components-framework-dc.aspx#comments</comments><description>&lt;p&gt;I&amp;#39;m starting a series of posts on my blog to share our experience while designing the &lt;a href="http://community.devexpress.com/blogs/eaf/archive/2008/03/04/reusable-domain-models-strikes-back.aspx"&gt;domain component (DC) technology&lt;/a&gt;. It will be useful for us to know whether you like what we are doing. If not, we&amp;#39;ll be able to correct our strategies early, before we make any mistakes.&lt;/p&gt;
&lt;p&gt;I spent last month with the XAF Core team designing the subsystem that manages type information in XAF. Until now, the framework obtained this information directly from XPO metadata, sometimes using Reflection. &lt;/p&gt;
&lt;p&gt;The new DC technology operates with interfaces. So now, the framework needs type information about interfaces. To get this information, we can&amp;#39;t use XPO metadata, because it does not contain it. Even if we could, we don&amp;#39;t like this approach, because we&amp;#39;ve targeted it to abstract away from a particular ORM tool. So, we decided to write a subsystem that would allow its users to avoid dealing with the sources of the type information.&lt;/p&gt;
&lt;p&gt;When considering which approach to choose in implementing this system, Aleksey and Mike, developers from the XAF Core team, suggested an agile approach: we should refactor until the new subsystem emerges. I voted for the &amp;quot;Big Refactoring&amp;quot; approach: just write a new system, and then call it in the old methods and helpers. My approach would be faster, but it was going to lead to the crash of the entire system in a couple of weeks. This led me to do research, and partially write the type info subsystem in my private branch of XAF sources.&lt;/p&gt;
&lt;p&gt;The next step was to integrate the new subsystem. Luckily, it was just after we had released the XAF 2008 vol. 2, the period when most of the XAF developers were busy fixing bugs and answering questions, and Aleksey was on vacation. This allowed me to convince Mike. We decided to integrate the new system and see how it behaved. Aleksey expected something like this from me. He even called us to ask if he should take one more week, so he wouldn&amp;rsquo;t see what we were doing. The next two weeks we were getting XAF back to the working state. Since then, we&amp;#39;ve been dealing with binding, type descriptors, complex property paths, structures, XPO dictionary (it directly affects what tables are created in the database), unit tests (should we reload type info between tests or not, you know, there are 1400+ tests), performance optimization and that sort of thing.&lt;/p&gt;
&lt;p&gt;Anyway, it now seems that we have the type information subsystem working. This means that we can start creating a reference application using the DC base library. We will write this library as we go.&lt;/p&gt;
&lt;p&gt;The base of the DC approach is the runtime interface implementation. In short, we write an interface for a domain object and a &amp;quot;domain logic&amp;quot; class that contains &amp;quot;non-obvious&amp;quot; parts of the domain object&amp;#39;s implementation. This approach provides us with the following advantages: we avoid writing obvious code, remove dependencies on a particular ORM system, inject the aspects like security or remoting flexibly, and use multiple inheritance to construct the final application from blocks.&lt;/p&gt;
&lt;p&gt;Real objects are generated from interfaces by the XpoBuilder class, written by the XPO team. This class is located in the XAF type information system. When you register an interface as an entity, the XpoBuilder implements an object for you. There is an important note here: you can build domain objects only once. After an object is generated, it cannot be modified. &lt;/p&gt;
&lt;p&gt;At this point, I have the XpoBuilder working at some level, and need to have a few things implemented in the type information system. So, let&amp;#39;s try to build an application using the DC approach.&lt;/p&gt;
&lt;p&gt;&lt;i&gt;Disclaimer: The code you see here cannot be run using XAF 2008 vol.2, or earlier. Moreover, I cannot be sure it will work in the final version of DC. This is just the code that works at the moment I wrote this post.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s add a Person entity to our application. In the new DC approach, the simplistic Person library element may look like this:&lt;/p&gt;
&lt;pre class="c#"&gt;	public enum Gender { Unknown, Male, Female }

	public interface IPerson {
		string FirstName { get; set; }
		string MiddleName { get; set; }
		string LastName { get; set; }
		string FullName { get; }
		DateTime Birthday { get; set; }
		Gender Gender { get; set; }
	}
	[DomainLogic(typeof(IPerson))]
	public class PersonLogic {
		public static string Get_FullName(IPerson self) {
			return self.FirstName + &amp;quot; &amp;quot; + self.LastName;
		}
	}&lt;/pre&gt;
&lt;p&gt;Now, I need to ask XAF to generate an entity for it. For this purpose, I override the Setup method in my Module class in the following manner:&lt;/p&gt;
&lt;pre class="c#"&gt;		public override void Setup(XafApplication application) {
			XafTypesInfo.Instance.AddEntityToGenerate(&amp;quot;Person&amp;quot;, typeof(IPerson));
			XafTypesInfo.Instance.GenerateEntities();
			base.Setup(application);
		}&lt;/pre&gt;
&lt;p&gt;I call the GenerateEntities method here, because at this time XAF does not performs this call inside (I&amp;#39;ve made a note to correct this).&lt;/p&gt;
&lt;p&gt;I run the Model Editor. As you can see, the IPerson entity is added to the BOModel node:&lt;/p&gt;
&lt;p&gt;&lt;img border="0" width="728" src="http://community.devexpress.com/blogs/eaf/DC-01_3E5EBEC1.png" alt="IPerson node in BOModel" height="524" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" title="IPerson node in BOModel" /&gt;&lt;/p&gt;
&lt;p&gt;Expanding the Views node I can see that the List and Detail Views are already generated. Oops, I cannot see a child node representing the IPerson in the NavigationItems node. I&amp;#39;ve made a note to fix this. For now, I&amp;#39;ll add this child node manually, together with the corresponding node in the CreatableItems node:&lt;/p&gt;
&lt;p&gt;&lt;img border="0" width="728" src="http://community.devexpress.com/blogs/eaf/DC-03_74E22646.png" alt="Adding navigation and creatable items nodes" height="524" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" title="Adding navigation and creatable items nodes" /&gt; &lt;/p&gt;
&lt;p&gt;I run the application. In spite of the child node that I&amp;#39;ve added to the NavigationItems node, there is no &amp;quot;Person&amp;quot; in the navbar:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img border="0" width="602" src="http://community.devexpress.com/blogs/eaf/DC-04_336773ED.png" alt="DC-04" height="455" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" title="DC-04" /&gt; &lt;/p&gt;
&lt;p&gt;After some investigation it turned out that I have no permissions for the newly generated entity. The fact is that the SecuritySimple strategy assumes that we are working with objects only. Look how it gives permissions:&lt;/p&gt;
&lt;pre class="c#"&gt;	public class SecuritySimple : SecurityBase  {
		...
		protected override PermissionSet ReloadPermissions() {
			...
				result.AddPermission(new ObjectAccessPermission(typeof(object), ObjectAccess.AllAccess));
			...
		}
		...
	}&lt;/pre&gt;
&lt;p&gt;Since an interface is not a descendant of the System.Object, I have no rights to it. I&amp;#39;ve written a unit test for XAF developers. It shows that their assumption is wrong. In order to proceed, I&amp;#39;ll write my own SecuritySystem strategy:&lt;/p&gt;
&lt;pre class="c#"&gt;	public class MySecurity : SecuritySimple {
		protected override System.Security.PermissionSet ReloadPermissions() {
			System.Security.PermissionSet result = base.ReloadPermissions();
			foreach(ITypeInfo entity in XafTypesInfo.Instance.RegisteredEntities) {
				result.AddPermission(new ObjectAccessPermission(entity.Type, ObjectAccess.AllAccess));
			}
			return result;
		}
	}&lt;/pre&gt;
&lt;p&gt;My Security gives all permissions to all registered entities (all persistent types). This is not a system you would like to have in a real application, but it will let me move on.&lt;/p&gt;
&lt;p&gt;Now, I run my application, and &amp;quot;voila&amp;quot;:&lt;/p&gt;
&lt;p&gt;&lt;img border="0" width="729" src="http://community.devexpress.com/blogs/eaf/DC-05_7D164BDD.png" alt="DC-05" height="455" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" title="DC-05" /&gt; &lt;/p&gt;
&lt;p&gt;In the next post, I&amp;#39;ll tell you about my efforts to associate objects using the One-to-Many relationship. Now, you are free to share your ideas on this post.&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=236186" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/DC/default.aspx">DC</category></item><item><title>Constraints included - considerations on framework structure, architecture and evolution</title><link>http://community.devexpress.com/blogs/eaf/archive/2008/07/03/constraints-included.aspx</link><pubDate>Thu, 03 Jul 2008 15:22:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:225555</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>10</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/eaf/rsscomments.aspx?PostID=225555</wfw:commentRss><comments>http://community.devexpress.com/blogs/eaf/archive/2008/07/03/constraints-included.aspx#comments</comments><description>&lt;p&gt;Somewhere on a forum, I found people engaged in a discussion about various business application frameworks, and somebody commented (paraphrased): &amp;quot;XAF is probably not the right choice for us, as it seems constrain us too much with regard to applications we can build. The technical documentation describes a particular path that has to be followed in order to create an XAF application.&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;(Btw, this comment is paraphrased and not attributed to anybody because I don&amp;#39;t have a way of finding out whether the original poster is fine with having his comment published and discussed here, together with his/her name.)&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Well, this comment baffles me. Let&amp;#39;s have a quick look at various hypothetical frameworks to see why:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Alma Knack, a C#/Windows Forms programmer who needs to prototype many new applications, feels that some of her work is redundant. So she creates a little library that makes it easier for her to create new applications from scratch. Most of her applications have splash screens, so she has a helper class for that. She takes the prototypes to other people and customizes them right there, so she also writes a feature that lets her change form layouts at runtime and import the modified layouts into her development code later. Since her applications are otherwise very diverse in nature, there&amp;#39;s really not much more she can do. When she&amp;#39;s tasked with creating a prototype of a little Tetris clone for Windows Mobile, to be given to customers as a gift, she can&amp;#39;t reuse any of the code in her library.&lt;/li&gt;
&lt;li&gt;Tad Pohl is a programmer in an insurance company. They have many different departments that work with custom applications. Of course there&amp;#39;s always a large part of the functionality in any one of these applications that accesses common data, so Tad uses a common data access layer and many standard data layouts which he created for his two target platforms Windows Forms and ASP.NET. Since he&amp;#39;s an OO fan, he structures his library well, which makes it quite easy for him to create the additional data views required by each of the departments. Of course his framework is specific to his domain of insurance data - creating an application for the HR department requires him to write almost everything from scratch, but then he doesn&amp;#39;t normally have to do that.&lt;/li&gt;
&lt;li&gt;Hugh Mungus is the lead developer in a company that specializes in SOHO productivity applications. Other teams in the company work on various applications for Windows Forms, ASP.NET and lately WPF and Silverlight. Many of these applications interoperate with Microsoft Office, Excel Services, SharePoint and SQL Server. Hugh&amp;#39;s team works on a framework of data display and manipulation functionality for typical small business needs, and the framework can also create data bound Word and Excel documents and publish to the various server solutions. The new requirements of WPF and especially Silverlight represent a great challenge to Hugh, and a special requirement of a data mining feature that needs to access an Oracle database is almost impossible to implement for him.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So what can we learn from these scenarios?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Every framework is created for a particular purpose.&lt;/li&gt;
&lt;li&gt;The functionality that&amp;#39;s included is that which is common in the majority of applications the framework needs to cover.&lt;/li&gt;
&lt;li&gt;The functionality that is *not* included is that which needs to be implemented specifically for most or all of the applications.&lt;/li&gt;
&lt;li&gt;A framework is designed to make a particular task easier by providing ready-made solutions for the typical parts of that task.&lt;/li&gt;
&lt;li&gt;There are always problems out there that a particular framework can&amp;#39;t solve easily.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Okay. Now, does XAF constrain the types of applications you can build with it? Yes, of course it does. Or no, of course it doesn&amp;#39;t. Hm... which one is it? Well, to give an example: the typical XAF application works with data in a database. If that&amp;#39;s the type of application you want to create, then XAF is going to help you a great deal. But does it mean that you can&amp;#39;t create applications that don&amp;#39;t use databases? No, it doesn&amp;#39;t. Only if you do that, then XAF won&amp;#39;t help you as much.&lt;/p&gt;
&lt;p&gt;Look at Windows Forms. If you want to create applications that have a typical main window, then Windows Forms makes that quite easy - you just derive your own form from System.Windows.Forms.Form, pass it to Application.Run and you&amp;#39;re done. If you want customize something small, then you&amp;#39;ll be able to hook into events or write method overrides in the form class to do it. If your form is supposed to be triangular in shape, have color effects in the background, a hole in the middle and shouldn&amp;#39;t react to the mouse, then you might still be able to do it, but it gets more complex. If you want to run a secondary UI thread for your splash and status windows, that&amp;#39;s when the standard mechanisms begin to fail and you have to do quite a lot of work yourself. If your application is Doom and you&amp;#39;re using Windows Forms because of the nice MessageBox class, you&amp;#39;ve probably made the wrong decision entirely.&lt;/p&gt;
&lt;p&gt;Back to XAF. The docs describe a particular way of creating an application that saves you as much work as XAF is able to save you. It is the most efficient way of creating an application if your basis is XAF, and if you want to use all the functionality the framework provides. If there&amp;#39;s some part of the functionality that you don&amp;#39;t want to use, that&amp;#39;s typically easy - just deactivate it, or never call it. If you want to customize the built-in functionality, there&amp;#39;s quite a lot you can do by way of options, custom pattern implementations and so on. If you want to replace certain parts of functionality with your own implementations, there are extensibility points that enable you to do this, and since our own modules aren&amp;#39;t different from the ones you can create, we are pretty confident that custom implementations will work just as well.&lt;/p&gt;
&lt;p&gt;What does that baffling commenter want us to do? Broaden the scope of applications that can be created easily? No, I don&amp;#39;t think so - the phrase &amp;quot;it constrains us&amp;quot; doesn&amp;#39;t seem right then, it should be &amp;quot;doesn&amp;#39;t currently include that functionality&amp;quot;. Of course broadening the scope of applications XAF can target is always something we work on anyway.&lt;/p&gt;
&lt;p&gt;Second guess, does he want us to describe different paths of creating XAF applications, ones that don&amp;#39;t take advantage of XAF functionality? Weird idea... why would we do that? Sounds like then we&amp;#39;re back to basic ASP.NET or Windows Forms programming, and it&amp;#39;s not our task to document that. Oh, we do write documentation about circumventing standard XAF features all the time - there&amp;#39;s content on creating custom editors based on third party controls, for example, and I&amp;#39;ve recorded a video on extensibility of the ASP.NET application just recently. Of course there are a million things somebody might want to do in place of the standard features, so we&amp;#39;re not likely to finish documenting them all anytime soon.&lt;/p&gt;
&lt;p&gt;Third guess, he wants to create his application in precisely the same way as he&amp;#39;s always done it, only he wants it to be easier. Yeah. Well. Perhaps a framework isn&amp;#39;t really the answer then.&lt;/p&gt;
&lt;p&gt;Generally speaking, there are certainly things that we need you to buy into in order to use XAF. Everybody who&amp;#39;s ever created a framework knows that there are lots of small decisions to make on the way. We&amp;#39;ve made all those decisions, keeping things as flexible as we could along the way (which is probably something that Alma, Tad and Hugh above wouldn&amp;#39;t do, since their situations are different), but still, we&amp;#39;ve made them. If some of these small things are really big for you and you don&amp;#39;t agree with our solution... well, there may be only so much we can about it now, but please do let us know, it will make XAF better in the long run.&lt;/p&gt;
&lt;p&gt;Bottom line: if your project doesn&amp;#39;t need the functionality in XAF, don&amp;#39;t use it. If the solution doesn&amp;#39;t fit the problem, don&amp;#39;t use it. It sounds simple, but it seems to be a word of wisdom these days. *cough*Ribbon*cough*Silverlight*cough*Astoria*cough*&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=225555" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XAF/default.aspx">XAF</category></item><item><title>Busy times</title><link>http://community.devexpress.com/blogs/eaf/archive/2008/06/19/busy-times.aspx</link><pubDate>Thu, 19 Jun 2008 17:52:18 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:223921</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/eaf/rsscomments.aspx?PostID=223921</wfw:commentRss><comments>http://community.devexpress.com/blogs/eaf/archive/2008/06/19/busy-times.aspx#comments</comments><description>&lt;p&gt;After coming back home from Orlando, I had two events to attend. The first was the brilliant UK &lt;a href="http://www.nxtgenug.net/Fest08/"&gt;NxtGenUG Fest 08&lt;/a&gt; in Reading. This was a day of .NET topics and I presented on F#. I met a few of our customers there who hadn&amp;#39;t made it to TechEd the week before, and I was glad to pass on all the news about awards, Silverlight controls and so on.&lt;/p&gt;
&lt;p&gt;The second event I went to was a training event in Germany, where I did a day of C# 3.0 (and a bit of Developer Express as well... &amp;lt;g&amp;gt;). Again, I had a good time - if I met you at either of these events, thank you, it was good to talk to you!&lt;/p&gt;
&lt;p&gt;Next week Gary and I are going to be in Glendale at the Developer Express office. As we already announced in the little interview we did at TechEd, we&amp;#39;re going to start creating content on technical topics around XAF, and we&amp;#39;re going to use the time there to create some video introductions. You&amp;#39;ll probably see some of these appear on our site during the week, some others a bit later, so watch out for them!&lt;/p&gt;
&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=223921" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XAF/default.aspx">XAF</category></item><item><title>No rest for the wicked - video announcements for XAF and XPO</title><link>http://community.devexpress.com/blogs/eaf/archive/2008/06/04/no-rest-for-the-wicked.aspx</link><pubDate>Wed, 04 Jun 2008 02:06:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:222198</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/eaf/rsscomments.aspx?PostID=222198</wfw:commentRss><comments>http://community.devexpress.com/blogs/eaf/archive/2008/06/04/no-rest-for-the-wicked.aspx#comments</comments><description>&lt;p&gt;... or the non-wicked, depending on your definition of &amp;quot;wicked&amp;quot; :-) &lt;/p&gt;
&lt;p&gt;In between exhibition hours here at TechEd, Gary and I managed to get Jeff to record an introduction video with the two of us. We talk a bit about the other videos we&amp;#39;re going to create in the next few weeks. &lt;a href="http://tv.devexpress.com/Content/TechEd2008/Day1/interviews/"&gt;Click here to watch it.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We don&amp;#39;t have too many details yet, but of course it&amp;#39;s about XAF and XPO and all the great things you can do with them. There&amp;#39;s always been the problem that while both these products take away a lot of the work you need to do to create a data layer yourself (or even a lot more than just a data layer if we&amp;#39;re talking about XAF), they still require certain knowledge and skills from the user. Nothing&amp;#39;s for free in this world... (&lt;a href="http://www.devexpress.com/Home/Announces/AgDataGridFreeLicense.xml"&gt;with the exception of our new Silverlight grid control, that is!&lt;/a&gt;) So we are going to create a bunch of content to target that problem particularly, to explain our product philosophy and generally help get everybody up to speed on things like designing domain class hierarchies, why ORM rulez and how you can do really crazy things in XAF, like create yet another blogging system. Some of this content is going to be in video format, some in written form -- it&amp;#39;s probably going to be two or three weeks, but keep watching this space for it!&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=222198" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XAF/default.aspx">XAF</category><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/XPO/default.aspx">XPO</category></item><item><title>TechEd got off to a good start</title><link>http://community.devexpress.com/blogs/eaf/archive/2008/06/03/teched-got-off-to-a-good-start.aspx</link><pubDate>Tue, 03 Jun 2008 19:37:23 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:222174</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/eaf/rsscomments.aspx?PostID=222174</wfw:commentRss><comments>http://community.devexpress.com/blogs/eaf/archive/2008/06/03/teched-got-off-to-a-good-start.aspx#comments</comments><description>&lt;p&gt;The first half day at TechEd 2008 is over and we&amp;#39;ve already had really good crowds at the booth. Mark was doing CodeRush and Refactor! demos and he showed a lot of the new and upcoming features, which are really great. We also demonstrated our new WPF and Silverlight controls and I did some XAF presentations. Lots of people are interested in XAF and object/relational mapping in general, which is interesting to see -- apparently Microsoft&amp;#39;s efforts with LINQ to SQL start paying off. &lt;/p&gt; &lt;p&gt;As I&amp;#39;ve blogged before, XAF is nominated as a finalist in the Best of TechEd awards, and one of the judges came around to interview me about the product this morning. I think he got a great impression of the product, so that&amp;#39;s good, but of course the category that XAF is nominated for is very broad, so there are going to be other products that don&amp;#39;t compete with XAF, but are good in their own right. We&amp;#39;ll see how that turns out, but being listed as a finalist for the first TechEd after XAF was released is a nice success already.&lt;/p&gt; &lt;p&gt;So, more exhibition tonight at the attendees party, with food and drinks. If you&amp;#39;re at TechEd, be sure to stop by and say hi!&lt;/p&gt; &lt;p&gt;Oh, did I mention how hot it is here? I&amp;#39;m melting away writing this -- the only thing hotter than I am is my computer. Time to stop :-)&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=222174" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/eaf/archive/tags/TechEd/default.aspx">TechEd</category></item></channel></rss>