summaryrefslogtreecommitdiff
path: root/.html/dev/rich-shared-models.html
diff options
context:
space:
mode:
authorOwen Jacobson <owen.jacobson@grimoire.ca>2015-07-03 22:31:49 -0400
committerOwen Jacobson <owen.jacobson@grimoire.ca>2015-07-03 22:35:09 -0400
commit76aed6ef732de38d82245b3d674f70bab30221e5 (patch)
treed50e9a296d91ef8a49bcb29c3e80096f200a3c26 /.html/dev/rich-shared-models.html
parent92f66d3e3a0996bb1fad9dc83d7e184f92673e5d (diff)
Fuck it, serve the files directly.
Diffstat (limited to '.html/dev/rich-shared-models.html')
-rw-r--r--.html/dev/rich-shared-models.html187
1 files changed, 187 insertions, 0 deletions
diff --git a/.html/dev/rich-shared-models.html b/.html/dev/rich-shared-models.html
new file mode 100644
index 0000000..c4d167c
--- /dev/null
+++ b/.html/dev/rich-shared-models.html
@@ -0,0 +1,187 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>
+ The Codex »
+ Rich Shared Models Must Die
+ </title>
+
+ <link
+ rel='stylesheet'
+ type='text/css'
+ href='http://fonts.googleapis.com/css?family=Buenard:400,700&amp;subset=latin,latin-ext'>
+ <link
+ rel="stylesheet"
+ type="text/css"
+ href="../media/css/reset.css">
+ <link
+ rel="stylesheet"
+ type="text/css"
+ href="../media/css/grimoire.css">
+</head>
+<body>
+
+<div id="shell">
+
+ <ol id="breadcrumbs">
+
+ <li class="crumb-0 not-last">
+
+ <a href="../">index</a>
+
+ </li>
+
+ <li class="crumb-1 not-last">
+
+ <a href="./">dev</a>
+
+ </li>
+
+ <li class="crumb-2 last">
+
+ rich-shared-models
+
+ </li>
+
+ </ol>
+
+
+
+ <div id="article">
+ <h1 id="rich-shared-models-must-die">Rich Shared Models Must Die</h1>
+<p>In a gaming system I once worked on, there was a single class which was
+responsible for remembering everything about a user: their name and contact
+information, their wagers, their balance, and every other fact about a user
+the system cared about. In a system I'm working with now, there's a set of
+classes that collaborate to track everything about the domain: prices,
+descriptions, custom search properties, and so on.</p>
+<p>Both of these are examples of shared, system-wide models.</p>
+<p>Shared models are evil.</p>
+<p>Shared models <em>must be destroyed</em>.</p>
+<p>A software system's model is the set of functions and data types it uses to
+decide what to do in response to various events. Models embody the development
+team's assumptions and knowledge about the problem space, and usually reflect
+the structure of the applications that use them. Not all systems have explicit
+models, and it's often hard to draw a line through the code base separating
+the code that is the model from the code that is not as every programmer sees
+models slightly differently.</p>
+<p>With the rise of object-oriented development, explicit models became the focus
+of several well-known practices. Many medium-to-large projects are built
+“model first,” with the interfaces to that model being sketched out later in
+the process. Since the model holds the system's understanding of its task,
+this makes sense, and so long as you keep the problem you're actually solving
+in mind, it works well. Unfortunately, it's too easy to lose sight of the
+problem and push the model as the whole reason for the system around it. This,
+in combination with both emotional and technical investment in any existing
+system, strongly encourages building <code>new</code> systems around the existing
+model pieces even if the relationship between the new system is tenuous at
+best.</p>
+<ul>
+<li>Why do we share them?<ul>
+<li>Unmanaged growth<ul>
+<li>Adding features to an existing system</li>
+<li>Building new systems on top of existing tools</li>
+</ul>
+</li>
+<li>Misguided applications of “simplicity” and “reuse”</li>
+<li>Encouraged by distributed object systems (CORBA, EJB, SOAP, COM)</li>
+</ul>
+</li>
+<li>What are the consequences?<ul>
+<li>Models end up holding behaviour and data relevant to many applications</li>
+<li>Every application using the model has to make the same assumptions</li>
+<li>Changing the model usually requires upgrading everyone at the same time</li>
+<li>Changes to the model are risky and impact many applications, even if the
+ changes are only relevant to one application</li>
+</ul>
+</li>
+<li>What should we do instead?<ul>
+<li>Narrow, flat interfaces</li>
+<li>Each system is responsible for its own modelling needs</li>
+<li>Systems share data and protocols, not objects</li>
+<li>Libraries are good, if the entire world doesn't need to upgrade at the
+ same time</li>
+</ul>
+</li>
+</ul>
+<p>It's easy to start building a system by figuring out what the various nouns it
+cares about are. In the gambling example, one of our nouns was a user (the guy
+sitting at a web browser somewhere), who would be able to log in, deposit
+money, place a wager, and would have to be notified when the wager was
+settled. This is a clear, reasonable entity for describing the goal of placing
+bets online, which we could make reasonable assumptions about. It's also a
+terrible thing to turn into a class.</p>
+<p>The User class in our gambling system was responsible for all of those things;
+as a result, every part of the system ended up using a User object somewhere.
+Because the User class had many responsibilities, it was subject to frequent
+changes; because it was used everywhere, those changes had the capability to
+break nearly any part of the overall system. Worse, because so much
+functionality was already in one place, it became psychologically easy to add
+one more responsibility to its already-bloated interface.</p>
+<p>What had been a clean model in the problem space eventually became one of a
+handful of “glue” pieces in a <a href="http://www.laputan.org/mud/mud.html#BigBallOfMud">big ball of
+mud</a> program. The User
+object did not come about through conscious design, but rather through
+evolution from a simple system. There was no clear point where User became
+“too big”; instead, the vagueness of its role slowly grew until it became the
+default behaviour-holder for all things user-specific.</p>
+<p>The same problem modeling exercise also points at a better way to design the
+same system: it describes a number of capabilities the system needed to be
+able to perform, each of which is simpler than “build a gaming website.” Each
+of these capabilities (accept or reject logins, process deposits, accept and
+settle wagers, and send out notification emails to players) has a much simpler
+model and solves a much more constrained of problem. There is no reason the
+authentication service needs to share any data except an identity with the
+wagering service: one cares about login names, passwords, and authorization
+tickets while the other cares about accounting, wins and losses, and posted
+odds.</p>
+<p>There is a small set of key facts that can be used to correlate all of pieces:
+usernames, which uniquely identify a user, can be used to associate data and
+behaviour in the login domain with data and behaviour in the accounting and
+wagering domain, and with information in a contact management domain. All of
+these key facts are flat—they have very little structure and no behaviour, and
+can be passed from service to service without dragging along an entire
+application's worth of baggage data.</p>
+<p>Sharing model classes between many services creates a huge maintenance
+bottleneck. Isolating models within the services they support helps encourage
+clean separations between services, which in turn makes it much easier to
+understand individual services and much easier to maintain the system as a
+whole. Kindergarten lied: sharing is <em>wrong</em>.</p>
+ </div>
+
+
+
+<div id="comments">
+<div id="disqus_thread"></div>
+<script type="text/javascript">
+ /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
+ var disqus_shortname = 'grimoire'; // required: replace example with your forum shortname
+
+ /* * * DON'T EDIT BELOW THIS LINE * * */
+ (function() {
+ var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
+ dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
+ })();
+</script>
+<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
+<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>
+</div>
+
+
+
+ <div id="footer">
+ <p>
+
+ The Codex —
+
+ Powered by <a href="http://markdoc.org/">Markdoc</a>.
+
+<a href="https://bitbucket.org/ojacobson/grimoire.ca/src/master/wiki/dev/rich-shared-models.md">See this page on Bitbucket</a> (<a href="https://bitbucket.org/ojacobson/grimoire.ca/history-node/master/wiki/dev/rich-shared-models.md">history</a>).
+
+ </p>
+ </div>
+
+</div>
+</body>
+</html> \ No newline at end of file