<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>cakebaker &#187; domain model</title>
	<atom:link href="http://cakebaker.42dh.com/tags/domain-model/feed/" rel="self" type="application/rss+xml" />
	<link>http://cakebaker.42dh.com</link>
	<description>baking cakes with CakePHP</description>
	<lastBuildDate>Mon, 19 Jul 2010 14:23:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Baking a Cake &#8211; From the domain model to Cake models</title>
		<link>http://cakebaker.42dh.com/2007/03/04/baking-a-cake-from-the-domain-model-to-cake-models/</link>
		<comments>http://cakebaker.42dh.com/2007/03/04/baking-a-cake-from-the-domain-model-to-cake-models/#comments</comments>
		<pubDate>Sun, 04 Mar 2007 16:53:24 +0000</pubDate>
		<dc:creator>cakebaker</dc:creator>
				<category><![CDATA[baking a cake]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[domain model]]></category>
		<category><![CDATA[model]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://cakebaker.42dh.com/2007/03/04/baking-a-cake-from-the-domain-model-to-cake-models/</guid>
		<description><![CDATA[Do you remember the domain model from a previous post? No? No problem, here it is again: The next logical step on the way from the domain model to the Cake models would be to refine the domain model to a database diagram. I say &#8220;would be&#8221; as it is something I almost never do, [...]]]></description>
			<content:encoded><![CDATA[<p>Do you remember the domain model from a previous post? No? No problem, here it is again:</p>
<p><img src='http://cakebaker.42dh.com/wp-content/uploads/2007/02/domain_model.png' alt='Domain model' /></p>
<p>The next logical step on the way from the domain model to the Cake models would be to refine the domain model to a database diagram. I say &#8220;would be&#8221; as it is something I almost never do, especially not for small projects. For me it isn&#8217;t worth the additional effort as a database diagram doesn&#8217;t add much value if you know some basic rules (Cake conventions). And well, I don&#8217;t have found a free tool for this task which convinced me ;-)</p>
<p>So I will go on and create the tables manually. For this purpose I will create a create.sql file in app/config/sql.</p>
<p>The first rule is that table names are plural. So we can write the SQL statement for the table for the &#8220;User&#8221; class (I omit the other classes as it is the same for them):</p>
<pre>
CREATE TABLE users (
);
</pre>
<p>The second rule is that each table has a primary key field with the name &#8220;id&#8221;. So we can modify the script from above to:</p>
<pre>
CREATE TABLE users (
    id INT(11) NOT NULL AUTO_INCREMENT,
    PRIMARY KEY (id)
);
</pre>
<p>The third rule is optional, but you can add the fields &#8220;created&#8221; and &#8220;modified&#8221; to the table, which are later automatically populated by CakePHP:</p>
<pre>
CREATE TABLE users (
    id INT(11) NOT NULL AUTO_INCREMENT,
    created DATETIME,
    modified DATETIME,
    PRIMARY KEY (id)
);
</pre>
<p>The fourth rule affects 1:n relations: The &#8220;n&#8221; table must contain a field named &#8220;singular name of &#8217;1&#8242; table&#8221; + &#8220;_id&#8221;. In our domain model the relation between User and Project is such a 1:n relation: one User can have many Projects. So we have to add the field &#8220;user_id&#8221; to the &#8220;projects&#8221; table:</p>
<pre>
CREATE TABLE projects (
    id INT(11) NOT NULL AUTO_INCREMENT,
    user_id INT(11) NOT NULL,
    created DATETIME,
    modified DATETIME,
    PRIMARY KEY (id)
);
</pre>
<p>The fifth rule affects n:n relations. Such relations cannot be mapped directly to the database, we have to introduce a join table. The name of this join table is &#8220;plural name of first &#8216;n&#8217; table&#8221; + &#8220;_&#8221; + &#8220;plural name of second &#8216;n&#8217; table&#8221; whereby the names are sorted alphabetically. In our domain model we have only one n:n relation, between User and Project. So the table name is &#8220;projects_users&#8221;. We also have to apply the fourth rule, as the relations between &#8220;projects&#8221; and &#8220;projects_users&#8221; resp. between &#8220;users&#8221; and &#8220;projects_users&#8221; are 1:n relations. And so we get:</p>
<pre>
CREATE TABLE projects_users (
    project_id INT(11) NOT NULL,
    user_id INT(11) NOT NULL
);
</pre>
<p>Now we can add the attributes from the conceptual classes as fields to the respective tables and write the drop statements. And we get:</p>
<pre>
CREATE TABLE users (
    id INT(11) NOT NULL AUTO_INCREMENT,
    created DATETIME,
	modified DATETIME,
    PRIMARY KEY (id)
);

CREATE TABLE projects (
    id INT(11) NOT NULL AUTO_INCREMENT,
    user_id INT(11) NOT NULL,
    created DATETIME,
    modified DATETIME,
    PRIMARY KEY (id)
);

CREATE TABLE messages (
    id INT(11) NOT NULL AUTO_INCREMENT,
    project_id INT(11) NOT NULL,
    title VARCHAR(255) NOT NULL,
    content TEXT NOT NULL,
    created DATETIME,
    modified DATETIME,
    PRIMARY KEY (id)
);

CREATE TABLE feeds (
    id INT(11) NOT NULL AUTO_INCREMENT,
    user_id INT(11) NOT NULL,
    url VARCHAR(255) NOT NULL,
    created DATETIME,
    modified DATETIME,
    PRIMARY KEY (id)
);

CREATE TABLE projects_users (
    project_id INT(11) NOT NULL,
    user_id INT(11) NOT NULL
);
</pre>
<p>And in app/config/sql/drop.sql:</p>
<pre>
DROP TABLE IF EXISTS users;
DROP TABLE IF EXISTS projects;
DROP TABLE IF EXISTS messages;
DROP TABLE IF EXISTS feeds;
DROP TABLE IF EXISTS projects_users;
</pre>
<p>To execute these SQL scripts I use a simple Ant script (app/config/sql/build.xml):</p>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;project name="n" default="default"&gt;
    &lt;property name="driver" value="com.mysql.jdbc.Driver"&gt;&lt;/property&gt;
    &lt;property name="url" value="jdbc:mysql://localhost/n?characterEncoding=UTF-8"&gt;&lt;/property&gt;
    &lt;property name="user" value="root"&gt;&lt;/property&gt;
    &lt;property name="password" value=""&gt;&lt;/property&gt;

    &lt;target name="default"&gt;
        &lt;sql driver="${driver}" password="${password}" url="${url}" userid="${user}" src="drop.sql" encoding="UTF-8"&gt;&lt;/sql&gt;
        &lt;sql driver="${driver}" password="${password}" url="${url}" userid="${user}" src="create.sql" encoding="UTF-8"&gt;&lt;/sql&gt;
    &lt;/target&gt;
&lt;/project&gt;
</pre>
<p>After executing the Ant script, we are ready to bake the models. I will use the bake script (available in cake/scripts) to generate the User model, as I was asked to show how bake.php is used. I think it should be self-explanatory:</p>
<p><img src='http://cakebaker.42dh.com/wp-content/uploads/2007/03/baking_model_1.png' alt='Baking model, part 1' /></p>
<p><img src='http://cakebaker.42dh.com/wp-content/uploads/2007/03/baking_model_2.png' alt='Baking model, part 2' /></p>
<p>This will create the following model in app/models/user.php:</p>
<pre>
&lt;?php
class User extends AppModel {
    var $name = 'User';

    //The Associations below have been created with all possible keys, those that are not needed can be removed
    var $hasMany = array(
        'Feed' =&gt; array('className' =&gt; 'Feed',
            'foreignKey' =&gt; 'user_id',
            'conditions' =&gt; '',
            'fields' =&gt; '',
            'order' =&gt; '',
            'limit' =&gt; '',
            'offset' =&gt; '',
            'dependent' =&gt; '',
            'exclusive' =&gt; '',
            'finderQuery' =&gt; '',
            'counterQuery' =&gt; ''),
        'Project' =&gt; array('className' =&gt; 'Project',
            'foreignKey' =&gt; 'user_id',
            'conditions' =&gt; '',
            'fields' =&gt; '',
            'order' =&gt; '',
            'limit' =&gt; '',
            'offset' =&gt; '',
            'dependent' =&gt; '',
            'exclusive' =&gt; '',
            'finderQuery' =&gt; '',
            'counterQuery' =&gt; ''),
    );

    var $hasAndBelongsToMany = array(
        'Project' =&gt; array('className' =&gt; 'Project',
            'joinTable' =&gt; 'projects_users',
            'foreignKey' =&gt; 'user_id',
            'associationForeignKey' =&gt; 'project_id',
            'conditions' =&gt; '',
            'fields' =&gt; '',
            'order' =&gt; '',
            'limit' =&gt; '',
            'offset' =&gt; '',
            'unique' =&gt; '',
            'finderQuery' =&gt; '',
            'deleteQuery' =&gt; '',
            'insertQuery' =&gt; ''),
    );
}
?&gt;
</pre>
<p>It generates also a test case for the model in app/tests/cases/models/user.test.php:</p>
<pre>
&lt;?php 

loadModel('User');

class UserTestCase extends UnitTestCase {
    var $object = null;

    function setUp() {
        $this-&gt;object = new User();
    }

    function tearDown() {
        unset($this-&gt;object);
    }

    /*
    function testMe() {
        $result = $this-&gt;object-&gt;doSomething();
        $expected = 1;
        $this-&gt;assertEqual($result, $expected);
    }
    */
}
?&gt;
</pre>
<p>As you see, when using the bake script you have to answer many questions. That&#8217;s a bit of a pain when you want to bake multiple models. And if you don&#8217;t want to write tests you have to remove them (that&#8217;s at least what I do with files which are not used). These are the reasons I prefer to write the models manually. </p>
<p>Here are the other models (please notice that I omit the $name variable as I am a) using PHP5 and b) lazy):</p>
<pre>
// app/models/feed.php
&lt;?php

class Feed extends AppModel {
    var $belongsTo = array('User');
}
?&gt;
</pre>
<pre>
// app/models/project.php
&lt;?php

class Project extends AppModel {
    var $hasMany = array('Message');
    var $hasAndBelongsToMany = array('User');
}
?&gt;
</pre>
<pre>
// app/models/message.php
&lt;?php

class Message extends AppModel {
    var $belongsTo = array('Project');
}
?&gt;
</pre>
<p>To test whether we defined the associations correctly, we can create for all models the corresponding controllers. Here the UsersController (the other controllers are similar):</p>
<pre>
// app/controllers/users_controller.php
&lt;?php

class UsersController extends AppController {
    var $scaffold;
}
?&gt;
</pre>
<p>With that, we have something to play, we can add, edit, and remove records. But it isn&#8217;t very useful yet ;-)</p>
<p>That&#8217;s it for today.</p>
<p>(<a href="http://cakebaker.42dh.com/tags/baking-a-cake/">other articles</a> from this series)</p>
]]></content:encoded>
			<wfw:commentRss>http://cakebaker.42dh.com/2007/03/04/baking-a-cake-from-the-domain-model-to-cake-models/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Baking a Cake &#8211; Domain model</title>
		<link>http://cakebaker.42dh.com/2007/02/10/baking-a-cake-domain-model/</link>
		<comments>http://cakebaker.42dh.com/2007/02/10/baking-a-cake-domain-model/#comments</comments>
		<pubDate>Sat, 10 Feb 2007 16:05:14 +0000</pubDate>
		<dc:creator>cakebaker</dc:creator>
				<category><![CDATA[baking a cake]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[domain model]]></category>
		<category><![CDATA[use case]]></category>

		<guid isPermaLink="false">http://cakebaker.42dh.com/2007/02/10/baking-a-cake-domain-model/</guid>
		<description><![CDATA[The use cases we have written in the previous article are the basis to identify the conceptual classes and to draw the domain model of our application. To identify the conceptual classes we will use &#8220;Noun Phrase Identification&#8221;, i.e. each noun is considered to be a candidate for a conceptual class (with some experience you [...]]]></description>
			<content:encoded><![CDATA[<p>The use cases we have written in the previous article are the basis to identify the conceptual classes and to draw the domain model of our application. To identify the conceptual classes we will use &#8220;Noun Phrase Identification&#8221;, i.e. each noun is considered to be a candidate for a conceptual class (with some experience you can skip this step).</p>
<p>If we look at the first use case &#8220;Creating a project&#8221;:</p>
<blockquote><p>
The user choses to create a new project, enters the project information, and the system creates the project.
</p></blockquote>
<p>we get the following nouns:</p>
<ul>
<li>user</li>
<li>project</li>
<li>project information</li>
<li>system</li>
</ul>
<p>The first two nouns are conceptual classes. The third noun sounds like it is an attribute of the &#8220;project&#8221; class, even though the term &#8220;information&#8221; is a bit too general. The last noun, &#8220;system&#8221; refers to the application we want to build and is therefore no conceptual class.</p>
<p>If we apply this approach to the other use cases we find two additional conceptual classes: message and feed.</p>
<p>The next step is to define the associations between those classes. We can do that textually or visually by drawing a UML diagram. I prefer the latter, as it is more clear. But first the textual version:</p>
<ul>
<li>A User has many Feeds</li>
<li>A User has many Projects</li>
<li>A User subscribes to many Projects</li>
<li>A Feed belongs to a User</li>
<li>A project belongs to a User
<li>
<li>A project is subscribed by many Users</li>
<li>A Project has many Messages</li>
<li>A Message belongs to a Project</li>
</ul>
<p>And here the same as UML diagram (created with <a href="http://jude.change-vision.com/jude-web/product/community.html">JUDE</a>, but personally I prefer to use pen and paper as it is the fastest way to create an UML diagram):<br />
<img src='http://cakebaker.42dh.com/wp-content/uploads/2007/02/domain_model.png' alt='Domain model' /></p>
<p>Up to now it doesn&#8217;t matter which technology we will use to realize the application, as all steps were technology-neutral. But this will change next week when we will setup the database and start programming.</p>
<p><a href="http://cakebaker.42dh.com/tags/baking-a-cake/">Entire series</a></p>
]]></content:encoded>
			<wfw:commentRss>http://cakebaker.42dh.com/2007/02/10/baking-a-cake-domain-model/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>How to understand your problem domain</title>
		<link>http://cakebaker.42dh.com/2006/10/09/how-to-understand-your-problem-domain/</link>
		<comments>http://cakebaker.42dh.com/2006/10/09/how-to-understand-your-problem-domain/#comments</comments>
		<pubDate>Mon, 09 Oct 2006 13:27:48 +0000</pubDate>
		<dc:creator>cakebaker</dc:creator>
				<category><![CDATA[cakephp]]></category>
		<category><![CDATA[domain model]]></category>
		<category><![CDATA[software engineering]]></category>

		<guid isPermaLink="false">http://cakebaker.42dh.com/2006/10/09/how-to-understand-your-problem-domain/</guid>
		<description><![CDATA[Before you can start with programming you have to know what application you want to build. It is possible that this is done for you by others and you just get a detailled specification of what you have to implement. On the other hand it is also possible that you are the one who has [...]]]></description>
			<content:encoded><![CDATA[<p>Before you can start with programming you have to know what application you want to build. It is possible that this is done for you by others and you just get a detailled specification of what you have to implement. On the other hand it is also possible that you are the one who has to specify what application to build, either together with a client, if it is a client project, or alone/with your team if it is a product/internal project. Of course, there isn&#8217;t just one way of doing it. So the following is just one possible way.</p>
<p>Let us imagine we want to build a simple blog application (highly imaginative, I know *g*). But what does that mean? As there is no client  we can ask, we have to imagine how the application will be used:</p>
<p>&#8220;The user logs into the application and writes a blog post. When he finishes the post, he adds tags to the post to categorize it. Then he publishes the post.&#8221;<br />
&#8220;The (web) surfer reads the post. and because he wants to add additional information, he writes a comment.&#8221;</p>
<p>As it is a simple blog application, that is everything that can be done with it ;-)</p>
<p>From these requirements we can extract the core objects of our application, which are:</p>
<ul>
<li>User</li>
<li>Post</li>
<li>Tag</li>
<li>Comment</li>
</ul>
<p>Those objects usually have associations among each other, which we can visualize in a domain model (I recommend to use pen and paper to draw the domain model as you will be much faster than using a software tool):<br />
<img src="http://cakebaker.42dh.com/wp-content/uploads/2006/10/blog_domain_model1.png" alt="Domain Model of a simple blog application" /><br />
With the domain model we have an image of the part of the real world that is relevant to our application (the problem domain). Things like foreign keys, id attributes, methods, and other details are not relevant at this level. </p>
<p>The next step is to develop the design based on the domain model. In the CakePHP world this usually means the creation of the database design. But that is outside the scope of this article, and left as an exercise for you ;-)</p>
]]></content:encoded>
			<wfw:commentRss>http://cakebaker.42dh.com/2006/10/09/how-to-understand-your-problem-domain/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
