Just A Summary : Tag 5nouns, everything about 5nouns http://www.bofh.org.uk/articles/tag/5nouns.rss en-us 40 Piers Cawley Practices Punditry Today's Noun is: Reticence <p>What does the <span class="caps">OED</span> say reticence is?</p> <blockquote> <p><ins>Reticence</ins>: Maintenance of silence; avoidance of saying too much or of speaking freely; disposition to say little.</p> </blockquote> <p>Pretty straightforward. When I chose reticence as one of my <a href="http://www.bofh.org.uk/articles/2007/08/20/five-nouns-for-programmers">five nouns for programmers</a> it was another reminder that objects are not the same as datastructures. Well designed objects keep their cards (instance variables) close to their chest. Client code tells objects what to do, it doesn&#8217;t ask them to kiss and tell. In <a href="http://www.amazon.co.uk/exec/obidos/ASIN/013476904X/justasummary-21">Smalltalk Best Practice Patterns</a>, (you don&#8217;t have a copy yet? Are you mad?) Kent Beck recommends that you put your accessor methods in the <code>private</code> protocol unless you have a <em>very</em> good reason for indicating that the accessors should be used by clients by putting the accessors in, say, the <code>accessing</code> protocol or some other, more suitably named, protocol. (In Smalltalk, all methods are public, but you can and should organize them into protocols/categories, either by choosing some existing protocol, or coming up with a new protocol name). In less flexible OO languages, you should probably at least mark your accessors as protected unless you have the aforementioned very good reason.</p> <h3>What about parameter objects then?</h3> <p>One obvious &#8216;exception&#8217; to the rule of reticence is the parameter object. Say you have an unwieldy method that takes a bunch of arguments and fills the screen with its implementation. Being a conscientious programmer, you want to apply the &#8216;composed method&#8217; pattern to the method so you&#8217;ll still end up with a screen&#8217;s worth of code, possibly more, but the individual methods will be much more focussed in what they achieve. What stops you is that bunch of parameters which are used through out the method. So, you introduce a parameter object. Bundle up the parameters into a single object, replace each parameter variable in the body of the code with an accessor call on the parameter object, and have at it. You can extract methods easily and you&#8217;ll only ever have to pass a single object.</p> <p>It&#8217;s tempting not to bother creating a &#8216;real&#8217; object, it&#8217;s very easy to just use an options hash, a la Ruby on Rails. And, because the options hash is a common pattern through your code, you can start adding helper methods like <code>with_options</code>, and you&#8217;ll get an awful lot of leverage out of it.</p> <p>However, what&#8217;s often missed in discussions of the parameter object pattern is that it&#8217;s a waystation, not a destination. It may be handy, but if you persist in treating it as a datastructure, you&#8217;re missing out on the good stuff. Now you have a parameter object, you can start to move <em>behaviour</em> onto the parameter object and before you know it you&#8217;ll end up with a real object doing real, testable (mockable?), work.</p> <h3>Homework</h3> <p>Find a method where you&#8217;re using an options hash. Try using that hash to build a parameter object and then apply the principle of reticence. What happens to it? Where does the behaviour go? If, like me, you&#8217;ve come to OO from procedural coding styles, making your objects reticent is not a natural thing to do, it can feel extremely odd. But the more you practice it, the better you&#8217;ll get at thinking in a truly object oriented fashion. Sometimes an options hash really is the way to go, but not as often as you&#8217;d think.</p> <p>Try it, maybe you&#8217;ll be converted.</p> Thu, 27 Sep 2007 18:30:29 -0500 urn:uuid:d915e393-cff4-4e70-86c1-710e4dd31958 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/09/27/todays-noun-is-reticence#comments Musings The Practice of Programming 5nouns http://www.bofh.org.uk/articles/2007/09/27/todays-noun-is-reticence Today's Noun Is: Notation <p>Remember back when I wrote about <a href="http://www.bofh.org.uk/articles/2007/05/20/metaprogramming-programming">metaprogramming and programming</a> being the same thing?</p> <p>Well, Libraries, Domain Specific Languages, <a href="http://www.bofh.org.uk/articles/2007/05/19/domain-agnostic-languages">Domain Agnostic Languages</a>, Pidgins, <span class="caps">YAML</span>, .INI files and the like are all the same thing. They&#8217;re all notation.</p> <p>That&#8217;s the thing to remember. Good notation makes life easy. Bad (or inappropriate) notation makes it hard (or, in some cases, fun). There&#8217;s no point striving to write a pidgin or <span class="caps">DSL</span> if your problem can be solved easily enough with a well factored set of loosely coupled classes. After all, even the neatest and cleanest of domain specific languages has to be learned. Meanwhile a class library that&#8217;s respects the language of your problem domain can be easier to learn because the notation with which the library is implemented is plain old <acronym title="Your Favourite Language">YFL</acronym> and your team already knows that (and if it doesn&#8217;t, you have bigger problems). Learning the class library is like learning about the problem domain and vice versa. Learning one supports learning the other.</p> <p>I&#8217;m of the opinion that DSLs and pidgins are at their most when their domains are generic. So ActiveRecord&#8217;s most useful language like interfaces are related to general problems like expressing the relationships between objects or describing how to validate an object. Backus-Naur Form, Perl compatible regular expressions, parser combinators are all useful for solving the generic parsing and lexing problems that crop up everywhere. Data serialization notations like <span class="caps">YAML</span>, FASTA, <span class="caps">XML</span>, CSV, <span class="caps">JSON</span> and all the others are useful when you want a generic way to pass data between systems. All of these notations are narrow in their focus, but broad in the sense that the things that they focus on are ubiquitous.</p> <p>The most useful notation for your specific task is almost always a well factored set of classes or functions (depends on your language of choice) which reflects the language of your problem domain. Different parts of your program might well make use of a wide range of &#8216;donor&#8217; notations, but it&#8217;s a rare problem that&#8217;s going to require to you implement a full blown language in order to solve it.</p> <p>Don&#8217;t worry about whether something&#8217;s a <span class="caps">DSL</span>, pidgin or a library. What it is is notation. A better question is is &#8220;does this notation help me solve my problem?&#8221;. If the answer is no, find better notation. Or keep plugging on with what you&#8217;ve got, but don&#8217;t fool yourself about your reasons for using the notation &#8211; not everyone&#8217;s here for the hunting after all.</p> Tue, 28 Aug 2007 16:20:00 -0500 urn:uuid:c7833d62-3fb4-4e78-bbcd-c1689520a6c6 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/08/28/todays-noun-is-notation#comments Musings The Practice of Programming 5nouns http://www.bofh.org.uk/trackbacks?article_id=todays-noun-is-notation&day=28&month=08&year=2007 http://www.bofh.org.uk/articles/2007/08/28/todays-noun-is-notation Today's noun is: Reification <blockquote> <p>Reification: The mental conversion of a person or abstract concept into a thing. Also, depersonalization, esp. such as Marx thought was due to capitalist industrialization in which the worker is considered as the quantifiable labour factor in production or as a commodity. &#8211; <span class="caps">OED</span></p> </blockquote> <p>In the sense that the <span class="caps">OED</span> has it, I&#8217;m not what you could call a fan of reification. At work, we have a rule that anybody who starts talking about &#8216;resources&#8217; when they mean &#8216;people&#8217; gets a (verbal) slap.</p> <p>However, in OO circles (or maybe just in my head), reification is a good thing. It&#8217;s the process of taking something abstract and turning it into a &#8216;real&#8217; object. Usually, the word gets used for big things like turning an intractable method into an object as a step on the way to refactoring that method. I tend to use it in a slightly broader sense. For me, reification is the process of turning something (a method or a data structure usually) into a full blown object with its own behaviour.</p> <p>Back when I was working on Pixie (a cunning, but weird, object persistence tool written in Perl) we had a data structure which was used for keeping track of managed objects. It started life as a hash. Everything was fine at first, but over time we ended up with more and more code being repeated across the codebase that was concerned with manipulating the cache hash. So, we replaced the hash with a new object and pulled all the repeated code into methods on that object, which gave us cleaner code to extend, and a strong feeling that we should have turned the cache into an object much earlier in the game. (By leaving it so long, we had a lot more code to move about, some of it in fairly obscure places; tracking down the last bit took a while.)</p> <p>Data structures like hashes and arrays are really useful in languages that have them. The catch is, they have this habit of acquiring code. When this starts to happen, it&#8217;s time to reify &#8211; to replace the hash with a task specific object. In Ruby, it&#8217;s easy enough to inherit from <code>Hash</code>, but Hash comes with a pile of methods that probably aren&#8217;t relevant to your particular need. Generally it&#8217;s better to delegate. The first cut doesn&#8217;t have to be that complicated, just decorate the hash with a new class and initialize an instance of the class at the point where you had just made the hash.</p> <p>Once that&#8217;s done, you can go through your code and move the bits that treat the hash as a data structure onto your new class. As you gather all the common behaviour to the new class, you&#8217;ll start to see places where you can improve code quality by merging common behaviours, replacing complex conditionals with polymorphism (you&#8217;ll probably have to introduce a factory method if you do that) and pulling hash keys out into instance variables.</p> <h3>Stalled reification</h3> <p>Reifying your data structure isn&#8217;t an end in itself, it&#8217;s a step along the way as you refactor your code.</p> <p>There&#8217;s an example of a stalled reification to be found in ActionController::Routing::Resources. Consider the implementations of <code>map_resource</code> and <code>map_singleton_resource</code>, which are the worker methods used whenever you do a <code>map.resource</code> or <code>map.resources</code> in your <code>routes.rb</code>.</p> <pre><code>def map_resource(entities, options = {}, &#38;block) resource = Resource.new(entities, options) with_options :controller =&gt; resource.controller do |map| map_collection_actions(map, resource) map_default_collection_actions(map, resource) map_new_actions(map, resource) map_member_actions(map, resource) if block_given? with_options(:path_prefix =&gt; resource.nesting_path_prefix, &#38;block) end end end def map_singleton_resource(entities, options = {}, &#38;block) resource = SingletonResource.new(entities, options) with_options :controller =&gt; resource.controller do |map| map_collection_actions(map, resource) map_default_singleton_actions(map, resource) map_new_actions(map, resource) map_member_actions(map, resource) if block_given? with_options(:path_prefix =&gt; resource.nesting_path_prefix, &#38;block) end end end </code></pre> <p>There&#8217;s a lot of repetition there. The only differences are the classes of the resource object, name of the second function called in the <code>with_options</code> block. If we take a look at, <code>map_collection_actions</code> things start to look even fishier. Here&#8217;s <code>map_collection_actions</code>, for example:</p> <pre><code>def map_collection_actions(map, resource) resource.collection_methods.each do |method, actions| actions.each do |action| action_options = action_options_for(action, resource, method) map.named_route("#{resource.name_prefix}#{action}_#{resource.plural}", "#{resource.path};#{action}", action_options) map.named_route("formatted_#{resource.name_prefix}#{action}_#{resource.plural}", "#{resource.path}.:format;#{action}", action_options) end end end </code></pre> <p><code>resource.collection_methods.each</code>? Let&#8217;s see what happens if we the various <code>map_foo_actions</code> methods into methods on <code>ActionController::Resources::Resource</code>. While we&#8217;re about it, we can rename <code>map_default_collection_actions</code> to <code>map_default_actions</code> on Resource, and <code>map_default_singleton_actions</code> to <code>map_default_actions</code> on SingletonResource, which inherits from Resource. <code>map_collection_actions</code> becomes:</p> <pre><code>def map_collection_actions(map) collection_methods.each do |method, actions| actions.each do |action| map.with_options(action_options_for(action, method)) do |m| m.named_route("#{name_prefix}#{action}_#{plural}", "#{path};#{action}") m.named_route("formatted_#{name_prefix}#{action}_#{plural}, "#{path}.:format;#{action}") end end end end </code></pre> <p>(we move <code>action_options_for</code> onto resource as well, of course).</p> <p>Once we&#8217;ve moved the various mapping helpers onto the resource classes, we can revisit <code>map_resource</code> and <code>map_singleton_resource</code></p> <pre><code> def map_resource(entities, options={}, &#38;block) resource = Resource.new(entities, options) with_options(:controller =&gt; resource_controller) do |map| resource.map_collection_actions(map) resource.map_default_actions(map) resource.map_new_actions(map) resource.map_member_actions(map) end if block_given? with_options(:path_prefix =&gt; resource.nesting_path_prefix, &#38;block) end end def map_singleton_resource(entities, options={}, &#38;block) resource = SingletonResource.new(entities, options) with_options(:controller =&gt; resource.controller) do |map| resource.map_collection_actions(map) resource.map_default_actions(map) resource.map_new_actions(map) resource.map_member_actions(map) end if block_given? with_options(:path_prefix =&gt; resource.nesting_path_prefix, &#38;block) end end </code></pre> <p>And now, we no longer have two method bodies that look very similar, apart from the resource class, we have to methods that look <em>identical</em> apart from the resource class. So, if we pull out the common bits and put them onto Resource, like so:</p> <pre><code> class ActionController::Resources::Resource def install_routes_in(map, &#38;block) map.with_options(:controller =&gt; controller) do |m| map_collection_actions(m) map_default_actions(m) map_new_actions(m) map_member_actions(m) end if block_given? map.with_options(:path_prefix =&gt; nesting_path_prefix, &#38;block) end end end </code></pre> <p>Then <code>map_resource</code> and <code>map_singleton_resource</code> become</p> <pre><code> def map_resource(entities, options = {}, &#38;block) Resource.new(entities, options).install_routes_in(self) end def map_singleton_resource(entities, options = {}, &#38;block) SingletonResource.new(entities, options).install_routes_in(self) end </code></pre> <h3>Where&#8217;s the benefit?</h3> <p>Apart from making the <code>active_record/lib/resources.rb</code> a bit shorter (a laudable result in itself), where&#8217;s the benefit here?</p> <p>From my own experience of implementing <code>datestamped_resource</code>, a routing plugin that we use in Typo, it makes the life of anyone writing a resource like routing helper for Rails a great deal easier. With <code>datestamped_resource</code> I ended up subclassing ActionController::Resources::Resource, doing the refactoring I&#8217;ve outlined here, but leaving the original Rails methods where they were and just implementing the &#8216;moved&#8217; methods on DatestampedResource (well, not quite, <code>map_collection_actions</code> is pretty different from the default Resource implementation, but the other actions are pretty much the same.</p> <p>In another project I&#8217;m working on, I&#8217;m trying to retain meaningful urls with (potentially) deep resource nesting, and it&#8217;d be really handy to have an <code>inflected_resource</code> route helper. The problem with using a meaningful <code>to_param</code> on your models is, avoiding permalinks that share a name with your actions. You could set up validations so that, say, &#8216;new&#8217; is an illegal permalinks, but it&#8217;s clumsy.</p> <p>However, if you arrange things so that your URLs are inflected, you can always tell that a <span class="caps">URL</span> that begins <code>/resource/new</code> will be a particular resource, with the permalink &#8216;new&#8217;, and <code>/resources/new</code> will be the virtual new resource.</p> <p>If the resource system is factored as I outlined, this is almost trivial, you can introduce a InflectedResource subclass of Resource</p> <pre><code> class InflectedResource &lt; Resource def member_path @new_path ||= #{path_prefix}/#{singular}/:id end end </code></pre> <p>and you&#8217;re pretty much done. Admittedly, something like that (plus a small amount of copy and paste) would work with the current system, but then we&#8217;re looking at 3 substantially identical methods in ActionController::Resources and if it wasn&#8217;t time to refactor before, it&#8217;d definitely be time to refactor then.</p> <h3>Conclusions</h3> <p>Reification shouldn&#8217;t be something you do every day, but nor should it be something you do once a flood. Take a look at some of your projects and some of the places where you&#8217;re using hashes. Are those <em>really</em> hashes, or would they benefit from having some behaviour of their own? You can track down stalled reification by looking for anaemic classes; classes which have a lot of accessors but very little behaviour. Once you&#8217;ve found an anaemic class, look for all the places that instances of it get used. Try moving some of the client code into methods on your anaemic class. Do that a few times and you&#8217;ll end up with a real object.</p> <p>If you&#8217;re fussy about never putting <span class="caps">HTML</span> in your models, you could end up with a mediating builder/presenter object as well, but until you start wanting to render the same structured info in different formats, I&#8217;d suggest biting the bullet and living with <span class="caps">HTML</span> in the model as a lesser evil than structural code. Your mileage may vary.</p> Wed, 22 Aug 2007 18:22:00 -0500 urn:uuid:3eced011-aa22-4695-9c13-85f654d50792 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/08/22/reification#comments Musings The Practice of Programming Ruby 5nouns http://www.bofh.org.uk/articles/2007/08/22/reification Five nouns for programmers <ul> <li>Reification</li> <li>Notation</li> <li>Reticence</li> <li>Lucidity</li> <li>Intent</li> </ul> <p>Learn &#8216;em. Live by them.</p> <p>What did I miss? Which ones don&#8217;t belong on the list. What am I talking about?</p> Mon, 20 Aug 2007 18:45:00 -0500 urn:uuid:37876d17-6ed0-49fb-94e0-62592bfe0f13 pdcawley@bofh.org.uk (Piers Cawley) http://www.bofh.org.uk/articles/2007/08/20/five-nouns-for-programmers#comments Musings The Practice of Programming gnomicutterances 5nouns http://www.bofh.org.uk/articles/2007/08/20/five-nouns-for-programmers