diff options
| author | Owen Jacobson <owen.jacobson@grimoire.ca> | 2015-07-03 22:31:49 -0400 |
|---|---|---|
| committer | Owen Jacobson <owen.jacobson@grimoire.ca> | 2015-07-03 22:35:09 -0400 |
| commit | 76aed6ef732de38d82245b3d674f70bab30221e5 (patch) | |
| tree | d50e9a296d91ef8a49bcb29c3e80096f200a3c26 /.html/dev/rich-shared-models.html | |
| parent | 92f66d3e3a0996bb1fad9dc83d7e184f92673e5d (diff) | |
Fuck it, serve the files directly.
Diffstat (limited to '.html/dev/rich-shared-models.html')
| -rw-r--r-- | .html/dev/rich-shared-models.html | 187 |
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&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 |
