Showing preview only (1,818K chars total). Download the full file or copy to clipboard to get everything.
Repository: elm-city-craftworks/practicing-ruby-manuscripts
Branch: master
Commit: b675b2cf9eab
Files: 114
Total size: 1.7 MB
Directory structure:
gitextract_ccqrdc7w/
├── .gitignore
├── AUTHORS.md
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── articles/
│ ├── v1/
│ │ ├── 001-method-lookup.md
│ │ ├── 002-method-lookup.md
│ │ ├── 003-configurable.md
│ │ ├── 004-configurable.md
│ │ ├── 005-testing-antipatterns.md
│ │ ├── 006-good-and-bad-code.md
│ │ ├── 007-good-and-bad-code.md
│ │ ├── 008-uses-for-modules.md
│ │ ├── 009-uses-for-modules.md
│ │ ├── 010-uses-for-modules.md
│ │ ├── 010a-uses-for-modules.md
│ │ ├── 011-uses-for-modules.md
│ │ ├── 012-rapid-prototyping.md
│ │ ├── 013-obfuscations.md
│ │ ├── 014-duck-typing.md
│ │ ├── 015-duck-typing.md
│ │ ├── 016-interesting-ruby-hackers.md
│ │ ├── 017-interesting-ruby-writers.md
│ │ ├── 018-testing-dogma.md
│ │ ├── 019-thoughts-on-mocking.md
│ │ ├── 020-thoughts-on-mocking.md
│ │ ├── 021-how-to-practice.md
│ │ ├── 022-how-to-practice.md
│ │ ├── 023-solid-design.md
│ │ ├── 024-connascence.md
│ │ ├── 025-creational-design-patterns.md
│ │ ├── 026-structural-design-patterns.md
│ │ └── README.md
│ ├── v2/
│ │ ├── 001-ways-to-load-code.md
│ │ ├── 002-sticky-problems.md
│ │ ├── 003-closure-double-edged-sword.md
│ │ ├── 004-roll-your-own-enumerable-and-enumerator.md
│ │ ├── 005-regression-testing.md
│ │ ├── 006-learning-new-things-step-by-step.md
│ │ ├── 007-unobtrusive-ruby.md
│ │ ├── 008-singleton-pattern.md
│ │ ├── 009-unix-style-command-line-applications.md
│ │ ├── 010-from-requirements-discovery-to-release.md
│ │ ├── 011-domain-specific-api-construction.md
│ │ ├── 012-working-with-binary-file-formats.md
│ │ ├── 014-arguments-and-results-1.md
│ │ ├── 015-arguments-and-results-2.md
│ │ └── README.md
│ ├── v3/
│ │ ├── 001-quality-software.md
│ │ ├── 002-building-excellent-examples.md
│ │ ├── 003-turing-tarpit.md
│ │ ├── 004-climbing-the-spiral-staircase-of-refactoring.md
│ │ ├── 005-framework-design-and-implementation.md
│ │ ├── 006-framework-design-and-implementation.md
│ │ ├── 007-criteria-for-disciplined-inheritance.md
│ │ ├── 008-criteria-for-disciplined-inheritance.md
│ │ ├── 009-using-games-to-practice-domain-modeling.md
│ │ ├── 010-robustness.md
│ │ └── README.md
│ ├── v4/
│ │ ├── 001-testing-costs-benefits.md
│ │ ├── 002-moving-beyond-the-first-release.md
│ │ ├── 004-cheap-counterfeits-jekyll.md
│ │ ├── 005-scoring-predictions-kata.md
│ │ ├── 006-persisting-relations.md
│ │ ├── 007-confident-ruby.md
│ │ ├── 008-implementing-active-record.md
│ │ ├── 009-the-hidden-costs-of-inheritance.md
│ │ ├── 010-implementing-active-record.md
│ │ ├── 011-responsibility-vs-data-driven.md
│ │ ├── 012-tdd-lessons-learned.md
│ │ ├── 012.1-tdd-lessons-learned-lesson-1.md
│ │ ├── 012.2-tdd-lessons-learned-lesson-2.md
│ │ ├── 012.3-tdd-lessons-learned-lesson-3.md
│ │ ├── 012.4-tdd-lessons-learned-lesson-4.md
│ │ └── README.md
│ ├── v5/
│ │ ├── 001-statistical-modeling.md
│ │ ├── 002-rocket-science-and-lod.md
│ │ ├── 003-evented-io.md
│ │ ├── 004-service-apis.md
│ │ ├── 005-process-spawning-patterns.md
│ │ ├── 006-service-quality.md
│ │ ├── 007-dependencies-notifications-and-adjustments.md
│ │ ├── 008-clojure.md
│ │ ├── 009-ants.md
│ │ ├── 010-prototypes.md
│ │ └── README.md
│ ├── v6/
│ │ ├── 001-parsing-json.md
│ │ ├── 002-code-reading.md
│ │ ├── 003-actors.md
│ │ ├── 004-code-reuse.md
│ │ ├── 005-debugging.md
│ │ ├── 006-recipes-method-bloat.md
│ │ ├── 007-demeter.md
│ │ ├── 008-procedural-to-oop.md
│ │ ├── 009-isolate-responsibilities.md
│ │ ├── 010-concept-before-code.md
│ │ └── README.md
│ ├── v7/
│ │ ├── 001-simulating-tiny-worlds.md
│ │ ├── 002-http-server.md
│ │ ├── 003-stats.md
│ │ ├── 004-incremental.md
│ │ ├── 005-low-level.md
│ │ ├── 006-infrastructure.md
│ │ ├── 007-wumpus.md
│ │ ├── 008-language-learning.md
│ │ ├── 008-oss-quality.md
│ │ ├── 009-course1.md
│ │ ├── 010-information.md
│ │ └── README.md
│ └── v8/
│ ├── 001-problem-discovery.md
│ ├── 002-formula-processing.md
│ └── README.md
└── templates/
└── default.html.erb
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
articles-html
================================================
FILE: AUTHORS.md
================================================
The articles within this repository are copyrighted works, released under a
creative commons license by their respective authors. Contributors to these
articles retain their own copyright, but must agree to release their content
under the same license as the original source materials.
* All articles in Practicing Ruby volume 1 and volume 2 were written
by Gregory Brown ( gregory@practicingruby.com ).
================================================
FILE: Gemfile
================================================
source 'https://rubygems.org'
gem "rake"
gem "kramdown"
gem "coderay"
================================================
FILE: LICENSE.txt
================================================
Creative Commons Legal Code
Attribution-ShareAlike 3.0 Unported
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
DAMAGES RESULTING FROM ITS USE.
License
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
CONDITIONS.
1. Definitions
a. "Adaptation" means a work based upon the Work, or upon the Work and
other pre-existing works, such as a translation, adaptation,
derivative work, arrangement of music or other alterations of a
literary or artistic work, or phonogram or performance and includes
cinematographic adaptations or any other form in which the Work may be
recast, transformed, or adapted including in any form recognizably
derived from the original, except that a work that constitutes a
Collection will not be considered an Adaptation for the purpose of
this License. For the avoidance of doubt, where the Work is a musical
work, performance or phonogram, the synchronization of the Work in
timed-relation with a moving image ("synching") will be considered an
Adaptation for the purpose of this License.
b. "Collection" means a collection of literary or artistic works, such as
encyclopedias and anthologies, or performances, phonograms or
broadcasts, or other works or subject matter other than works listed
in Section 1(f) below, which, by reason of the selection and
arrangement of their contents, constitute intellectual creations, in
which the Work is included in its entirety in unmodified form along
with one or more other contributions, each constituting separate and
independent works in themselves, which together are assembled into a
collective whole. A work that constitutes a Collection will not be
considered an Adaptation (as defined below) for the purposes of this
License.
c. "Creative Commons Compatible License" means a license that is listed
at http://creativecommons.org/compatiblelicenses that has been
approved by Creative Commons as being essentially equivalent to this
License, including, at a minimum, because that license: (i) contains
terms that have the same purpose, meaning and effect as the License
Elements of this License; and, (ii) explicitly permits the relicensing
of adaptations of works made available under that license under this
License or a Creative Commons jurisdiction license with the same
License Elements as this License.
d. "Distribute" means to make available to the public the original and
copies of the Work or Adaptation, as appropriate, through sale or
other transfer of ownership.
e. "License Elements" means the following high-level license attributes
as selected by Licensor and indicated in the title of this License:
Attribution, ShareAlike.
f. "Licensor" means the individual, individuals, entity or entities that
offer(s) the Work under the terms of this License.
g. "Original Author" means, in the case of a literary or artistic work,
the individual, individuals, entity or entities who created the Work
or if no individual or entity can be identified, the publisher; and in
addition (i) in the case of a performance the actors, singers,
musicians, dancers, and other persons who act, sing, deliver, declaim,
play in, interpret or otherwise perform literary or artistic works or
expressions of folklore; (ii) in the case of a phonogram the producer
being the person or legal entity who first fixes the sounds of a
performance or other sounds; and, (iii) in the case of broadcasts, the
organization that transmits the broadcast.
h. "Work" means the literary and/or artistic work offered under the terms
of this License including without limitation any production in the
literary, scientific and artistic domain, whatever may be the mode or
form of its expression including digital form, such as a book,
pamphlet and other writing; a lecture, address, sermon or other work
of the same nature; a dramatic or dramatico-musical work; a
choreographic work or entertainment in dumb show; a musical
composition with or without words; a cinematographic work to which are
assimilated works expressed by a process analogous to cinematography;
a work of drawing, painting, architecture, sculpture, engraving or
lithography; a photographic work to which are assimilated works
expressed by a process analogous to photography; a work of applied
art; an illustration, map, plan, sketch or three-dimensional work
relative to geography, topography, architecture or science; a
performance; a broadcast; a phonogram; a compilation of data to the
extent it is protected as a copyrightable work; or a work performed by
a variety or circus performer to the extent it is not otherwise
considered a literary or artistic work.
i. "You" means an individual or entity exercising rights under this
License who has not previously violated the terms of this License with
respect to the Work, or who has received express permission from the
Licensor to exercise rights under this License despite a previous
violation.
j. "Publicly Perform" means to perform public recitations of the Work and
to communicate to the public those public recitations, by any means or
process, including by wire or wireless means or public digital
performances; to make available to the public Works in such a way that
members of the public may access these Works from a place and at a
place individually chosen by them; to perform the Work to the public
by any means or process and the communication to the public of the
performances of the Work, including by public digital performance; to
broadcast and rebroadcast the Work by any means including signs,
sounds or images.
k. "Reproduce" means to make copies of the Work by any means including
without limitation by sound or visual recordings and the right of
fixation and reproducing fixations of the Work, including storage of a
protected performance or phonogram in digital form or other electronic
medium.
2. Fair Dealing Rights. Nothing in this License is intended to reduce,
limit, or restrict any uses free from copyright or rights arising from
limitations or exceptions that are provided for in connection with the
copyright protection under copyright law or other applicable laws.
3. License Grant. Subject to the terms and conditions of this License,
Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
perpetual (for the duration of the applicable copyright) license to
exercise the rights in the Work as stated below:
a. to Reproduce the Work, to incorporate the Work into one or more
Collections, and to Reproduce the Work as incorporated in the
Collections;
b. to create and Reproduce Adaptations provided that any such Adaptation,
including any translation in any medium, takes reasonable steps to
clearly label, demarcate or otherwise identify that changes were made
to the original Work. For example, a translation could be marked "The
original work was translated from English to Spanish," or a
modification could indicate "The original work has been modified.";
c. to Distribute and Publicly Perform the Work including as incorporated
in Collections; and,
d. to Distribute and Publicly Perform Adaptations.
e. For the avoidance of doubt:
i. Non-waivable Compulsory License Schemes. In those jurisdictions in
which the right to collect royalties through any statutory or
compulsory licensing scheme cannot be waived, the Licensor
reserves the exclusive right to collect such royalties for any
exercise by You of the rights granted under this License;
ii. Waivable Compulsory License Schemes. In those jurisdictions in
which the right to collect royalties through any statutory or
compulsory licensing scheme can be waived, the Licensor waives the
exclusive right to collect such royalties for any exercise by You
of the rights granted under this License; and,
iii. Voluntary License Schemes. The Licensor waives the right to
collect royalties, whether individually or, in the event that the
Licensor is a member of a collecting society that administers
voluntary licensing schemes, via that society, from any exercise
by You of the rights granted under this License.
The above rights may be exercised in all media and formats whether now
known or hereafter devised. The above rights include the right to make
such modifications as are technically necessary to exercise the rights in
other media and formats. Subject to Section 8(f), all rights not expressly
granted by Licensor are hereby reserved.
4. Restrictions. The license granted in Section 3 above is expressly made
subject to and limited by the following restrictions:
a. You may Distribute or Publicly Perform the Work only under the terms
of this License. You must include a copy of, or the Uniform Resource
Identifier (URI) for, this License with every copy of the Work You
Distribute or Publicly Perform. You may not offer or impose any terms
on the Work that restrict the terms of this License or the ability of
the recipient of the Work to exercise the rights granted to that
recipient under the terms of the License. You may not sublicense the
Work. You must keep intact all notices that refer to this License and
to the disclaimer of warranties with every copy of the Work You
Distribute or Publicly Perform. When You Distribute or Publicly
Perform the Work, You may not impose any effective technological
measures on the Work that restrict the ability of a recipient of the
Work from You to exercise the rights granted to that recipient under
the terms of the License. This Section 4(a) applies to the Work as
incorporated in a Collection, but this does not require the Collection
apart from the Work itself to be made subject to the terms of this
License. If You create a Collection, upon notice from any Licensor You
must, to the extent practicable, remove from the Collection any credit
as required by Section 4(c), as requested. If You create an
Adaptation, upon notice from any Licensor You must, to the extent
practicable, remove from the Adaptation any credit as required by
Section 4(c), as requested.
b. You may Distribute or Publicly Perform an Adaptation only under the
terms of: (i) this License; (ii) a later version of this License with
the same License Elements as this License; (iii) a Creative Commons
jurisdiction license (either this or a later license version) that
contains the same License Elements as this License (e.g.,
Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible
License. If you license the Adaptation under one of the licenses
mentioned in (iv), you must comply with the terms of that license. If
you license the Adaptation under the terms of any of the licenses
mentioned in (i), (ii) or (iii) (the "Applicable License"), you must
comply with the terms of the Applicable License generally and the
following provisions: (I) You must include a copy of, or the URI for,
the Applicable License with every copy of each Adaptation You
Distribute or Publicly Perform; (II) You may not offer or impose any
terms on the Adaptation that restrict the terms of the Applicable
License or the ability of the recipient of the Adaptation to exercise
the rights granted to that recipient under the terms of the Applicable
License; (III) You must keep intact all notices that refer to the
Applicable License and to the disclaimer of warranties with every copy
of the Work as included in the Adaptation You Distribute or Publicly
Perform; (IV) when You Distribute or Publicly Perform the Adaptation,
You may not impose any effective technological measures on the
Adaptation that restrict the ability of a recipient of the Adaptation
from You to exercise the rights granted to that recipient under the
terms of the Applicable License. This Section 4(b) applies to the
Adaptation as incorporated in a Collection, but this does not require
the Collection apart from the Adaptation itself to be made subject to
the terms of the Applicable License.
c. If You Distribute, or Publicly Perform the Work or any Adaptations or
Collections, You must, unless a request has been made pursuant to
Section 4(a), keep intact all copyright notices for the Work and
provide, reasonable to the medium or means You are utilizing: (i) the
name of the Original Author (or pseudonym, if applicable) if supplied,
and/or if the Original Author and/or Licensor designate another party
or parties (e.g., a sponsor institute, publishing entity, journal) for
attribution ("Attribution Parties") in Licensor's copyright notice,
terms of service or by other reasonable means, the name of such party
or parties; (ii) the title of the Work if supplied; (iii) to the
extent reasonably practicable, the URI, if any, that Licensor
specifies to be associated with the Work, unless such URI does not
refer to the copyright notice or licensing information for the Work;
and (iv) , consistent with Ssection 3(b), in the case of an
Adaptation, a credit identifying the use of the Work in the Adaptation
(e.g., "French translation of the Work by Original Author," or
"Screenplay based on original Work by Original Author"). The credit
required by this Section 4(c) may be implemented in any reasonable
manner; provided, however, that in the case of a Adaptation or
Collection, at a minimum such credit will appear, if a credit for all
contributing authors of the Adaptation or Collection appears, then as
part of these credits and in a manner at least as prominent as the
credits for the other contributing authors. For the avoidance of
doubt, You may only use the credit required by this Section for the
purpose of attribution in the manner set out above and, by exercising
Your rights under this License, You may not implicitly or explicitly
assert or imply any connection with, sponsorship or endorsement by the
Original Author, Licensor and/or Attribution Parties, as appropriate,
of You or Your use of the Work, without the separate, express prior
written permission of the Original Author, Licensor and/or Attribution
Parties.
d. Except as otherwise agreed in writing by the Licensor or as may be
otherwise permitted by applicable law, if You Reproduce, Distribute or
Publicly Perform the Work either by itself or as part of any
Adaptations or Collections, You must not distort, mutilate, modify or
take other derogatory action in relation to the Work which would be
prejudicial to the Original Author's honor or reputation. Licensor
agrees that in those jurisdictions (e.g. Japan), in which any exercise
of the right granted in Section 3(b) of this License (the right to
make Adaptations) would be deemed to be a distortion, mutilation,
modification or other derogatory action prejudicial to the Original
Author's honor and reputation, the Licensor will waive or not assert,
as appropriate, this Section, to the fullest extent permitted by the
applicable national law, to enable You to reasonably exercise Your
right under Section 3(b) of this License (right to make Adaptations)
but not otherwise.
5. Representations, Warranties and Disclaimer
UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION
OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
7. Termination
a. This License and the rights granted hereunder will terminate
automatically upon any breach by You of the terms of this License.
Individuals or entities who have received Adaptations or Collections
from You under this License, however, will not have their licenses
terminated provided such individuals or entities remain in full
compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
survive any termination of this License.
b. Subject to the above terms and conditions, the license granted here is
perpetual (for the duration of the applicable copyright in the Work).
Notwithstanding the above, Licensor reserves the right to release the
Work under different license terms or to stop distributing the Work at
any time; provided, however that any such election will not serve to
withdraw this License (or any other license that has been, or is
required to be, granted under the terms of this License), and this
License will continue in full force and effect unless terminated as
stated above.
8. Miscellaneous
a. Each time You Distribute or Publicly Perform the Work or a Collection,
the Licensor offers to the recipient a license to the Work on the same
terms and conditions as the license granted to You under this License.
b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
offers to the recipient a license to the original Work on the same
terms and conditions as the license granted to You under this License.
c. If any provision of this License is invalid or unenforceable under
applicable law, it shall not affect the validity or enforceability of
the remainder of the terms of this License, and without further action
by the parties to this agreement, such provision shall be reformed to
the minimum extent necessary to make such provision valid and
enforceable.
d. No term or provision of this License shall be deemed waived and no
breach consented to unless such waiver or consent shall be in writing
and signed by the party to be charged with such waiver or consent.
e. This License constitutes the entire agreement between the parties with
respect to the Work licensed here. There are no understandings,
agreements or representations with respect to the Work not specified
here. Licensor shall not be bound by any additional provisions that
may appear in any communication from You. This License may not be
modified without the mutual written agreement of the Licensor and You.
f. The rights granted under, and the subject matter referenced, in this
License were drafted utilizing the terminology of the Berne Convention
for the Protection of Literary and Artistic Works (as amended on
September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996
and the Universal Copyright Convention (as revised on July 24, 1971).
These rights and subject matter take effect in the relevant
jurisdiction in which the License terms are sought to be enforced
according to the corresponding provisions of the implementation of
those treaty provisions in the applicable national law. If the
standard suite of rights granted under applicable copyright law
includes additional rights not granted under this License, such
additional rights are deemed to be included in the License; this
License is not intended to restrict the license of any rights under
applicable law.
Creative Commons Notice
Creative Commons is not a party to this License, and makes no warranty
whatsoever in connection with the Work. Creative Commons will not be
liable to You or any party on any legal theory for any damages
whatsoever, including without limitation any general, special,
incidental or consequential damages arising in connection to this
license. Notwithstanding the foregoing two (2) sentences, if Creative
Commons has expressly identified itself as the Licensor hereunder, it
shall have all rights and obligations of Licensor.
Except for the limited purpose of indicating to the public that the
Work is licensed under the CCPL, Creative Commons does not authorize
the use by either party of the trademark "Creative Commons" or any
related trademark or logo of Creative Commons without the prior
written consent of Creative Commons. Any permitted use will be in
compliance with Creative Commons' then-current trademark usage
guidelines, as may be published on its website or otherwise made
available upon request from time to time. For the avoidance of doubt,
this trademark restriction does not form part of the License.
Creative Commons may be contacted at http://creativecommons.org/.
================================================
FILE: README.md
================================================
## Practicing Ruby: Manuscripts archive
This is a collection of publicly released articles from the [Practicing
Ruby](http://practicingruby.com) journal.
You are welcome to use these materials as you see fit, as long as you
abide by the terms of the [Creative Commons Attribution-ShareAlike 3.0
Unported](http://creativecommons.org/licenses/by-sa/3.0/) license.
Make sure to include a clear reference to practicingruby.com anywhere you make
use of these materials. It'd also be nice for you to link to
http://github.com/elm-city-craftworks/practicing-ruby-manuscripts so
that others can find these source materials, but that is optional.
Please see the AUTHORS.md file in this repository for copyright information.
For any questions, please contact gregory@practicingruby.com. I am especially
interested in hearing from folks who would like to translate these articles into
other languages (both spoken languages and programming languages!), but I'd love
to hear from anyone who wishes to make use of these materials for any purpose.
## To support my work, please subscribe at practicingruby.com
I believe that it's only right for me to release my articles under a free
documentation license, but this project is still a TON of work,
and would not exist without my subscribers. You can make it possible for me
to keep publishing by signing up for a paid account. It's only $8/month, and it's totally worth it.
================================================
FILE: Rakefile
================================================
require "kramdown"
require "coderay"
require "fileutils"
MARKDOWN_FILES = Dir.glob("#{__dir__}/articles/**/*.md")
task default: :html_files
desc "Generate HTML files from markdown articles"
task :html_files do
MARKDOWN_FILES.each do |markdown_file|
html_path = markdown_file.sub("/articles/", "/articles-html/").sub(/\.md$/, ".html")
puts "Generating #{html_path}"
FileUtils.mkdir_p(File.dirname(html_path))
File.open(html_path, "w") do |html_file|
filecontent = File.read(markdown_file)
filecontent = filecontent.gsub("\`\`\`", "~~~")
filecontent = Kramdown::Document.new(filecontent, template: "#{__dir__}/templates/default.html.erb")
html_file.write(filecontent.to_html)
end
end
end
desc "Delete all generated HTML files"
task :clean do
FileUtils.rm_rf("#{__dir__}/articles-html")
end
================================================
FILE: articles/v1/001-method-lookup.md
================================================
I decided to start off this newsletter with one of the most basic but essential pieces of knowledge you can have about Ruby's object model: the way it looks up methods. Let's do a little exploration by working through a few examples.
Below we have a simple report class tasked with performing some basic data manipulations and then producing some text output.
```ruby
class Report
def initialize(ledger)
@balance = ledger.inject(0) { |sum, (k,v)| sum + v }
@credits, @debits = ledger.partition { |k,v| v > 0 }
end
attr_reader :credits, :debits, :balance
def formatted_output
"Current Balance: #{balance}\n\n" +
"Credits:\n\n#{formatted_line_items(credits)}\n\n" +
"Debits:\n\n#{formatted_line_items(debits)}"
end
def formatted_line_items(items)
items.map { |k, v| "#{k}: #{'%.2f' % v.abs}" }.join("\n")
end
end
```
The following example demonstrates how we'd make use of this class.
```ruby
ledger = [ ["Deposit Check #123", 500.15],
["Fancy Shoes", -200.25],
["Fancy Hat", -54.40],
["ATM Deposit", 1200.00],
["Kitteh Litteh", -5.00] ]
report = Report.new(ledger)
puts report.formatted_output
```
And for those who don't want to take the time to copy and paste this code and run it locally, the actual output is shown below.
```
Current Balance: 1440.5
Credits:
Deposit Check #123: 500.15
ATM Deposit: 1200.00
Debits:
Fancy Shoes: 200.25
Fancy Hat: 54.40
Kitteh Litteh: 5.00
```
While not particularly pretty, this report is mostly what we'd expect to see. You can probably imagine how this information might be embedded within another report, such as an email-based form letter with some header and footer information. One possible way to do this would be through class inheritance, as in the example below.
```ruby
require "date"
class EmailReport < Report
def header
"Dear Valued Customer,\n\n"+
"This report shows your account activity as of #{Date.today}\n"
end
def banner
"\n............................................................\n"
end
def formatted_output
header + banner + super + banner + footer
end
def footer
"\nWith Much Love,\nYour Faceless Banking Institution"
end
end
```
We only need to make a minor change to our calling code to make use of this new class.
```ruby
ledger = [ ["Deposit Check #123", 500.15],
["Fancy Shoes", -200.25],
["Fancy Hat", -54.40],
["ATM Deposit", 1200.00],
["Kitteh Litteh", -5.00] ]
report = EmailReport.new(ledger)
puts report.formatted_output
```
Below you can see what the new output ends up looking like.
```
Dear Valued Customer,
The following report shows your account activity as of 2010-11-09
............................................................
Current Balance: 1440.5
Credits:
Deposit Check #123: 500.15
ATM Deposit: 1200.00
Debits:
Fancy Shoes: 200.25
Fancy Hat: 54.40
Kitteh Litteh: 5.00
............................................................
With Much Love,
Your Faceless Banking Institution
```
Looking back at the `EmailReport` code, it's easy to see what we've done to produce this new output. We've defined a new `formatted_output` method which adds the headers and footers, and combined this new behavior with the original behavior of our `Report` class by calling `super`. This is the same extension by inheritance pattern that you'll learn in any basic computer science course or encounter in any of the reasonably traditional object oriented languages out there.
But before you go asking for a refund and start telling your friends that this newsletter is painfully dull, consider this: While many languages have a method lookup path which is based on inheritance alone, that isn't even close to being true about Ruby.
Because Ruby allows for module mixins and per-object behavior, the `super` keyword takes on a whole new life in which an object's superclass is the last stop on a five part journey through Ruby's object model. The following example proves the point by composing a simple string which demonstrates the order in which methods are resolved in Ruby.
```ruby
module W
def foo
"- Mixed in method defined by W\n" + super
end
end
module X
def foo
"- Mixed in method defined by X\n" + super
end
end
module Y
def foo
"- Mixed in method defined by Y\n" + super
end
end
module Z
def foo
"- Mixed in method defined by Z\n" + super
end
end
class A
def foo
"- Instance method defined by A\n"
end
end
class B < A
include W
include X
def foo
"- Instance method defined by B\n" + super
end
end
object = B.new
object.extend(Y)
object.extend(Z)
def object.foo
"- Method defined directly on an instance of B\n" + super
end
puts object.foo
```
When we run this code, we see the following output, which traces the `super` calls all the way up from the method defined directly on our object to its superclass.
```
- Method defined directly on an instance of B
- Mixed in method defined by Z
- Mixed in method defined by Y
- Instance method defined by B
- Mixed in method defined by X
- Mixed in method defined by W
- Instance method defined by A
```
As promised, it's a five step journey. Particularly, the above is a demonstration that Ruby methods are looked up in the following order:
1. Methods defined in the object's singleton class (i.e. the object itself)
1. Modules mixed into the singleton class in reverse order of inclusion
1. Methods defined by the object's class
1. Modules included into the object's class in reverse order of inclusion
1. Methods defined by the object's superclass.
This process is then repeated all the way up the inheritance chain until `BasicObject` is reached. Now that we know the basic order, we should stop and consider a few questions about what we've discussed so far.
### Open Questions / Things To Explore
* Why would we want or need five distinct places to define methods? Do these other options really gain us anything over ordinary inheritance?
* Does this change the way that classic object oriented design principles apply to Ruby? For example, how well do you think direct translations of design patterns map to Ruby?
* Think of each place you can define a method in Ruby, and consider which ones are important for every day use, and which ones are edge cases. Is per-object behavior really that useful?
* It is rare to use all of these options at once, and the only reason it was done in this exercise was for demonstration purposes. But taken individually, can you think of a practical use for each way of defining Ruby methods?
* What are some disadvantages for each technique shown here?
I will address these points and also go over some practical applications in the next issue, but please share your own thoughts in the comments section below.
> **NOTE:** This article has also been published on the Ruby Best Practices blog. There [may be additional commentary](http://blog.rubybestpractices.com/posts/gregory/030-issue-1-method-lookup.html#disqus_thread)
over there worth taking a look at.
================================================
FILE: articles/v1/002-method-lookup.md
================================================
In [Issue #1](http://practicingruby.com/articles/29) we discussed Ruby's lookup
path and proved by example that class inheritance is only a small part of the
picture. To recap, Ruby methods are looked up in the following order:
1. Methods defined in the object's singleton class (i.e. the object itself)
1. Modules mixed into the singleton class in reverse order of inclusion
1. Methods defined by the object's class
1. Modules included into the object's class in reverse order of inclusion
1. Methods defined by the object's superclass, i.e. inherited methods
The example we looked at in the previous issue just showed the mechanics of how the above process plays out, it didn't really hint at practical use cases. Today, we'll look at a scenario for each of these options and discuss some of the up and downs that come along with them. Rather than presenting the examples in method lookup order, I'll try to start with the most common ones and work my way out to the more special purpose ones.
> **NOTE:** In a comment on issue #1, <a href="http://twitter.com/jeg2">@JEG2</a> correctly pointed out that this roadmap doesn't account for what happens after the whole class hierarchy is walked. Once `BasicObject` is reached, Ruby starts from the bottom again calling the `method_missing` hook, which is essentially an implicit step 6. I left this detail out for the sake of simplicity, but it's very important to at least be aware of.
### When to use ordinary class definitions
The following code implements a simple timer that can write out a timestamp to a file and read it back later to determine elapsed time. Study it and consider its design.
```ruby
class Timer
MissingTimestampError = Class.new(StandardError)
def initialize(dir=Turbine::Application.config_dir)
@file = "#{dir}/timestamp"
end
def write_timestamp
File.open(@file, "w") { |f| f << Time.now.utc.to_s }
end
def timestamp
raise MissingTimestampError unless running?
Time.parse(File.read(@file)).localtime
end
def elapsed_time
(Time.now.utc - timestamp.utc) / 60.0 / 60.0
end
def clear_timestamp
FileUtils.rm_f(@file)
end
def running?
File.exist?(@file)
end
end
```
When deciding if just a plain old class definition will do, I often ask myself several questions.
* Is it likely is that I'll need to customize this code later for another purpose?
* Is this code meant to be interacted with and extended by third party code?
* Are there any common behaviors in this code I'd want to extract and use elsewhere?
Because this `Timer` class definition comes from a real project of mine, I can tell you that the answer to all of the above questions in the context this code is intended to be used is a simple 'no'. What this indicates to me is that while extension might be necessary at some point down the line, there is no immediate need to design for extensibility, and so we go with the most simple option that could possibly work.
Another indicator that a plain class definition might be appropriate here is the fact that most of the functionality in this class is centered around manipulating a particular bit of state, the <i>timestamp</i> file. The problem we are trying to solve is quite a narrow one, and a single-minded class definition reflects that.
The downside to designing code this way is that it does make third-party modification harder. If for example, you wanted to add some behavior around the `timestamp()` method, you have three options, none of them great:
* You can create a subclass of `Timer`, but your new class won't be used by the application that defined `Timer` without modification.
* You can create an instance of `Timer` and then add per-object behavior, but this has the same problem as subclassing.
* You can use `alias_method` to create a monkeypatch to `Timer`, which will inject your code into the original application, but runs risks of naming clashes and other nasty things.
While it ultimately depends on how the calling code uses this `Timer` class, and what features are provided for making extensions, it's not going to be trivial to modify systems built in this fashion. But because we already determined this was a narrow bit of functionality designed to be used internally within a larger application, it isn't a problem that it isn't super extendable.
Many of the rules that apply to defining your own classes also apply to inheritance based designs, so let's investigate that now.
### When Inheritance Makes Sense
For those working with Rails, you already encounter class inheritance on a daily basis, through the ActiveRecord ORM. Despite the terrible choice of name, `ActiveRecord::Base` is a reasonable example of when class inheritance is a decent option.
Consider the typical ActiveRecord model, which is often extremely simple:
```ruby
class User < ActiveRecord::Base
has_many :comments
validates_presence_of :name, :email
end
```
While it's true that in most interesting applications, models do become more complex, implementing intricate business logic, the amount of functionality added by the user is dwarfed by what ActiveRecord provides.
One key thing to notice about a subclass of `ActiveRecord::Base` is that by design, there is really no incentive to manage your own state. All state manipulation is passed upwards to the parent class to handle, which typically involves using a pre-configured database connection also managed by the parent class to persist whatever state is required.
Inheritance makes sense in situations where complex state manipulations are handled by the parent class. This is especially true if the parent class provides a boat-load of functionality which dwarfs the customization needs of the child class. Since both things are true about a typical ActiveRecord model, the design is certainly a reasonable choice.
However, before you start modeling your own projects after this pattern, you should take a look at the great pains that go into designing an extensible parent class. It's outside the scope of this article, but I'd recommend reading what <a href="http://is.gd/gW558 ">Yehuda Katz has to say about ActiveModel</a>, which provides the bulk of ActiveRecord's functionality under the hood.
Before we move on to other topics, I'd like to offer another example outside of the Rails world, just to help further illuminate the pattern.
The PDF generation library <a href="http://prawn.majesticseacreature.com">Prawn</a> provides a class that's designed to be inherited from, `Prawn::Document`. I made use of this functionality recently to build a small typesetting library for formatting technical articles. While I won't go into much detail here, you can check out the <a href="http://github.com/madriska/jambalaya">implementation and example code</a>.
What you'll find in <a href="https://github.com/madriska/jambalaya/blob/master/lib/jambalaya.rb">lib/jambalaya.rb</a> is that except for a custom factory method for generating the document, Jambalaya introduces no new state, relying on calls to `Prawn::Document` to do all the heavy lifting. You can also see that <a href="https://github.com/madriska/jambalaya/blob/master/example/rbp_ch1.rb">examples/rbp_ch1.rb</a> gives the illusion of a new special purpose DSL, but that in truth, almost all the work is being done by Prawn under the hood.
Unfortunately, the disadvantages of class inheritance become clear the farther away you get from these scenarios in which the subclass truly is analogous to its parent class. You get only one parent class, and chaining to it is a commitment that you must be willing to respect all the way up the hierarchy. For the scenarios we've shown, the benefits outweigh the drawbacks, but for many others, they do not.
In Issue #1, I asked the question of which techniques are special cases, and which are meant to be used commonly. While not rare by any means, inheritance falls closer to being a special case than it does to being the first tool you should reach for. If this comes as a surprise to you, it's about time for us to talk about modules.
### Mixing modules into a class
If you want to see the power of mixins, you need to look no farther than Ruby's
`Enumerable` module. Rather than relying on a common base class to provide
iterators for collections, Ruby mixes in the `Enumerable` module into its core structures,
including `Array` and `Hash`. This is where a whole host of useful methods come from,
including `map`, `select`, and `inject`.
The beauty of this design is that it imposes a much lighter contract than the rigid is-a relationship enforced by class inheritance. Instead, mixins focuses on what you can do with an object rather than what that object is. It makes perfect sense to say both `Hash` and `Array` objects have elements that can be enumerated over. As far as Ruby is concerned, the same can be true about any object which defines an `each()` method.
Let's take a look at a custom Ruby class which implements each and mixes in
`Enumerable`. It is a simple file-backed numerical queue, from the same project
our `Timer` came from.
```ruby
class Queue
include Enumerable
def initialize(file)
@file = file
end
def entries
return [] if empty?
File.read(@file).split("\n").map { |e| e.to_f }
end
def each
entries.each { |e| yield(e) }
end
# additional unrelated methods omitted
end
```
The data file this queue wraps looked something similar to the data shown below.
```
125.75
100.25
300.50
700
```
Given a properly formatted input file, it's possible to interact with the `Queue` like any other `Enumerable` object.
```ruby
queue = Queue.new("queue.txt")
p queue.map { |x| "Amount: #{x}" }
p queue.inject { |x,y| x + y }
```
If you go ahead and try this yourself, you'll find that it will work identically if you simply replace the first line with an array, as shown below.
```ruby
queue = [125.75, 100.25, 300.50, 700]
p queue.map { |x| "Amount: #{x}" }
p queue.inject { |x,y| x + y }
```
This simple example hints at the real beauty of `Enumerable` in particular, and the mixin technique in general. In reality, my `Queue` object and Ruby's `Array` class have very little in common. But in the context of how you can iterate over the two objects, they can share a matching interface for the things they do have in common.
This is where modules shine. They allow some of the benefits of inheritance in that they allow implementation sharing, but without the requirement of organizing things into a rigid class hierarchy. Things get even more interesting when you remember to tie your understanding of how modules work back to the way Ruby looks up methods.
### Exploiting the lookup order of mixins
Methods are looked up in mixins in reverse order of their inclusion, giving the last module you mixed in a priority spot in the lookup path. A pleasant effect that arises naturally from this rule is that it provides an elegant technique for monkey patching that does not rely on method aliasing. Let's look at a patch that uses method aliasing, and how it could be written differently.
Below is the code that Rubygems uses to patch `require` to add in gem loading functionality. Since `require` is just a method in Ruby, and not a keyword, the patch is relatively straightforward in pure Ruby.
```ruby
module Kernel
alias gem_original_require require
def require(path) # :doc:
gem_original_require path
rescue LoadError => load_error
if load_error.message.end_with?(path)
if Gem.try_activate(path)
return gem_original_require(path)
end
end
raise load_error
end
end
```
At the time this code was written, using method aliasing was the standard way of changing the behavior of an existing method. Aliases are used to make a copy of an existing method before modifying it, which allows customized code to delegate to the original method. This permits re-using the parts of the original method that are needed while (hopefully) preventing issues with backwards compatibility. The general approach works well, but it increases the chances that the copied methods will clash with each other as the chain gets longer, and also adds a number of superfluous methods to objects that are really just implementation details.
Taking advantage of Ruby's method lookup order in modules, we can get around the issues with aliasing by writing a patch similar to the one shown below.
```ruby
module GemCustomRequire
def require(path) # :doc:
super
rescue LoadError => load_error
if load_error.message.end_with?(path)
if Gem.try_activate(path)
return super
end
end
raise load_error
end
end
class Object
include GemCustomRequire
end
```
Because the original `require()` method is defined within the `Kernel` module and not on `Object` itself, we can include our `GemCustomRequire` module and then use `super` to call the original require. The result is code that looks more natural and ordinary, reducing the amount of magic you need to know in order to understand it. It also completely avoids the possible issue of copied methods clashing with one another.
This ability to do safe monkeypatching that modules affords us has been picking up steam within popular Ruby projects. Rails 3 was in a large extent designed to afford this sort of modularity, for the express purpose of making it easier for third party plugins to hook into the system in a more graceful way than method aliasing. Other projects that require a high degree of extensibility are quickly following in its footsteps, which is a good thing.
While you're less likely to run into this question in application code than you are in library or framework code, knowing what mixins can gain you in terms of extensibility can really come in handy. There are tons of other good things to say about modules, but we'll need to save those for another day.
### Per Object Behavior
I was originally going to go into detail about mixing modules into individual objects as well as defining singleton methods. However, I think that can be a topic all of it's own, and I want to give it a proper treatment rather than tacking it on to the end of an already lengthy newsletter.
I promise we'll revisit it soon, but for those who absolutely want to explore potential uses of these techniques right away, I offer two small challenges.
1) Rather than using a framework for testing stubs, experiment with something like the code below next time you're writing tests.
```ruby
obj = Object.new
class << obj
def my_stubbed_method
end
end
```
2) Rather than re-opening a class to add some extra behavior, experiment with mixing modules into individual objects to get the extra features you need.
```ruby
module MathHelpers
def sum
inject { |x,y| x + y }
end
def average
sum.to_f / length
end
end
array = [1,2,3]
array.extend(MathHelpers)
p array.average
```
If you try these ideas out, you'll almost certainly find uses for them in other
contexts, too.
### Reflections
Hopefully you've learned something new about Ruby's method lookup rules, or at least been given some new things to think about and explore. If you've come from a background in which inheritance has been your only tool, you will likely have to retrain yourself a bit to make full use of what Ruby has to offer.
Whenever you compare one of these options to the other, consider your context
and how much the advantages and disadvantages of each technique affect your
particular situation. The correct approach always depends on that context, and
if in doubt, experiment and see what works best.
More discussion on this topic is welcome in the comments section below. While I wrote this article a while ago, I am happy to jump back into the topic as long as folks have interesting ideas and questions to share.
> **NOTE:** This article has also been published on the Ruby Best Practices blog. There [may be additional commentary](http://blog.rubybestpractices.com/posts/gregory/031-issue-2-method-lookup.html#disqus_thread)
over there worth taking a look at.
================================================
FILE: articles/v1/003-configurable.md
================================================
Ruby developers tend to prefer convention over configuration, but that doesn't mean our applications are configuration-free. If you're doing serious software development, it's likely that at least some of your projects depend on some sort of configuration data. Whether you simply need to store database credentials, an API key, or something much more complicated, it's important to know how to do so in a way that is flexible without introducing too much administrative overhead.
In this two part article series, we'll be talking about the many options Ruby provides us for working with configuration data, and what techniques work best in various common scenarios. We'll start by showing a single example of a problem and one way to solve it, and then go on to discuss various other options in Issue #4.
### Configuration Done Wrong
The worst way to work with configuration data is to embed it directly within your application. The simple Sinatra application shown below is a nice example of what *not* to do.
```ruby
require "rubygems"
require "sinatra"
require "active_record"
class User < ActiveRecord::Base; end
configure do
ActiveRecord::Base.establish_connection(
:adapter => "mysql",
:host => "myhost",
:username => "myuser",
:password => "mypass",
:database => "somedatabase"
)
end
get "/users" do
@users = User.all
haml :user_index
end
```
The code above establishes a connection to the database on application startup and then proceeds to implement a rather simple call to get a full user listing and then render a Haml template. With an application this simple, the configuration data seems a bit harmless. But with just a moment's thought, it is easy to see numerous flaws with this sort of design.
The first and most obvious issue with this sort of code is security, everyone who looks at its source needs to be trusted, as the credentials for the database connection are embedded directly within it. Now, this may or may not be a concern depending on who is involved with the project, and what other systems are in place to restrict access to production systems, but it is important to think about nonetheless.
In a field in which revision control is a key part of our practices, it's not as simple as removing this sensitive information when you decide you no longer want to share it with others. Rewriting the history of a repository is straightforward on its own, but mixing application and configuration code makes it tricky to do this without jumping through a bunch of hoops. This is where the security concerns overlap with maintenance issues.
Suppose you want to share this trivial sinatra application with a friend, or even use it on another machine. The in-application configuration forces everyone to set up an identical database environment, even if the needs of the application may not really call for that. Any change to this configuration information would lead to merge conflicts when you try to pull in changes across machines, which could become annoying quite fast.
Fortunately, Ruby makes writing proper configuration systems easy enough where the only valid reason for writing code this way is if you're doing a throwaway spike. Let's see how easily we can emulate the way Rails solves this problem in their own framework.
### YAML Based Configurations
With slight modifications, we can move our configuration out of our application and into a YAML file. We'd like to end up with a database.yml file looking quite similar to a standard Rails configuration file, such as the one below:
```
development:
adapter: mysql
database: mydatabase
username: myuser
password: mypass
host: myhost
```
Through the standard YAML library, we can easily access this data by parsing it into a nested hash, as shown in the irb session below.
```
>> require "yaml"
=> true
>> YAML.load_file("config/database.yml")
=> {"development"=>{"username"=>"myuser", "adapter"=>"mysql",
"database"=>"mydatabase", "host"=>"myhost", "password"=>"mypass"}}
```
If we compare this output to our original example of calling `establish_connection()` directly with an explicit configuration hash, the following code should be very easy to follow.
```ruby
require "rubygems"
require "yaml"
require "sinatra"
require "active_record"
class User < ActiveRecord::Base; end
configure do
database_config = YAML.load_file("config/database.yml")
ActiveRecord::Base.establish_connection(database_config)
end
get "/users" do
@users = User.all
haml :user_index
end
```
By removing the configuration data from the application code, we have made it so that the application code no longer needs to be modified everywhere it runs, provided the configuration data is properly set up. We can now safely tell our revision control system to ignore the configuration file without it causing many problems.
Now that we've seen a simple problem and a reasonable fix for it, let's ponder a few questions so that we can hit some more subtle topics in Issue #4
### Questions and Discussion Points
* YAML is a nice readable data format with good Ruby support, but it can only represent data, which does not allow you to make dynamic configuration systems with it. Rails runs its YAML files through ERB to address this issue, but what other ways could this problem be solved?
* How would you handle configuration for something like a command line application which may be run anywhere on your system? How might you build per-user and per-project configuration systems?
* Suppose you have a project that is mirrored to both Github and Heroku, and that you want to run directly from your public sources while providing some configuration options in your production environment. How should you handle this?
* What are some important practices to follow when implementing configuration systems, regardless of the underlying context and what approach you choose?
Please feel free to include your answers to these questions in the comments section below, along with any other thoughts or questions you might wish to share. I promise to reply personally to anyone who leaves a comment!
> **NOTE:** This article has also been published on the Ruby Best Practices blog. There [may be additional commentary](http://blog.rubybestpractices.com/posts/gregory/032-issue-3-configurable.html#disqus_thread)
over there worth taking a look at.
================================================
FILE: articles/v1/004-configurable.md
================================================
In [Issue #3](http://practicingruby.com/articles/31), we looked at the downsides
of mixing configuration code with application code. We discussed how storing
configuration data in YAML files can solve many of those issues, but not
all of them. In this article, we will explore the limitations of the YAML
format, and then consider the tradeoffs involved in using various
alternative solutions.
### Dynamic Configuration
In response to the questions posed by Issue #3, Franklin Webber demonstrated
how YAML's aliasing functionality can be used to reduce duplication in
a configuration file:
```
default: &DEFAULT
host:
name: testsystem
http_port: '8080'
username: defaultuser
database:
host: db01/db01
username:
password:
test:
browser: FIREFOX
windows_default: &WIN_DEFAULT
<<: *DEFAULT
test:
browser: IE
```
In this example, the `default` and `windows_default` configurations share almost
the same attributes, except that browsers differ in test mode. Franklin uses
aliasing to merge the `DEFAULT` data into the `WIN_DEFAULT` entry, solving his
duplication problem. This is a neat way to keep your YAML configurations well
organized.
While Franklin shared this example of aliasing to illustrate that some dynamic
functionality does exist within YAML, he acknowledged that the format was still
mostly suited for static data. Even though it is possible to reference
various entries within the data structure, they cannot be manipulated.
That means that the following concatenation example cannot be done in pure
YAML, and would require some additional processing:
```
host:
name: localhost
port: 3000
web:
login_url: #{name}:#{port}/login
```
This is where we cross the line from problems solved by a data format to those
solved by programming languages. Franklin suggests that running the YAML data
through Ruby's `eval` method is an option, which is similar to how Rails
passes its YAML files through `ERB`. This approach would work, but once we
start going down that road, we need to ask what it would take to implement
the entire configuration in pure Ruby. As you can see in the following example,
the answer is 'not much':
```ruby
module MyApp
module Config
HOST = { :name => 'localhost', :port => 3000 }
WEB = { :login_url => "#{HOST[:name]}:#{HOST[:port]}/login" }
end
end
```
If we drop this snippet into our application code, we run into the same problems
that we saw in the first example in Issue #3. But by defining this module
in its own file and requiring that file, those issues are avoided:
```ruby
require "config/my_app_config"
require "rest_client"
module MyApp
module Client
extend self
def authenticate(user, password)
RestClient.post(MyApp::Config::WEB[:login_url],
:user => user, :password => password)
end
end
end
MyApp::Client.authenticate('my_user', 'seekrit')
```
Using ordinary Ruby constants is no more complicated than referring to data
stored in a YAML file, but gives you the full power of Ruby in your
configuration scripts. In more complex configurations, you may even build
a mini-DSL, as shown in the following example:
```ruby
AccessControl.configure do
role "basic",
:permissions => [:read_answers, :answer_questions]
role "premium",
:parent => "basic",
:permissions => [:hide_advertisements]
role "manager",
:parent => "premium",
:permissions => [:create_quizzes, :edit_quizzes]
role "owner",
:parent => "manager",
:permissions => [:edit_users, :deactivate_users]
end
```
While this looks like vanilla configuration code on the surface, we can see that what we're working with are full blown Ruby objects. Here are some examples of how this system is used:
```ruby
>> AccessControl.roles_with_permission(:create_quizzes)
=> ["manager", "owner"]
>> AccessControl["premium"].permissions
=> [:hide_advertisements, :read_answers, :answer_questions]
>> AccessControl["owner"].allows?(:edit_users)
=> true
>> AccessControl["basic"].allows?(:edit_users)
=> false
```
This is an advanced configuration system that not only encapsulates some configuration data, but also makes it possible to query that data in useful ways. The following implementation code illustrates how little magic is involved in building such a system.
```ruby
module AccessControl
extend self
def configure(&block)
instance_eval(&block)
end
def definitions
@definitions ||= Hash.new
end
def role(level, options={})
definitions[level] = Role.new(level, options)
end
def roles_with_permission(permission)
definitions.select { |k,v| v.allows?(permission) }.map { |k,_| k }
end
def [](level)
definitions[level]
end
class Role
def initialize(name, options)
@name = name
@permissions = options[:permissions]
@parent = options[:parent]
end
attr_reader :parent
def permissions
return @permissions unless parent
@permissions + AccessControl[parent].permissions
end
def allows?(permission)
permissions.include?(permission)
end
def to_s
@name
end
end
end
```
Because doing configuration in pure Ruby is so easy, I often lean towards it rather than using YAML or some other external file format. I find configuration files written in Ruby to be just as readable as YAML, but far more flexible.
There are some situations in which external data formats make more sense than Ruby based configurations. Using YAML might be a better idea than the approach shown above if any of the following apply to your application:
* You need to integrate with other programs that will either read or write your configuration files. It is easier for a program written in another language to produce and consume YAML than it is for it to work with arbitrary Ruby code
* You don't want users to be able to execute arbitrary code in your application's runtime environment. This can either be for security reasons, or for protecting users from their own stupidity by restricting the range of possible mistakes they can make.
* You want configuration data that can easily be passed over a network and then executed remotely.
While these are all good reasons to avoid Ruby based configurations, frankly they are not common scenarios. The reason Ruby has had such a widespread adoption of YAML is almost certainly not because of it being the best tool for the job, but instead due to an early design decision made in Rails that people have emulated in their own projects without further thought. While either technique may get the job done, I'd argue that Ruby based configurations are a better default choice due to their inherent flexibility.
But sometimes, neither Ruby nor YAML does what we need them to do. In certain situations, configuration data isn't made available until the application is invoked. For those scenarios, we can take advantage of how well Ruby is integrated with the shell by making use of environment variables.
### Using the Shell Environment for Configuration
Every Ruby application has a fairly primitive but useful configuration system built into it through direct access to shell environment variables. As you can see in the code below, Ruby provides a top level constant that turns the environment variable mappings into a plain old Hash object.
```
$ TURBINE_API_KEY="saf3t33553" ruby -e "puts ENV['TURBINE_API_KEY']"
IqxPfasfasasfasfgqNm
```
The fact that I mention API keys in the above contrived example is no coincidence. The area I first made use of environment variables in my own applications was in a command line application which acted as a client to a web service I needed to interact with. Each distinct user needed to use a different API key, but I didn't want to rely on fragile home directory lookup code to provide per-user configuration. By using environment variables, it was possible to write a line like the following in my <i>.bash_profile</i> which would ensure that this information was available whenever my command line program ran.
```
export TURBINE_API_KEY="IqxPfasfasasfasfgqNm"
```
Since most modern shell implementations support environment variables, they're a good choice for this sort of semi-global configuration data. You'll also find environment variables used in places where you don't have much control over the system where your application is destined to run. The Ruby web application deployment service Heroku is a good example of that sort of environment.
On Heroku, you aren't given direct shell access and aren't even given any guarantees about where on the filesystem your application is destined to run. On top of that, if you want to run an open source application on Heroku while actively mirroring your changes to Github or some other public git host, you can't simply check in configuration files which may contain sensitive information, whether written in Ruby, YAML, or anything else.
The way Heroku solves these problems is with a configuration system based on, you guessed it, environment variables. The following example from the Heroku website shows how these set via the heroku command line app.
```
$ cd myapp
$ heroku config:add S3_KEY=8N029N81 S3_SECRET=9s83109d3+583493190
Adding config vars:
S3_KEY => 8N029N81
S3_SECRET => 9s83109d3+583493190
Restarting app...done.
```
In the application, these variables are accessed in a similar fashion to our
previous example:
```ruby
AWS::S3::Base.establish_connection!(
:access_key_id => ENV['S3_KEY'],
:secret_access_key => ENV['S3_SECRET']
)
```
While hardly the first tool you should reach for, environment variables make sense in situations in which you do not want to store sensitive information within your application. They also come in handy when you don't want to assume anything about your user's file system in order to locate user-wide configuration settings.
Before we wrap up with some general tips that are relevant to all configurable applications, I'd like to quickly visit one more trick that involves project-wide configurations.
### Per-project configurations for command line apps
Some command line applications need to be context aware in order to do their jobs. Two such examples are rake and git. Both tools know how to locate their own configuration information so that they do the right thing when running their commands.
For example, git knows which repository to interact with because it knows how to work backwards to find the <i>.git/</i> configuration folder at the project root. Likewise, running `rake test` from anywhere within your project causes rake to look backwards recursively until it finds the nearest <i>Rakefile</i> to run. This general pattern can be seen in many other applications, and is worth knowing about in case you ever need to make use of it yourself.
While I don't want to go into much detail about this topic, I will say that it seemed a bit magical to me until I needed to implement this sort of functionality in my own projects. The basic idea is no more complicated than working backwards from your current directory until you find the file or folder than you need to interact with, which is something Ruby's pathname library can make quick work of.
Here's an example pulled directly out of a project of mine which illustrates a reverse search from the current working directory back to the filesystem's root directory.
```ruby
require 'pathname'
def config_dir(dir = Pathname.new("."))
app_config_dir = dir + ".myappconfigfolder"
if dir.children.include?(app_config_dir)
app_config_dir.expand_path
else
return nil if dir.expand_path.root?
config_dir(dir.parent)
end
end
```
A bit of code like this combined with ordinary `require` calls for Ruby configurations or `YAML.load_file` calls for YAML configurations can be used to implement exactly the sort of context sensitive behavior you find in rake and git. I'll leave the exact methods of doing that as something for you to explore on your own, but hopefully this bit of code will come in handy if you ever run into that sort of situation.
This article turned out to be longer than I expected it to be, but hopefully was still quite useful to you. Before we part, let's review a few key points to keep in mind when building any sort of configuration system.
### Configuration Best Practices
* Convention often is better than configuration. Always provide sensible defaults where possible. For example, if you're interacting with a service that has a common default port, don't force the user to define a port to use unless they wish to deviate from the default.
* Don't put your real configuration files into your application's code repository, since this can expose sensitive data and also makes it hard for others to submit patches without merge conflicts on configuration settings.
* Include a sample configuration file filled with reasonable defaults with your application. For example, in Rails, people often check in a <i>config/database.yml.example</i> for this purpose. The goal should be to make it as easy for your user to make a copy of the sample file and then customize it as needed to get their systems up and running
* Raise an appropriate error message when a config file is missing. You can do this by doing a `File.exist?` check before loading your configuration file, or by rescuing the error a failed load causes and then re-raising a more specific error that instructs the user on where to set up their configuration file.
* Make it very easy for users to override defaults by merging their overrides rather than forcing them to replace whole configuration structures in order to make a small change.
### Reflections
What do you think of what we've covered here? Feel free to leave your questions, comments and suggestions in the comments section below.
> **NOTE:** This article has also been published on the Ruby Best Practices blog. There [may be additional commentary](http://blog.rubybestpractices.com/posts/gregory/033-issue-4-configurable.html#disqus_thread)
over there worth taking a look at.
================================================
FILE: articles/v1/005-testing-antipatterns.md
================================================
If you are using `send` to test private methods in your tests, you are almost certainly doing it wrong. Most private methods tend to fall into one of the following categories, none of which require `send` to test:
* A method that does not have behavior of its own (a helper function)
* A method that actually deserves to be public on the current object
* A method that is only private to hide a design flaw
Take a look at the three objects below and try to match them to the patterns listed above.
```ruby
class Book
def initialize(name)
@name = name
end
def available_for_purchase?
copies_remaining > 0
end
private
def copies_remaining
Inventory.count(:book, @name)
end
end
module Inventory
extend self
def count(item_type, name)
item_class(item_type).find_by_name(name).quantity
end
def receive(item_type, name, quantity)
item_class(item_type).create(name, quantity)
end
private
def item_class(item_type)
case item_type
when :book
InStockBook
when :video
InStockVideo
end
end
end
class InStockBook
def self.titles
@titles ||= {}
end
def self.find_by_name(name)
titles[name]
end
def self.create(name, quantity)
titles[name] = new(name, quantity)
end
def initialize(name, quantity)
@title = name
@quantity = quantity
end
attr_reader :title, :quantity
def isbn
@isbn ||= isbn_from_service
end
private
def isbn_from_service
isbn_service_connect
isbn = @isbn_service.find_isbn_for(@title)
isbn_service_disconnect
return isbn
end
def isbn_service_connect
@isbn_service = IsbnService.new
@isbn_service.connect
end
def isbn_service_disconnect
@isbn_service.disconnect
end
end
```
If you guessed that `Inventory` was the object which demonstrated a private method that doesn't implement an external behavior, you guessed right. The sole purpose of `Inventory#item_class` is just to make the code in `Inventory#count` and `Inventory#receive` a bit cleaner to read. Therefore, it'd be wasteful to write an explicit test such as the one below.
```ruby
def test_item_class
assert_equal InStockBook, Inventory.send(:item_class, :book)
end
```
The following tests implicitly cover the functionality of `Inventory#item_class` while focusing on actual interactions through the public interface.
```ruby
def test_stocking_a_book
Inventory.receive(:book, "Ruby Best Practices", 100)
assert_equal 100, Inventory.count(:book, "Ruby Best Practices")
end
```
Because indirectly testing a private method will result in the same code coverage results as testing the method directly, you won't silently miss out on a failure if `Inventory#item_class` does not work as expected. However, by writing your tests this way, you focus primarily on what can be done to the object via its external interface. This leads to clearer, more maintainable tests. If a user is expected to add books through `Inventory#receive`, they should not need to know about `InStockBook`, so it can be regarded as an implementation detail. Changing the definition of `Inventory#item_class` or even removing it entirely will not require a change to these tests as long as you maintain the signature of the objects public API.
Now that we've identified the approach for testing `Inventory`, we are left with `Book` and `InStockBook` to discuss. Of the two, the problem with `Book` is a little more obvious, so we'll tackle it first.
Book implements a method called `available_for_purchase?`, which relies on a private method called `copies_remaining` to operate. The following code demonstrates a poorly implemented test.
```ruby
def test_copies_remaining
book = Book.new("Ruby Best Practices")
Inventory.receive(book.name, 10)
assert_equal book.send(:copies_remaining), 10
end
```
The reason why this is poor is because once again, we are relying on `send` to call a private method in our tests. Our theory from the previous example is that private methods do not need to be tested because they don't actually implement behavior. However, `Book#copies_remaining` seems like something you might want to actually make use of. If you imagine a web front-end for an e-commerce site, it's easy to visualize both an indicator of whether an item is in stock, as well as how many of that item are still available.
The rule of thumb here is that if a method provides a sensible behavior that fits the context of your object, it's better off to just make it public. The following test seems very natural to me.
```ruby
def test_copies_remaining
book = Book.new("Ruby Best Practices")
Inventory.receive(book.name, 10)
assert_equal book.copies_remaining, 10
end
```
So far we've seen two extremes: Private methods that are rightfully private and do not need to be tested explicitly, and private methods that ought to be public so that they can be tested explicitly. We will now examine the space between these two opposite ends of the spectrum.
Let's think a bit about how we could test the `InStockBook#isbn` shown below.
```ruby
class InStockBook
# .. other features omitted
def isbn
@isbn ||= isbn_from_service
end
end
```
One way to do it the would be to mock out the call to `isbn_from_service` as we do in the following tests.
```ruby
def test_retreive_isbn
book = InStockBook.new("Ruby Best Practices", 10)
book.expects(:isbn_from_service).once.returns("978-0-596-52300-8")
# Verify caching by calling isbn twice but expecting only one service
# call to be made
2.times { assert_equal "978-0-596-52300-8", @book.isbn }
end
```
The downside of this approach is that by mocking out the call to `isbn_from_service`, we're bypassing all of the following code, leaving it untested.
```ruby
def isbn_from_service
isbn_service_connect
isbn = @isbn_service.find_isbn_for(@title)
isbn_service_disconnect
return isbn
end
def isbn_service_connect
@isbn_service = IsbnService.new
@isbn_service.connect
end
def isbn_service_disconnect
@isbn_service.disconnect
end
```
Making these methods public on `InStockBook` doesn't make much sense, but we also can't say that these are mere implementation details that can be ignored. In these situations, typically some redesign is necessary, and in this case, a simple shift of this functionality upstream to the `IsbnService` class makes the most sense.
```ruby
class IsbnService
def self.find_isbn_for(title)
service = new
service.connect
isbn = service.find_isbn_for(title) # delegate to instance
service.disconnect
return isbn
end
# .. other functionality
end
```
This functionality can now easily be tested as a public behavior of the `IsbnService` class, where it won't get jumbled up with `InStockBook`'s logic. All that's left to do is rewrite our `InStockBook#isbn` method so that it delegates to this new class.
```ruby
class InStockBook
# .. other features omitted
def isbn
@isbn ||= IsbnService.find_isbn_for(@title)
end
end
```
Our updated `isbn` tests only need to change slightly to accommodate this
change:
```ruby
def test_retreive_isbn
book = InStockBook.new("Ruby Best Practices", 10)
IsbnService.expects(:find_isbn_for).with(book.title).once.
returns("978-0-596-52300-8")
# Verify caching by calling isbn twice but expecting only one service
# call to be made
2.times { assert_equal "978-0-596-52300-8", @book.isbn }
end
```
Now, when reading the tests for `InStockBook`, the developer can safely gloss
over `IsbnService`'s implementation until its contract changes. With this
dilemma solved, we've now comprehensively categorized the strategies that allow
you to avoid testing private methods without sacrificing the clarity and
coverage of your test suite.
### Reflections
We've now seen examples of how to deal with all of the following situations that might tempt us to use `send` in our tests unnecessarily:
1. A method that does not have behavior of its own (a helper function)
1. A method that actually deserves to be public on the current object
1. A method that is only private to hide a design flaw
Can you think of a situation where none of these approaches seem to work? Please feel free to share them in the comments section below.
> **NOTE:** This article has also been published on the Ruby Best Practices blog. There [may be additional commentary](http://blog.rubybestpractices.com/posts/gregory/034-issue-5-testing-antipatterns.html#disqus_thread)
over there worth taking a look at.
================================================
FILE: articles/v1/006-good-and-bad-code.md
================================================
In this issue and the next one, I'd like to demonstrate one of my favorite learning exercises while inviting you to follow along at home. It's something I usually do while teaching in a one-on-one setting, but I think we can adapt it for a broader audience and still get a lot out of it.
In this exercise, the goal is to first produce some bad code, and then steadily improve it while explaining why each change is an improvement. I usually start with a very simple problem but then add some twists about how to implement it to make sure it comes out pretty bad.
One surefire way of writing bad code without resorting to intentionally writing things worse than they should be is to eliminate a few of Ruby's key organizational tools. In particular, if you want to write ugly code without it seeming fake, it is easy to do so if you never write any user defined functions, classes, or modules. So we'll do exactly that!
### Implementing Tic-Tac-Toe as a single procedure.
I've chosen the game [Tic-Tac-Toe](http://en.wikipedia.org/wiki/Tic-Tac-Toe) as the problem to focus on, because it only involves a few simple rules and can be implemented by anyone who has basic programming skills.
In fact, if you ignore end game conditions and error handling, you can get a simple prompt for a two player game with just a few lines of Ruby.
```ruby
board = [[nil,nil,nil],
[nil,nil,nil],
[nil,nil,nil]]
players = [:X, :O].cycle
loop do
current_player = players.next
puts board.map { |row| row.map { |e| e || " " }.join("|") }.join("\n")
print "\n>> "
row, col = gets.split.map { |e| e.to_i }
puts
board[row][col] = current_player
end
```
But of course, the devil is in the details. To get a fully playable game, you need some basic error checking to ensure that you can't play out of bounds or on top of another player's marker. You also need to figure out when a player has won, and when the game has ended in a draw. While this doesn't sound like a lot of work, you'll see in the code below how much complexity these simple changes add.
```ruby
board = [[nil,nil,nil],
[nil,nil,nil],
[nil,nil,nil]]
left_diagonal = [[0,0],[1,1],[2,2]]
right_diagonal = [[2,0],[1,1],[0,2]]
players = [:X, :O].cycle
current_player = players.next
loop do
puts board.map { |row| row.map { |e| e || " " }.join("|") }.join("\n")
print "\n>> "
row, col = gets.split.map { |e| e.to_i }
puts
begin
cell_contents = board.fetch(row).fetch(col)
rescue IndexError
puts "Out of bounds, try another position"
next
end
if cell_contents
puts "Cell occupied, try another position"
next
end
board[row][col] = current_player
lines = []
[left_diagonal, right_diagonal].each do |line|
lines << line if line.include?([row,col])
end
lines << (0..2).map { |c1| [row, c1] }
lines << (0..2).map { |r1| [r1, col] }
win = lines.any? do |line|
line.all? { |row,col| board[row][col] == current_player }
end
if win
puts "#{current_player} wins!"
exit
end
if board.flatten.compact.length == 9
puts "It's a draw!"
exit
end
current_player = players.next
end
```
While relatively short, you need to read through the whole script to really understand how any part of it operates. Of course, this script did not spring together fully formed, there was a thought process that drove it to this final implementation. For those curious, you can [follow my stream of consciousness notes](https://gist.github.com/24ef3c8209877c1946bb) about what I was building and why in a step by step fashion.
Seeing these notes will hopefully give you a bit of a sense of how this process might have gone if we were pair programming on this project, working in tiny iterations to push forward just a little bit farther each time. If so, you might already be catching a glimpse of what this exercise is all about. Otherwise, there is still more for us to do!
### What Happens Next?
I've placed my bad tictactoe example in a [repository on github](https://github.com/sandal/tictactoe/tree/7fd72a33aec33f75909d8c9d59a43423b0f66b24). If you'd like to participate, please fork this repository and make one change to the code at a time, leaving detailed reasoning in each commit message as to why you're making the change. Once you're happy with what you've got, post a link in the comments section on this post so others can check out what you have done.
In the next issue, I will post my own iterative set of improvements, as well as links to some reader submissions. I will also summarize the lessons that can be learned from using this technique, and provide a few suggestions for other problems to attempt in this fashion.
### Reflections
Please leave any questions, thoughts, or suggestions in the comments section below. These articles are much better when they're treated as discussions rather than monologues.
> **NOTE:** This article has also been published on the Ruby Best Practices blog. There [may be additional commentary](http://blog.rubybestpractices.com/posts/gregory/035-issue-6-good-and-bad-code.html#disqus_thread)
over there worth taking a look at.
================================================
FILE: articles/v1/007-good-and-bad-code.md
================================================
In Issue #6, you got to see my intentionally bad implementation of Tic Tac Toe. For today, I have promised to show you some better code and the steps I took to get there. But before we move forward, let's take a quick look back at where we started.
To start this exercise, I had challenged myself to implement this simple game without using any user defined classes or methods. Given that I wanted to make sure I produced *bad* code to start with, I got a little nervous when my back-of-the-napkin proof of concept didn't come out looking that bad. Here it is again below, for those who forgot about it.
```ruby
board = [[nil,nil,nil],
[nil,nil,nil],
[nil,nil,nil]]
players = [:X, :O].cycle
loop do
current_player = players.next
puts board.map { |row| row.map { |e| e || " " }.join("|") }.join("\n")
print "\n>> "
row, col = gets.split.map { |e| e.to_i }
puts
board[row][col] = current_player
end
```
The above code is good demo-ware, as long as you type really carefully and conveniently forget to finish a game before hitting ctrl+c. But to make a real, playable implementation, some end game conditions and basic validations are necessary. To my great joy, adding those new features caused this tight little script to explode into a hot mess of intertwined logic and nasty little hacks. Check out [the source tree](https://github.com/sandal/tictactoe/tree/7fd72a33aec33f75909d8c9d59a43423b0f66b24) that we ended up with at the end of Issue #6 to see how things turned.
While concise at less than 60 lines of code, it's pretty easy to see that this isn't the kind of software we should aspire to be writing. So the challenge was to start here and end up somewhere better.
Whenever I do this exercise with my students, there is a roadmap I follow that tends to lead to some decent insights. It roughly goes like this:
* Get some basic file structures and namespaces in place so that you get yourself out of the global namespace and open the doors for scripting some examples or running things in irb without firing off a procedure automatically.
* Break down the procedure into some separable chunks so that you can think about smaller parts of the problems, and more easily see the dependencies between the steps in the procedure.
* Re-think the design by identifying areas where objects can put an abstraction barrier between different layers of data and logic. Strive to have each bit of code do one thing and one thing well.
* Identify the leaky abstractions and dangly bits that didn't get ironed out by the last step. Aim for beautiful solutions, but be skeptical of over-engineering at this point. No problem can be modeled perfectly
* Reflect on the exercise, and ask yourself whether you've gone far enough with your cleanup. If you feel like so, then be sure to think about whether you've gone *too* far!
This is the approach I took as I worked on this problem myself, and you'll be able to see it step by step in the git logs. I tried to write good log messages, so I will link to them rather than repeat what was said, but I'll also share some more big-picture oriented thoughts as I walk you through my work.
### Basic organization first
Here is my [first commit](https://github.com/sandal/tictactoe/commit/5af96941d74f8014a3276b77fe67c17e0ed5e2df) of the evening. And this is the [source tree](https://github.com/sandal/tictactoe/tree/5af96941d74f8014a3276b77fe67c17e0ed5e2df).
Tiny changes really, but it's the first thing I do as soon as I've exited 'spike
mode' on any project, no matter how small. I've used a standard structure, and
it does two things for me:
1. Allows me to load my whole library with a single require. (See app.rb for example and note how it doesn't change throughout this walkthrough)
1. Places 100% of what I build under a single constant's namespace (i.e. `TicTacToe`)
These two points pretty much guarantee me that I won't have any naming clashes or unexpected collisions with other people's code unless I plan on loading a library that might clobber the name `TicTacToe` or the `require` path of <i>"tictactoe/*"</i>. It also makes it easy for me to start interacting with my code from scripts I write, from irb, and from unit tests. For so little work, we get a ton of benefit, and this is a great place to start when doing any sort of cleanup.
### Basic Slicing and Dicing
My next goal is to start breaking my monolithic procedure into some smaller chunks so I can get a sense of what parts go well together and how they need to interact with each other.
I start by realizing that using a singleton pattern for `Game`, while possible, isn't a great idea. A function bag approach in which we pass board and player information around like crazy also wouldn't be great, so I decide to make `Game` an ordinary class in this [commit](https://github.com/sandal/tictactoe/commit/2579626bd73fc7ad9e7d0a87419d5ecab2aacdda).
Read the message, and then if you'd like, have a look at the [updated source tree](https://github.com/sandal/tictactoe/tree/2579626bd73fc7ad9e7d0a87419d5ecab2aacdda).
I immediately make use this refactoring by breaking down the original game procedure into several smaller, simpler methods. ([commit](https://github.com/sandal/tictactoe/commit/286724de5328fda779caa500ccc76a0ad5de2bd7), [source](https://github.com/sandal/tictactoe/tree/286724de5328fda779caa500ccc76a0ad5de2bd7))
At this point, it's not uncommon for folks to think they're done refactoring. By giving things nicer names and distributing the pain points so that they're not all crammed together in one place, the code feels cleaner. But upon further investigation of this code, while perhaps understandability and organization have improved, flexibility and abstraction have not. This is what I like to call 'procedural programming with objects', and we can do better than this.
The good news is, with the code cleaned up a bit, we see where some of the pain points are. When it seems like a large amount of your code is dedicated to handling a particular concept, that means you have an object begging to be born. Our handling of the game board logic in this code is a prime example.
### Sneaking in Domain Models
A key principle of object oriented design is to do one thing and do it well. But what does that mean? Hopefully, this refactored `Board` class gives you an idea!
([commit](https://github.com/sandal/tictactoe/commit/efcbf51bcc1f7d4d094c671b60761229aec3dded), [source](https://github.com/sandal/tictactoe/tree/efcbf51bcc1f7d4d094c671b60761229aec3dded))
If you look at the `Board` class, you'll see that it takes the concept of a Tic Tac Toe board and solidifies it so that when `Game` works with it, `Board` does the heavy lifting and `Game` mostly just calls the methods it needs to get its job done. This lets `Game` forget about some of the finer points like what the individual kinds of illegal moves are, or how to compute the intersecting lines that cross through a given point. This sort of black box effect gives us some real abstraction, which is exactly why object oriented programming is as good as they say it is.
With this complex board logic out of the way and some updates to the way flow is handled in game, it's obvious that `Game` is now something like a controller, and `Board` is a model. But there are still some loose ends in `Game`, things that actually look like logic rather than just flow control and dispatch. The majority of the code you see in this class has to do with implementing a user interface and basic event loop. So, methods like `check_move`, `check_win`, and `check_draw` feel a little bit out of place, since they implement actual logic about the rules of the game rather than just how players interact with it.
Sometimes, little leaks like this aren't a big deal. In fact, the code looks reasonable to me at this point and if I were doing this for my day job and wasn't trying to get in the record books for 'World's Best Tic Tac Toe Implementation', I'd probably stop here.
But we're already cruising now, so why don't we try to shoot for the stars?
### Grail Quests
I really wanted to find a way to rip that last bit of domain logic out of `Game`, and after wrestling a little bit, I came up with something.
([commit](https://github.com/sandal/tictactoe/commit/0fef18d320af2bd1a08f5115a2b94e552205f218), [source](https://github.com/sandal/tictactoe/tree/0fef18d320af2bd1a08f5115a2b94e552205f218))
The thing I kept wrestling with was how to manage the screen output stuff. I wrestled with a bunch of ideas, including defining a simply `display()` method on `Game` like this:
```ruby
def display(message)
puts message
end
```
The reason why I wanted this is so my Rules mixin could rely on a method that `Game` provided for display rather than directly assuming console output. But I think that what I ended up with is better.
Imagine that my `check_draw` method in Rules was written like this:
```ruby
def check_draw
if @board.covered?
display "It's a draw"
game_over
end
end
```
It's almost a trivial difference *except* that now we have a leak on the Rules side. If `TicTacToe::Game` is now meant to exclusively be a UI event loop, having the messages that are displayed to the user caught up in some module seems a bit ugly.
But instead, I chose to let `Game` fill in the blanks with an implementation like this:
```ruby
def check_draw
if @board.covered?
yield
game_over
end
end
```
This allows the draw logic to live in `Rules`, with calling code in `Game`
that looks like this:
```ruby
check_draw { puts "It's a draw" }
```
A place for everything and everything in its place! Time to go hang some banners on aircraft carriers, because well, Mission Accomplished.
### Fear, Uncertainty, and Doubt
Is this final implementation an example of good Ruby code? Yeah, probably. Is it excellent? I really have no idea. At the very least, it's almost certainly not 'The Best Tic Tac Toe Implementation Ever'.
But really, the kind of perfection I was trying to seek in this exercise is not really what we should be looking for in our day to day work. Right now I have the amps cranked up to 11, when 7 or 8 would really do fine. But as I said before, this is one of my favorite exercises for learning and teaching. Here's why: It really gets me thinking.
I'm still trying to decide on whether extracting out the `Rules` module was really necessary, and I also have some areas about this I still don't like. For example, I'm not sure whether `Board` should know more about the rules of the game, or even less. I don't like the hard coding I did of all the parameters of the game in there, but I can't put my finger on why. After all, it's very unlikely that Tic Tac Toe is suddenly going to become Chess and need to expand to an NxN board. Even if it did, wouldn't it need to change a whole lot to accommodate it?
Still, I don't like things like these constants:
```ruby
LEFT_DIAGONAL_POSITIONS = [[0,0],[1,1],[2,2]]
RIGHT_DIAGONAL_POSITIONS = [[2,0],[1,1],[0,2]]
SPAN = (0..2)
CELL_COUNT = 9
```
There is a natural connascence between all four of these values, but the code to generalize their creation would be longer and much uglier to read than the above. So maybe it's a good choice to do it this way, but it makes the mathematician in me uneasy.
Another thing I don't like about my design is `Board#to_s`, because putting presentation logic on domain logic is nasty. But to make a view object or otherwise promote one line of code to something more complex seems to be a cure that is worse than the disease.
But on the bright side of things, I really like the callback scheme for doing the bits of game logic like `check_win` and `check_draw` and passing in a block with the rendering code. This is actually a formal design pattern just hiding in a line of code, and things like that remind me of why Ruby is so beautiful.
Also, I've never used `throw` / `catch` before in real code. Never really saw why I'd need it. But at a glance, my use of it here actually seems pretty expressive and appropriate given the situation. But because I've never used it before, I'm still glancing at it sideways with considerable doubt. I even had to wrap it in a method called `game_over` to hide the throw keyword to get over my fear of its relative novelty. But now, my `game_over` method is like some sort of crazy goto call... and that makes me not so sure that this was a good idea afterall.
Oh yeah, and I also didn't write any tests while working on this code. I thought about writing them, but I felt that it'd cause me to think about the tests themselves more than the coding practices I was experimenting with. But then again, maybe if I wrote tests, I wouldn't be pondering the relative merits of my fancy `game_over()` goto.
And this is how this exercise always ends. It doesn't come together in a beautiful blossom of Ruby awesomeness, it just kind of falls off a cliff. But really, that's okay! Not every question needs to be answered, and as I said before, if this were something I was working on just to get a job done, I would happily make concessions where needed to avoid letting perfect become the enemy of the good.
Still, this sort of practice gnaws on your subconscious, and I've seen it lead to great progress in my own studies and in my students as well. Hopefully you've enjoyed seeing this process in action, and will give it a try soon if you weren't able to try it out this week.
### Submissions from our readers
I haven't had a chance to review them in depth, but a few readers did share
their own explorations with us. Check out the [github network graph](https://github.com/sandal/tictactoe/network) to see what others have done.
Looking forward to hearing your thoughts on this exercise, and whether it seems like something you could make good use of. Until next time, happy hacking!
> **NOTE:** This article has also been published on the Ruby Best Practices blog. There [may be additional commentary](http://blog.rubybestpractices.com/posts/gregory/036-issue-7-good-and-bad-code.html#disqus_thread)
over there worth taking a look at.
================================================
FILE: articles/v1/008-uses-for-modules.md
================================================
> Note: This article series on modules is also available as a [PDF download]. The
> PDF version has been revised and is more up-to-date than what you see here.
[PDF download]:https://github.com/elm-city-craftworks/pr-monthly/blob/gh-pages/b5e5a89847701c4aa7c170cf/sept-2012-modules.pdf?raw=true
Modules are part of what makes Ruby's design beautiful. However, since they do not have a direct analogy in any mainstream programming language, it is easy to get a bit confused about what they should be used for. While most folks quickly encounter at least some of their use cases, typically only very experienced Ruby developers know their true versatilty.
In this four part article series, I aim to demystify Ruby modules by showing many practical use cases, explaining some tricky details along the way. We'll work through some of the fundamentals in the first two issues, and move into more advanced examples in the second two. Today we'll kick off this series by looking at the most simple, but perhaps most important ability modules offer us, the creation of namespaces.
### Modules for Namespacing
Imagine that you are writing an XML generation library, and in it, you have a class to generate your XML documents. Perhaps uncreatively, you choose the name `Document` for your class, creating something similar to what is shown below.
```ruby
class Document
def generate
# ...
end
end
```
On its own, this seems to make a lot of sense; a user could do something simple like the following to make use of your library.
```ruby
require "your_xml_lib"
document = Document.new
# do something with document
puts document.generate
```
But imagine that you were using another library that generates PDF documents, which happens to use similar uncreative naming for its class that does the PDF document generation. Then, the following code would look equally valid.
```ruby
require "their_pdf_lib"
document = Document.new
# do something with document
puts document.generate
```
As long as the two libraries were never loaded at the same time, there would be no issue. But as soon as someone loaded both libraries, some quite confusing behavior would happen. One might think that defining two different classes with the same name would lead to some sort of error being raised by Ruby, but with open classes, that is not the case. Ruby would actually apply the definitions of `Document` one after the other, with whatever file was required last taking precedence. The end result would in all likelihood be a very broken `Document` class that could generate neither XML nor PDF.
But there is no reason for this to happen, as long as both libraries take care to namespace things. Shown below is an example of two `Document` classes that could co-exist peacefully.
```ruby
# somewhere in your_xml_lib
module XML
class Document
# ...
end
end
# somewhere in their_pdf_lib
module PDF
class Document
# ...
end
end
```
Using both classes in the same application is as easy, as long as you explicitly include the namespace when referring to each library's `Document` class.
```ruby
require "your_xml_lib"
require "their_pdf_lib"
# this pair of calls refer to two completely different classes
pdf_document = PDF::Document.new
xml_document = XML::Document.new
```
The clash has been prevented because each library has nested its `Document` class within a module, allowing the class to be defined within that namespace rather than at the global level. While this is a relatively straightforward concept, it's important to note a few things about what is really going on here.
Firstly, namespacing actually applies to the way constants are looked up in Ruby in general, not classes in particular. This means that it applies to modules nested within modules as well as ordinary constants as well.
```ruby
module A
module B
end
end
p A::B
module A
C = 10
end
p A::C
```
Secondly, this same behavior of using modules as namespaces applies just as well to classes, as in the code below.
```ruby
class Blog
class Comment
#...
end
end
```
Be sure to note that in this example, nesting a class within a class does not in any way make it a subclass or establish any relationship between `Blog` and `Blog::Comment` except that `Blog::Comment` is within the `Blog` namespace. In the example below, you can see that a class nested within another class looks the same as a class nested within a module.
```ruby
blog = Blog.new
comment = Blog::Comment.new
# ...
```
Of course, this technique is only really useful when you have a desired namespace for your library that also happens matches one of your class names. In all other situations, it makes sense to use a module for namespacing as it would prevent your users from creating instances of an empty and meaningless class.
Finally, it is important to understand that constants are looked up from the innermost nesting to the outermost, finally searching the global namespace. This can be a bit confusing at times, especially when you consider some corner cases.
For example, examine the following code:
```ruby
module FancyReporter
class Document
def initialize
@output = String.new
end
attr_reader :output
end
end
```
If you load this code into irb and play with a bit on its own, you can inspect an instance of Document to see that its output attribute is a core ruby `String` object, as shown below:
```ruby
>> FancyReporter::Document.new.output
=> ""
>> FancyReporter::Document.new.output.class
=> String
```
While this seems fairly obvious, it is easy for a bit of unrelated code written elsewhere to change everything. Consider the following code:
```ruby
module FancyReporter
module String
class Formatter
end
end
end
```
While the designer of `FancyReporter` was most likely trying to be well organized by offering `FancyReporter::String::Formatter`, this small change causes headaches because it changes the meaning of `String.new` in `Document`'s initialize method. In fact, you cannot even create an instance of `Document` before the following error is raised:
```ruby
?> FancyReporter::Document.new
NoMethodError: undefined method `new' for FancyReporter::String:Module
from (irb):35:in `initialize'
from (irb):53:in `new'
from (irb):53
```
There are a number of ways this problem can be avoided. Often times, it's
possible to come up with alternative names that do not clash with core objects,
and when that's the case, it's preferable. In this particular case, `String.new`
can also be replaced with `""`, as nothing can change what objects are created
via Ruby's string literal syntax. But there is also an approach that works
independent of context, and that is to use explicit constant lookups from the
global namespace. You can see an example of explicit lookups in the following
code:
```ruby
module FancyReporter
class Document
def initialize
@output = ::String.new
end
attr_reader :output
end
end
```
Prepending any constant with `::` will force Ruby to skip the nested namespaces and bubble all the way up to the root. In this sense, the difference between `A::B` and `::A::B` is that the former is a sort of relative lookup whereas the latter is absolute from the root namespace.
In general, having to use absolute lookups may be a sign that there is an unnecessary name conflict within your application. But if upon investigation you find names that inheritently collide with one another, you can use this tool to avoid any ambiguity in your code.
While we've mostly covered the mechanics of namespacing, all this talk about `::` compels me to share a cautionary tale of mass cargoculting before we wrap up for today. Please bear with me as I stroke my beard for a moment.
### Abusing the Constant Lookup Operator (`::`)
In some older documentation, and some relatively recent code written by folks who learned from old documentation, you may see class methods being called in the manner shown below.
```ruby
YAML::load(File::read("foo.yaml"))
```
While the above code runs fine, it's only a historical accident that it does. In fact, `::` was never meant for method invocation, class methods or otherwise. You can easily demonstrate that `::` can be used to execute instance methods as well, which eliminates any notion that `::` has some special 'class methods only' distinction to it.
```ruby
"foo"::reverse #=> "oof"
```
As far as I can tell, this style of method invocation actually came about as a documentation convention. In both formal documentation and in mailing list discussions, it can sometimes be difficult to discern whether someone is talking about a class method or instance method, since both can be called just as well with the dot operator. So, a convention was invented so that for a class `Foo`, the instance method `bar` would be referred to as `Foo#bar`, and the class method `bar` would be referred to as `Foo::bar`. This did away with the dot entirely, leaving no room for ambiguity.
Unfortunately, this lead to a confusing situation. Beginners would often type `Foo#bar` to try to call instance methods, but were at least promptly punished for doing so because such code will not run at all. However, typing `Foo::bar` does work! Thus, an entire generation of Ruby developers were born thinking that `::` is some sort of special operator for calling class methods, and to an extent, others followed suit as a new convention emerged.
The fact that `::` will happily call methods for you has to do with internal implementation details of MRI, and so it's actually an undefined behavior, subject to change. As far as I know, there is no guarantee it will actually work as expected, and so it shouldn't be relied upon.
In your code, you should feel free to replace any method calls that use this style with ordinary `Foo.bar` calls. This actually reflects more of the true nature of Ruby, in that it doesn't emphasize the difference between class level calls and instance level calls, since that distinction isn't especially important. In documentation, things are a little trickier, but it is now generally accepted that `Foo.bar` refers to a class method and `Foo#bar` refers to an instance method. In cases where that distinction alone might be confusing, you could always be explicit, as in the example below.
```ruby
obj.bar # obj is an instance of Foo
```
If this argument wasn't convincing enough, you should know that every time you replace a `Foo::bar` call with `Foo.bar`, a brand new baby unicorn is born beneath a magnificent double rainbow. That should be reason enough to reverse this outdated practice, right?
### Reflections
This article probably gave you more details than you ever cared to know about namespacing. But future articles will be sure to blow your mind with what else modules can do. However, if you have any questions or thoughts about what we've discussed so far, feel free to leave them in the comments section below.
> **NOTE:** This article has also been published on the Ruby Best Practices blog. There [may be additional commentary](http://blog.rubybestpractices.com/posts/gregory/037-issue-8-uses-for-modules.html#disqus_thread)
over there worth taking a look at.
================================================
FILE: articles/v1/009-uses-for-modules.md
================================================
> Note: This article series on modules is also available as a [PDF download]. The
> PDF version has been revised and is more up-to-date than what you see here.
[PDF download]:https://github.com/elm-city-craftworks/pr-monthly/blob/gh-pages/b5e5a89847701c4aa7c170cf/sept-2012-modules.pdf?raw=true
### Using Mix-ins to Augment Class Definitions
Although knowing [how to use modules for namespacing](http://practicingruby.com/articles/36) is important, it's really only a small part of what you can do with modules. What modules do best is providing a convenient way to write code that can be mixed into other objects, augmenting their behaviors. Because modules facilitate code sharing in a way that is distinct from both the general OO concept of class inheritance and from things like Java's interfaces, they require you to think about your design in a way that's a bit different from most other object oriented programming languages.
While I imagine that most of our readers are comfortable with using mixins, I'll
refer to some core Ruby mixins to illustrate their power before moving on to more
subtle points. For example, consider the following bit of code which implements lazily evaluated computations:
```ruby
class Computation
def initialize(&block)
@action = block
end
def result
@result ||= @action.call
end
def <(other)
result < other.result
end
def >(other)
result > other.result
end
def >=(other)
result >= other.result
end
def <=(other)
result <= other.result
end
def ==(other)
result == other.result
end
end
a = Computation.new { 1 + 1 }
b = Computation.new { 4*5 }
c = Computation.new { -3 }
p a < b #=> true
p a <= b #=> true
p b > c #=> true
p b >= c #=> true
p a == b #=> false
```
While Ruby makes defining custom operators easy, there is a lot more code here than there needs to be. We can easily clean it up by mixing in Ruby's built in `Comparable` module.
```ruby
class Computation
include Comparable
def initialize(&block)
@action = block
end
def result
@result ||= @action.call
end
def <=>(other)
return 0 if result == other.result
return 1 if result > other.result
return -1 if result < other.result
end
end
a = Computation.new { 1 + 1 }
b = Computation.new { 4*5 }
c = Computation.new { -3 }
p a < b #=> true
p a <= b #=> true
p b > c #=> true
p b >= c #=> true
p a == b #=> false
```
We see that our individual operator definitions have disappeared, and in its place are two new bits of code. The first new thing is just an include statement that tells Ruby to mix the `Comparable` functionality into the `Computation` class definition. But in order to make use of the mixin, we need to tell `Comparable` how to evaluate the sort order of our `Computation` objects, and that's where `<=>` comes in.
The `<=>` method, sometimes called the spaceship operator, essentially fills in a template method that allows `Comparable` to work. It codifies the notion of comparison in an abstract manner by expecting the method to return `-1` when the current object is considered less than the object it is being compared to, `0` when the two are considered equal, and `1` when the current object is considered greater than the object it is being compared to.
If you're still scratching your head a bit, pretend that rather than being a core Ruby object, that we've implemented `Comparable` ourselves by writing the following code.
```ruby
module Comparable
def ==(other)
(self <=> other) == 0
end
def <(other)
(self <=> other) == -1
end
def <=(other)
self < other || self == other
end
def >(other)
(self <=> other) == 1
end
def >=(other)
self > other || self == other
end
end
```
Now, if you imagine these method definitions literally getting pasted into your `Computation` class when `Comparable` is included, you'll see that it would provide a behavior that is functionally equivalent to our initial example.
Of course, it wouldn't make sense for Ruby to implement such a feature for us
without using it in its own structures. Because Ruby's numeric classes
all implement `<=>`, we are able to simply delegate our `<=>` call to the
result of the computations.
```ruby
class Computation
include Comparable
def initialize(&block)
@action = block
end
def result
@result ||= @action.call
end
def <=>(other)
result <=> other.result
end
end
```
The only requirement for this code to work as expected is that each `Computation`'s result must implement the `<=>` method. Since all objects that mix in `Comparable` have to implement `<=>`, any comparable object returned as a result should work fine here.
While not a technically complicated example, there is surprising power in having a primitive built into your programming language which trivializes the implementation of the Template Method design pattern. If you look at Ruby's `Enumerable` module and the powerful features it offers, you might think it would be a much more complicated example to study. But it too hinges on Template Method and requires only an `each()` method to give you all sorts of complex functionality including things like `select()`, `map()`, and `inject()`. If you haven't tried it before, you should certainly try to roll your own `Enumerable` module to get a sense of just how useful mixins can be.
We can also invert this relationship by having our class define a template, and then relying on the module that we mix in to provide the necessary details. If we look back at a previous example `TicTacToe`, we can see a practical example of this technique by looking at the play method in our `TicTacToe::Game` class.
```ruby
module TicTacToe
class Game
def play
catch(:finished) do
loop do
start_new_turn
show_board
check_move { |error_message| puts error_message }
check_win { puts "#{current_player} wins" }
check_draw { puts "It's a tie" }
end
end
end
# ...
end
end
```
In this code, we wanted to keep our event loop abstract, and rely on a mixed in module to provide the logic for executing and validating a move as well as checking end game conditions. As a result, we ended up with the `TicTacToe::Rules` module shown below.
```ruby
module TicTacToe
module Rules
def check_move
row, col = move_input
board[row, col] = current_player
rescue TicTacToe::Board::InvalidRequest => error
yield error.message if block_given?
retry
end
def check_win
return false unless board.last_move
win = board.intersecting_lines(*board.last_move).any? do |line|
line.all? { |cell| cell == current_player }
end
if win
yield
game_over
end
end
def check_draw
if @board.covered?
yield
game_over
end
end
end
end
```
When we look at this code, we see some basic business logic implementing the rules of Tic Tac Toe, with some placeholder hooks being provided by `yield()` that allows the calling code to inject some logic at certain key points in the process. This is how we manage to split the UI code from the game logic, without creating frivolous adapter classes.
While this is a more complicated example than our walkthrough of `Comparable`, the two share a common thread. In both cases, some coupling exists between the module and the object it is being mixed into. This is a common pattern when using mixins, in which the module and the code it is mixed into have to do a bit of a secret handshake to be able to talk to one another, but as long as they agree on that, neither needs to know about the other's inner workings. The end result is two components which must agree on an interface but do not need to necessarily understand each other's implementations. Code with this sort of coupling is easy to test and easy to refactor.
### Using Mix-ins to Augment Objects Directly
As you may already know, Ruby's mixin capability is not limited to simply including new behavior into a class definition. You can also extend the behavior of a class itself, through the use of the `extend()` method. We can look to the Ruby standard library <i>forwardable</i> for a nice example of how this is used. Consider the following trivial `Stack` implementation.
```ruby
require "forwardable"
class Stack
extend Forwardable
def_delegators :@data, :push, :pop, :size, :first, :empty?
def initialize
@data = []
end
end
```
In this example, we can see that after we extend our `Stack` class with the `Forwardable` module, we are provided with a class level method called `def_delegators` which allows us to easily define methods which delegate to an object stored in the specified instance variable. Playing around with the `Stack` object a bit should illustrate what this code has done for us.
```ruby
>> stack = Stack.new
=> #<Stack:0x4f09c @data=[]>
>> stack.push 1
=> [1]
>> stack.push 2
=> [1, 2]
>> stack.push 3
=> [1, 2, 3]
>> stack.size
=> 3
>> until stack.empty?
>> p stack.pop
>> end
3
2
1
```
As before, it may be helpful to think about how we might implement `Forwardable` ourselves. The following bit of code shows one way to approach the problem.
```ruby
module MyForwardable
def def_delegators(ivar, *delegated_methods)
delegated_methods.each do |m|
define_method(m) do |*a, &b|
obj = instance_variable_get(ivar)
obj.send(m,*a, &b)
end
end
end
end
```
While the metaprogramming aspects of this may be a bit noisy to read if you're not familiar with them, this is fairly vanilla dynamic Ruby code. If you've got Ruby 1.9.2 installed, you can actually try it out on your own and verify that it does indeed work as expected. But the practical use case of this code isn't what's important here.
The key thing to notice about this code is that while it essentially implements a class method, nothing in the module's syntax directly indicates this to be the case. The only hint we get that this is meant to be used at the class level is the use of `define_method()`, but we need to dig into the implementation code to notice that.
Before we wrap up, we should investigate why this is the case.
### A Brief Stroking of the Beard
The key thing to recognize is that `include()` mixes methods into the instances of the base object while `extend()` mixes methods into the base object itself. Notice that this is more general than a class method / instance method dichotomy.
Let's explore a few different possibilities using a somewhat contrived example so that we can focus on the mixin mechanics. First, we start with an ordinary module, which is somewhat useless on its own.
```ruby
module Greeter
def hello
"hi"
end
end
```
By including `Greeter` into `SomeClass`, we make it so that we can now call `hello()` on instances of `SomeClass`.
```ruby
class SomeClass
include Greeter
end
SomeClass.new.hello #=> "hi"
```
But as we saw in the `Forwardable` example, extending `AnotherClass` with `Greeter` would allow us to call the hello method directly at the class level, as in the example below.
```ruby
class AnotherClass
extend Greeter
end
AnotherClass.hello #=> "hi"
```
Be sure to note at this point that `extend()` and `include()` are two totally
different operations. Because you did not extend `SomeClass` with `Greeter`, you
could not call `SomeClass.hello()`. Similarly, you cannot call
`AnotherClass.new.hello()` without explicitly including `Greeter`.
From the examples so far, it might seem as if `include()` is for defining instance methods, and `extend()` is for class methods. But that is not quite accurate, and the next bit of code illustrates just how much deeper the rabbit hole goes.
```ruby
obj = Object.new
obj.extend(Greeter)
obj.hello #=> "hi"
```
Before you let this example make you go cross-eyed, let's review the key point I made at the beginning of this section: <i>The key thing to recognize is that `include()` mixes methods into the instances of the base object while `extend()` mixes methods into the base object itself.</i>
Since not every base object can have instances, not every object can have modules included into them (in fact, only classes can). But *every* object can be extended by modules. This includes, among other things, classes and modules themselves.
Let's try to bring the two `extend()` examples closer together with the following little snippet:
```ruby
MyClass = Class.new
MyClass.extend(Greeter)
MyClass.hello #=> "hi"
```
If you feel like you understand the lines above, you're ready for the rest
of this mini-series. If not, please ponder the following questions and leave a
comment sharing your thoughts.
### Questions To Consider
* Why do we have both `include()` and `extend()` available to us? Why not just have one way of doing mixins?
* When you write `extend()` within a class definition, does it do any sort of special casing? Or is it the same as calling `extend()` on any other object?
* Except for mixing in class methods, what is `extend()` useful for?
Please feel free to ask for hints on any of these if you're stumped, or share your answers if you'd like to help others and maybe get a bit of feedback to check your assumptions against.
> **NOTE:** This article has also been published on the Ruby Best Practices blog. There [may be additional commentary](http://blog.rubybestpractices.com/posts/gregory/038-issue-9-uses-for-modules.html#disqus_thread)
over there worth taking a look at.
================================================
FILE: articles/v1/010-uses-for-modules.md
================================================
> Note: This article series on modules is also available as a [PDF download]. The
> PDF version has been revised and is more up-to-date than what you see here.
[PDF download]:https://github.com/elm-city-craftworks/pr-monthly/blob/gh-pages/b5e5a89847701c4aa7c170cf/sept-2012-modules.pdf?raw=true
In the last two issues, we covered mixins and namespacing, two of the most common uses for modules. In the second half of this series, we'll look at some other ways to use modules that are not quite so obvious.
We can now focus on the question that caused me to write this series in the
first place. Many readers were confused by my use of `extend self` within
earlier Practicing Ruby articles, and this lead to a number of interesting
questions on the mailing list at the time these articles were originally
published. While I tried my best to answer them directly, I think we're in better
shape to study this topic now that the last two articles have laid a
foundation for us.
### Review of how `extend()` works
To understand this trick of mixing modules into themselves, one first must understand how `extend()` works. We covered this concept at the end of the last article, but we can touch on it again for good measure. Start by considering the trivial module shown below.
```ruby
module Greeter
def hello
"hi"
end
end
```
We had shown that unlike `include()` which is especially designed for augmenting class definitions so that a mixin can add instance methods to some target class, `extend()` has a much more simple behavior and works with any object.
```ruby
obj = Object.new
obj.extend(Greeter)
obj.hello #=> "hi"
```
From this, we can see that mixing in a module by using extend simply mixes the methods defined by the module directly at that object's level. In this way, the methods defined by the module are mixed into the receiver, no matter what that object is.
In Ruby, classes and modules are ordinary objects. We can confirm this by doing a tiny bit of introspection on `Greeter`.
```ruby
>> Greeter.object_id
=> 212500
>> Greeter.class
=> Module
>> Greeter.respond_to?(:extend)
=> true
```
While this may be a mental leap for some, you might be able to find peace with it by considering the ordinary module definition syntax to be a bit of sugar that is functionally equivalent to the following bit of code.
```ruby
Greeter = Module.new do
def hello
"hi"
end
end
```
When written in this way, it becomes far more obvious that `Greeter` is actually just an instance of the class Module, making it an ordinary Ruby object at its core. Once you feel that you understand this point, consider what happens when the following line of code is run.
```ruby
Greeter.extend(Greeter)
```
If we compare this to previous examples of `extend()`, it should be clear now that despite the seemingly circular reference, this line does exactly what it would if called on any other object: It mixes the methods defined by `Greeter` directly into the `Greeter` object itself. A simple test confirms this to be true.
```ruby
Greeter.hello #=> "hi"
```
If we unravel things a bit, we find that we could have written our `extend()` call slightly differently, by doing it from within the module definition itself:
```ruby
module Greeter
extend Greeter
def hello
"hi"
end
end
```
The reason `extend()` works here is because `self == Greeter` in this context.
Noticing this detail allows us to use slightly more dynamic approach, resulting
in the following code.
```ruby
module Greeter
extend self
def hello
"hi"
end
end
```
You'll find this new code to be functionally identical to the previous example, but slightly more flexible. Now, if we change the name of our module, we won't need to update our `extend()` call. This is why folks tend to write `extend self` rather than `extend TheCurrentModule`.
Hopefully by now, it is clear that this trick does not involve any sort of special casing for modules, and is an ordinary application of the `extend()` method provided by every Ruby object. The only thing that might be confusing is the seemingly recursive nature of the technique, but this issue disappears when you recognize that modules are not mixed into anything by default, and that modules themselves are not directly related to the methods they define. If you understand the difference between class and instance methods in Ruby, this isn't a far stretch from that concept.
While the inner workings of modules are an interesting academic topic, my emphasis is always firmly set on practical applications of programming techniques rather than detached conceptual theory. So now that we've answered 'how does this work?', let's focus on the much more interesting 'how can I use it?' topic.
### Self-Mixins as Function Bags
A fascinating thing about Ruby is the wide range of different software design paradigms it supports. While object-oriented design is heavily favored, Ruby can do a surprisingly good job of emulating everything from procedure programming to prototype-based programming. But the one area that Ruby overlaps most with is functional programming.
Now, before you retire your parenthesis for good and herald Ruby as a replacement for LISP, be warned: There is a lot about Ruby's design that makes it a horrible language for functional programming. But when used sparingly, techniques from the functional world fit surprisingly well in Ruby programs. The technique I find most useful is the ability to organize related functions together under a single namespace.
When we create class definitions, we tend to think of the objects we're building as little structures which manage state and provide behaviors which manipulate that state. But sometimes, a more stateless model makes sense. The closer you get to pure mathematics, the more a pure functional model makes sense. We need to look no farther than Ruby's own `Math` module for an example:
```ruby
>> Math.sin(Math::PI/2.0)
=> 1.0
>> Math.log(Math::E)
=> 1.0
```
It seems unlikely that we'd want to create an instance of a `Math` object, since
it doesn't really deal with any state that persists beyond a single function
call. But it might be desirable to mix this functionality into another object so
that you can call math functions without repeating the `Math` constant
excessively. For this reason, Ruby implements `Math` as a module.
```ruby
>> Math.class
=> Module
```
For another great example of modular code design in Ruby itself, be sure to check out the `FileUtils` standard library, which allows you to execute basic *nix file operations as if they were just ordinary function calls.
After seeing how Ruby is using this technique, I didn't find it hard to stumble upon scenarios in my own code that could benefit from a similar design. For example, when I was working on building out the backend for a trivia website, I was given some logic for normalizing user input so that it could be compared against a predetermined pattern.
While I could have stuck this logic in a number of different places, I decided I wanted to put it within a module of its own, because its logic did not rely on any persistent state and could be defined independently of the way our questions and quizzes were modeled. The following code is what I came up with:
```ruby
module MinimalAnswer
extend self
def match?(pattern, input)
pattern.split(/,/).any? do |e|
normalize(input) =~ /\b#{normalize(e)}/i
end
end
private
def normalize(input)
input.downcase.strip.gsub(/\s+/," ").gsub(/[?.!\-,:'"]/, '')
end
end
```
The nice thing about the code above is that using a modular design doesn't force you to give up things like private methods. This allows you to keep your user facing API narrow while still being able to break things out into helper methods.
Here is a simple example of how my `MinimalAnswer` module is used within the application:
```ruby
>> MinimalAnswer.match?("Cop,Police Officer", "COP")
=> true
>> MinimalAnswer.match?("Cop,Police Officer", "police officer")
=> true
>> MinimalAnswer.match?("Cop,Police Officer", "police office")
=> false
>> MinimalAnswer.match?("Cop,Police Officer", "police officer.")
=> true
```
Now as I said before, this is a minor bit of functionality and could probably be shelved onto something like a `Question` object or somewhere else within the system. But the downside of that approach would be that as this `MinimalAnswer` logic began to get more complex, it would begin to stretch the scope of whatever object you attached this logic to. By breaking it out into a module right away, we give this code its own namespace to grow in, and also make it possible to test the logic in isolation, rather than trying to bootstrap a potentially much more complex object in order to test it.
So whenever you have a bit of logic that seems to not have many state dependencies between its functions, you might consider this approach. But since stateless code is rare in Ruby, you may wonder if learning about self-mixins really bought us that much.
As it turns out, the technique can also be used in more stateful scenarios when you recognize that Ruby modules are objects themselves, and like any object, can contain instance data.
### Self-Mixins for Implementing Singleton Pattern
Ruby overloads the term 'singleton object', so we need to be careful about terminology here. What I'm about to show you is how to use these self-mixed modules to implement something similar to the [Singleton design pattern](http://en.wikipedia.org/wiki/Singleton_pattern).
I've found in object design that objects typically need zero, one, or many instances. When an object doesn't really need to be instantiated at all because it has no data in common between its behaviors, the modular approach we just reviewed often works best. The vast majority of the remaining cases fall into ordinary class definitions which facilitate many instances. Virtually everything we model fits into this category, so it's not worth discussing in detail. However, there are some cases in which a single object is really all we need. In particular, configuration systems come to mind.
The following example shows a simple DSL I wrote for the trivia application I had mentioned earlier. It may look familiar, and that is because it appeared in our discussion on writing configuration systems some weeks ago. This time around, our focus will be on how this system actually works rather than what purpose it serves.
```ruby
AccessControl.configure do
role "basic",
:permissions => [:read_answers, :answer_questions]
role "premium",
:parent => "basic",
:permissions => [:hide_advertisements]
role "manager",
:parent => "premium",
:permissions => [:create_quizzes, :edit_quizzes]
role "owner",
:parent => "manager",
:permissions => [:edit_users, :deactivate_users]
end
```
To implement code that allows the definitions above to be modeled internally, we need to consider how this system will be used. While it is easy to imagine roles shifting over time, getting added and removed as needed, it's hard to imagine what the utility of having more than one `AccessControl` object would be.
For this reason, it's safe to say that `AccessControl` configuration data is global information, and so does not need the data segregation that creating instances of a class provides.
By modeling `AccessControl` as a module rather than class, we end up with an object that we can store data on that can't be instantiated.
```ruby
module AccessControl
extend self
def configure(&block)
instance_eval(&block)
end
def definitions
@definitions ||= {}
end
# Role definition omitted, replace with a stub if you want to test
# or refer to Practicing Ruby Issue #4
def role(level, options={})
definitions[level] = Role.new(level, options)
end
def roles_with_permission(permission)
definitions.select { |k,v| v.allows?(permission) }.map { |k,_| k }
end
def [](level)
definitions[level]
end
end
```
There are two minor points of potential confusion in this code worth discussing, the first is the use of `instance_eval` in `configure()`, and the second is that the `definitions()` method refers to instance variables. This is where we need to remind ourselves that the scope of methods defined by a module cannot be determined until it is mixed into something.
Once we recognize these key points, a bit of introspection shows us what is really going on.
```ruby
>> AccessControl.configure { "I am #{self.inspect}" }
=> "I am AccessControl"
>> AccessControl.instance_eval { "I am #{self.inspect}" }
=> "I am AccessControl"
>> AccessControl.instance_variables
=> ["@definitions"]
```
Since `AccessControl` is an ordinary Ruby object, it has ordinary instance variables and can make use of `instance_eval` just like any other object. The key difference here is that `AccessControl` is a module, not a class, and so cannot be used as a factory for creating more instances. In fact, calling `AccessControl.new` raises a `NoMethodError`.
In a traditional implementation of Singleton Pattern, you have a class which disables instantiation through the ordinary means, and creates a single instance that is accessible through the class method `instance()`. However, this seems a bit superfluous in a language in which classes are full blown objects, and so isn't necessary in Ruby.
For cases like the configuration system we've shown here, choosing to use this approach is reasonable. That having been said, the reason why I don't have another example that I can easily show you is that with the exception of this narrow application for configuration objects, I find it relatively rare to have a legitimate need for the Singleton Pattern. I'm sure if I thought long and hard on it, I could dig some other examples up, but upon looking at recent projects I find that variants of the above are all I use this technique for.
However, if you work with other people's code, it is likely that you'll run into someone implementing Singleton Pattern this way. Now, rather than scratching your head, you will have a solid understanding of how this technique works, and why someone might want to use it.
### Reflections
In Issue 11, we'll wrap up with some even more specialized uses for modules, showing how they can be used to build plugin systems as well as how they can be used as a replacement for monkey patching. But before we close the books on today's lesson, I'd like to share some thoughts that were rattling around in the back of my mind while I was preparing this article.
The techniques I've shown today can be useful in certain edge case scenarios
where an ordinary class definition might not be the best tool to use. In my own
code, I tend to use the first technique of creating function bags often but sparingly,
and the second technique of building singleton objects rarely and typically only
for configuration systems.
Upon reflection, I wonder to myself whether the upsides of these techniques outweigh the cost of explaining them. I don't really have a definitive answer to that question, but it's really something I think about often.
On the one hand, I feel that users of Ruby should have an ingrained understanding of its object system. After all, these are actually fairly straightforward techniques once you understand how things work under the hood. It's also true that you can't really claim to understand Ruby's object system without fully understanding these examples. Having a weak understanding of how Ruby's objects work is sure to rob you of the joy of working in Ruby, so for this reason, I feel like 'dumbing down' our code would be a bad thing.
On the other hand, I think that for the small gains yielded by using these techniques, we require those who are reading our code to understand a whole score of details that are unique to Ruby. When you consider that by changing a couple lines of code, you can have a design which is not much worse but is understandable by pretty much anyone who has programmed in an OO language before, it's certainly tempting to cater to the lowest common denominator.
But this sort of split-mindedness is inevitable in Ruby, and comes up in many scenarios. The truth of the matter is that it's going to take many more years before Ruby is truly understood by the programming community at large. But as more people dive deeper into Ruby, Ruby is starting to come into its own, and the mindset that things should be done as they are in other languages is not nearly as common as it was several years ago. For this reason, it's important to stop thinking of Ruby in terms of whatever language you've come from, and start thinking of it as its own thing. As soon as you do that, a whole range of possibilities open up.
At least, that's what I think. What about you?
> **NOTE:** This article has also been published on the Ruby Best Practices blog. There [may be additional commentary](http://blog.rubybestpractices.com/posts/gregory/040-issue-10-uses-for-modules.html#disqus_thread)
over there worth taking a look at.
================================================
FILE: articles/v1/010a-uses-for-modules.md
================================================
> Note: This article series on modules is also available as a [PDF download]. The
> PDF version has been revised and is more up-to-date than what you see here.
[PDF download]:https://github.com/elm-city-craftworks/pr-monthly/blob/gh-pages/b5e5a89847701c4aa7c170cf/sept-2012-modules.pdf?raw=true
In the [last issue](http://practicingruby.com/articles/38), we discussed the use of `extend self` in great detail, but neglected to cover a pair of alternatives that seem on the surface to be functionally equivalent. While I don't want to spend too much time rehashing an old topic, I want to at least provide an example of each approach and comment on their quirks.
### Defining methods at the module level
Occasionally folks ask whether mixing a module into itself via `extend()` is equivalent to the code shown below.
```ruby
module Greeter
def self.hello
"hi"
end
end
```
The short answer to that question is "no", but it is easy to see where the confusion comes from, because calling `Greeter.hello` does indeed work as expected. But the important distinction is that methods defined in this way are simply directly defined on the module itself and so cannot be mixed into anything at all. There is really very little difference between the above code and the example below.
```ruby
obj = Object.new
def obj.hello
"hi"
end
```
Consider our earlier example of Ruby's `Math` or `FileUtils` modules. With both of these modules, you can envision scenarios in which you would call the functions on the modules themselves. But there are also cases where using these modules as mixins would make a lot of sense. For example, Ruby itself ships with a math mode (-m) for irb which mixes in the `Math` module at the top level so you can call its functions directly.
```ruby
$ irb -m
>> sin(Math::PI/2)
=> 1.0
```
In the above example, if `sin()` were implemented by defining the method
directly on the `Math` module, there would be no way to mix it into anything.
While sometimes it might make sense to force a module to never be used as a
mixin, that use case is rare, and so little is gained by defining methods on
modules rather than using the `extend self` technique.
### Using `module_function`
Before people got in the habit of mixing modules into themselves, they often relied on a more specialized feature called `module_function` to accomplish the same goals.
```ruby
module Greeter
module_function
def hello
"hi"
end
end
```
This code allows the direct calling of `Greeter.hello`, and does not prevent
`Greeter` from being mixed into other objects. The `module_function` approach
also allows you to choose certain methods to be module functions while
leaving others accessible via mixin only:
```ruby
module Greeter
def hello
"hi"
end
def goodbye
"bye"
end
module_function :hello
end
```
With this modified definition, it is still possible to call `Greeter.hello`, but attempting to call `Greeter.goodbye` would raise a `NoMethodError`. This sort of sounds like it offers the benefits of extending a module with itself, but with some added granularity. Unfortunately, there is something about `module_function` that makes it quite weird to work with.
As it turns out, `module_function` works very different under the hood than self-mixins do. This is because `module_function` actually doesn't manipulate the method lookup path, but instead, it makes a direct copy of the specified methods and attaches them to the module itself. If that sounds too weird to be true, check out the code below.
```ruby
module Greeter
def hello
"hi"
end
module_function :hello
def hello
"howdy"
end
end
Greeter.hello #=> "hi"
class Foo
include Greeter
end
Foo.new.hello #=> "howdy"
```
Pretty weird behavior, right? You may find it interesting to know that I was not actually aware that `module_function` made copies of methods until I wrote Issue #10 and was tipped off about this by one of our readers. However, I did know about one of the consequences of `module_function` being implemented in this way: private methods cannot be used in conjunction with `module_function`. That means that the following example cannot be literally translated to use `module_function`.
```ruby
module MinimalAnswer
extend self
def match?(pattern, input)
pattern.split(/,/).any? do |e|
normalize(input) =~ /\b#{normalize(e)}/i
end
end
private
def normalize(input)
input.downcase.strip.gsub(/\s+/," ").gsub(/[?.!\-,:'"]/, '')
end
end
```
From these examples, we see that `module_function` is more flexible than defining methods directly on your modules, but not nearly as versatile as extending a module with itself. While the ability to selectively define which methods can be called directly on the module is nice in theory, I've yet to see a use case for it where it would lead to a much better design.
### Reflections
With the alternatives to `extend self` having unpleasant quirks, it's no surprise that they're quickly falling out of fashion in the Ruby world. But since no technical decision should be made based on dogma or a blind-faith acceptance of community conventions, these notes hopefully provide the necessary evidence to help you make good design decisions on your own.
> **NOTE:** This article has also been published on the Ruby Best Practices blog. There [may be additional commentary](http://blog.rubybestpractices.com/posts/gregory/041-issue-10.5-uses-for-modules.html#disqus_thread)
over there worth taking a look at.
================================================
FILE: articles/v1/011-uses-for-modules.md
================================================
> Note: This article series on modules is also available as a [PDF download]. The
> PDF version has been revised and is more up-to-date than what you see here.
[PDF download]:https://github.com/elm-city-craftworks/pr-monthly/blob/gh-pages/b5e5a89847701c4aa7c170cf/sept-2012-modules.pdf?raw=true
Today we're going to wrap up this series on modules by looking at how mixins can be useful for implementing custom behavior on individual objects. In particular, we'll be looking at how modules can be used both as a replacement for monkey patching, as well as for constructing systems that can be extended without the need for monkey patching. While neither of these techniques are going to be something you'll use every day, they really come in handy when you run into a situation that calls for them.
### Modules instead of Monkey Patches
Back in the bad old days before Prawn, I was working on a reporting framework called Ruby Reports (Ruport), which generated PDF reports via `PDF::Writer`. At the time, `PDF::Writer` was quite buggy, and essentially abandoned, but was the only game in town when it came to PDF generation.
One of the bugs was something fairly critical: Memory consumption for outputting simple PDF tables would balloon like crazy, causing a document with more than a few pages to take anywhere from several minutes to several *hours* to run.
The original author of the library had a patch laying around that inserted a hook which did some caching that greatly reduced the memory consumption, but he had not tested it extensively and did not want to want to cut a release. I had talked to him about possibly monkey patching `PDF::Document` in Ruport's code to add this patch, but together, we came up with a better solution: wrap the patch in a module.
```ruby
module PDFWriterMemoryPatch
unless self.class.instance_methods.include?("_post_transaction_rewind")
def _post_transaction_rewind
@objects.each { |e| e.instance_variable_set(:@parent,self) }
end
end
end
```
In Ruport's PDF formatter code, we did something like the following to apply our patch:
```ruby
@document = PDF::Document.new
@document.extend(Ruport::PDFWriterMemoryPatch)
```
Throughout our application, whenever someone interacted with a `PDF::Document` instance we created, they had a patched instance that fixed the memory leak. This meant from the Ruport user's perspective, the bug was fixed. So what makes this different from monkey patching?
Because we were only manipulating the individual objects that we created in our library, we were not making a global change that might surprise people. For example if someone was building an application that only implicitly loaded Ruport as a dependency, and they created a `PDF::Document` instance, our patch would not be loaded. This prevented us from causing unexpected behavior in any code that lived outside of Ruport itself.
While this approach didn't shield us from the risks that a future change to `PDF::Writer` could potentially break our patch in Ruport, it did prevent any risk of global consequences. Anyone who's ever spent a day scratching their head because of some sloppy monkey patch in a third party dependency will immediately be able to see the value of this sort of isolation.
The neat thing is that a similar approach can be used for core extensions as
well. Rather than re-opening Ruby core classes, you can imbue individual
instances with custom behavior, getting many of the benefits of monkey patching
without the disadvantages. For example, suppose you want to add the `sum)()` and
`average()` methods to Array. If we were monkey patching, we'd write something
like the following code:
```ruby
class Array
def sum
inject(0) { |s,e| s + e }
end
def average
sum.to_f / length
end
end
obj = [1,3,5,7]
obj.sum #=> 16
obj.average #=> 4
```
The danger here of course is that you'd be globally stomping anyone else's definition of `sum()` and `average()`, which can lead to ugly conflicts. All these problems can be avoided with a minor modification.
```ruby
module ArrayMathHelpers
def sum
inject(0) { |s,e| s + e }
end
def average
sum.to_f / length
end
end
obj = [1,3,5,7]
obj.extend(ArrayMathHelpers)
obj.sum #=> 16
obj.average #=> 4
```
By explicitly mixing in the `ArrayMathHelpers` module, we isolate our changes just to the objects we've created ourselves. With slight modification, this technique can also be used with objects passed into functions, typically by making a copy of the object before working on it.
Because modules mixed into an instance of an object are looked up before
the methods defined by its class,
you can actually use this technique for modifying existing behavior of an object as well.
The example below demonstrates modifying `<<` on strings so that it allows appending
arbitrary objects to a string through coercion.
```ruby
module LooseStringAppend
def <<(value)
super
rescue TypeError
super(value.to_s)
end
end
a = "foo"
a.extend(LooseStringAppend)
a << :bar << :baz #=> "foobarbaz"
```
Of course this (like most core modifications), is a horrible idea. But speaking as a pure technique, this is far better than the alternative global monkey patch shown below:
```ruby
class String
alias_method :old_append, :<<
def <<(value)
old_append(value)
rescue TypeError
old_append(value.to_s)
end
end
```
When using per-object mixins as an alternative to monkey patching, what you gain is essentially two things: A first class seat in the lookup path allowing you to make use of `super()`, and isolation on a per-object behavior so that consumers of your code don't curse you for patching things in unexpected ways. While this approach isn't always available, it is definitely preferable whenever you can choose it over monkey patching.
In Ruby 2.0, we may end up with even better option for this sort of thing called refinements, which are also module based. But for now, if you must hack other people's objects, this approach is a civil way to do it.
We'll now take a look at how to produce libraries and applications that actively encourage extensions to be done this way.
### Modules as Extension Points
This last section is not so much about practical advice as it is about taking what we've learned so far and really stretching it as far as possible into new territories. In essence, what follows are my own experiments with ideas that I'm not fully sure are good, but find interesting enough to share with you.
In previous Practicing Ruby issues, I've shown some code from a command line client we've used for time tracking in my consulting work. The tool itself never quite matured far enough to be release ready, but I used it as a testing ground for new design ideas, so it is a good conversation starter at least.
Today, I want to show how we implemented commands for it. Essentially, I want to walk through what happens when someone types the following command into their console:
```ruby
$ turbine start
Timer started at Wed Dec 15 17:55:37 -0500 2010
```
Because we knew this tool would evolve over time, we wanted to make it as hackable as possible. To do this, we set up a system in which commands get installed into a hidden folder in each project, making it trivial to modify existing commands or add new ones. Here's a quick directory listing to show what that structure looks like:
```ruby
$ ls .turbine/commands/standard/
add.rb project.rb rewind.rb status.rb commit.rb push.rb
staged.rb stop.rb drop.rb reset.rb start.rb
```
As you might expect, start.rb defines the start command. Here's what its source
looks like:
```ruby
Turbine::Application.extension(:start_command) do
def start
timer = Turbine::Timer.new
if timer.running?
prompt.say "Timer already started, please stop or rewind first"
else
timer.write_timestamp
prompt.say "Timer started at #{Time.now}"
end
end
end
```
You'll notice that all our commands are direct mappings to method
calls, which are responsible for doing all the work. While I've simplified the
following definition to remove some domain specific callbacks and options
parsing, the following example shows the basic harness which registers
Turbine's commands:
```ruby
module Turbine
class Application
def self.extensions
@extensions ||= {}
end
def self.extension(key, &block)
extensions[key] = Module.new(&block)
end
def initialize
self.class.extensions.each do |_, extension|
extend(extension)
end
end
def run(command)
send(command)
end
end
end
```
From this, we see that `Turbine::Application` stores a Hash of anonymous modules
which are created on the fly whenever the `extension()` is called. The
interesting thing about this design is that the commands aren't applied globally
to `Turbine::Application`, but instead, are mixed in at the instance level. This
approach allows us to selectively disable features, or completely replace them
with alternative implementations.
For example, consider a custom command that gets loaded after the standard commands, which is implemented like this:
```ruby
Turbine::Application.extension(:start_command) do
def go
puts "Let's go!"
end
end
```
Because the module defining the `go()` method would replace the original module in the extensions hash, the original module ends up getting completely wiped out. In retrospect, for my particular use case, this approach seems to be like using a thermonuclear weapon where a slingshot would do, but you can't argue that this fails to take extensibility to whole new limits.
Eventually, when someone falls off the deep end in their study of modules, they ask 'is it possible to uninclude them?', and the short answer to that question is "No", promptly followed up with "Why would you want to do that?". But what we've shown here is a good approximation for unincluding a module, even if we haven't quite figured out the answer to the 'why' part yet.
But sometimes, we have to explore just for the fun of it, right? :)
### Reflections
I have had a blast writing to you all about modules and answering your questions as they come up. Unfortunately, the topic is even bigger than I thought, and there are at least two full articles I could write on the topic,which might actually be more practical and immediately relevant than the materials I've shared today. In particular, we didn't cover things like the `included()` and `extended()` hooks, which can be quite useful and are worth investigating on your own.
Moving forward, my goals for Practicing Ruby are to be able to hit a wide range of topics, so we'll probably move away from the fundamentals of Ruby's object system and go back to some more problem-solving oriented topics in the coming weeks. But if you like this kind of format, please let me know.
> **NOTE:** This article has also been published on the Ruby Best Practices blog. There [may be additional commentary](http://blog.rubybestpractices.com/posts/gregory/043-issue-11-uses-for-modules.html#disqus_thread)
over there worth taking a look at.
================================================
FILE: articles/v1/012-rapid-prototyping.md
================================================
Ruby makes it easy to quickly put together a proof-of-concept for almost any kind of project, as long as you have some experience in rapid application development. In this article, I will go over how I build prototypes, sharing the tricks that have worked well for me.
Today we'll be walking through a bit of code that implements a small chunk of a falling blocks game that is similar to Tetris. If you're not familiar with Tetris, head over to [freetetris.org](http://freetetris.org) and play it a bit before reading this article.
Assuming you're now familiar with the general idea behind the game, I'll walk you through the thought process that I went through from the initial idea of working on a falling blocks game to the small bit of code I have written for this issue.
### The Planning Phase
After running through a few ideas, I settled on a falling blocks game as a good example of a problem that's too big to be tackled in a single sitting, but easy enough to make some quick progress on.
The next step for me was to come up with a target set of requirements for my
prototype. To prevent the possibilities from seeming endless, I had to set a
time limit up front to make this decision making process easier. Because
very small chunks of focused effort can get you far in Ruby, I settled on
coming up with something I felt I could build within an hour or two.
I knew right away this meant that I wasn't going to make an interactive demo. Synchronizing user input and screen output is something that may be easy for folks who do it regularly, but my concurrency knowledge is very limited, and I'd risk spending several hours on that side of things and coming up empty if I went down that path. Fortunately, even without an event loop, there are still a lot of options for building a convincing demo.
In my initial optimism, I thought what I'd like to be able to do is place a piece on the screen, and then let gravity take over, eliminating any completed lines as it fell into place. But this would require me to implement collision detection, something I didn't want to tackle right away.
Eventually, I came up with the idea of just implementing the action that happens when a piece collides with the junk on the grid. This process involved turning the active piece into inactive junk, and then removing any completed rows from the grid. This is something that I felt fit within the range of what I could do within an hour or two, so I decided to sleep on it and see if any unknowns bubbled up to the surface.
I could have just started hacking right away, but ironically that's a practice I typically avoid when putting together rapid prototypes. If this were a commercial project and I quoted the customer 2-4 hours, I'd want to use their money in the best possible way, and picking the wrong scope for my project would be a surefire way to either blow the budget or fail to produce something interesting. I find a few hours of passive noodling helps me see unexpected issues before they bite me.
Fortunately, this idea managed to pass the test of time, and I set out to begin coding by turning the idea into a set of requirements.
### The Requirements Phase
A good prototype does not come from a top-down or bottom-up design, but instead comes from starting in the middle and building outwards. By taking a small vertical slice of the problem at hand, you are forced to think about many aspects of the system, but not in a way that requires you consider the whole problem all at once. This allows most of your knowledge and often a good chunk of your code to be re-used when you approach the full project.
The key is to start with a behavior the user can actually observe. This means that you should be thinking in terms of features rather than functions and objects. Some folks use story frameworks such as Cucumber to help them formalize this sort of inside-out thinking, but personally, I prefer just to come up with a good, clear example and not worry about shoehorning it into a formal setting.
To do this, I created a simple text file filled with ascii art that codified two cases: One in which a line was cleared, and where no lines were cleared. Both cases are shown below.
### CASE 1: REMOVING COMPLETED LINES
```
==========
#
#| |
|#|| ||
|||#||||||
==========
```
BECOMES:
```
==========
|
|| |
|||| ||
==========
```
### CASE 2: COLLISION WITHOUT ANY COMPLETED LINES
```
==========
#
##| |
|#|| ||
||| ||||||
==========
```
BECOMES:
```
==========
|
||| |
|||| ||
||| ||||||
==========
```
---------------------------------------------------------------------
With the goals for the prototype clearly outlined, I set out to write a simple program that would perform the necessary transformations.
### The Coding Phase
One thing I'll openly admit is that when prototyping something that will take me less than a half day from end to end, I tend to relax my standards on both testing and writing clean code. The reason for this is that when I'm trying to take a nose-dive into a new problem domain, I find my best practices actually get in the way until I have at least a basic understanding of the project.
What I'll typically do instead is write a single file that implements both the objects I need and an example that gets me closer to my goal. For this project, I started with a canvas object for rendering output similar to what I outlined in my requirements.
Imagining this canvas object already existed, I wrote some code for generating the very first bit out output we see in the requirements.
```ruby
canvas = FallingBlocks::Canvas.new
(0..2).map do |x|
canvas.paint([x,0], "|")
end
canvas.paint([2,1], "|")
(0..3).map do |y|
canvas.paint([3,y], "#")
end
(4..9).map do |x|
canvas.paint([x,0], "|")
end
[4,5,8,9].map do |x|
canvas.paint([x,1], "|")
end
canvas.paint([4,2], "|")
canvas.paint([9,2], "|")
puts canvas
```
While I use a few loops for convenience, it's easy to see that this code does little more than put symbols on a text grid at the specified (x,y) coordinates. Once `FallingBlocks::Canvas` is implemented, we'd expect the following output from this example:
```
==========
#
#| |
|#|| ||
|||#||||||
==========
```
What we have done is narrowed the problem down to a much simpler task, making it easier to get started. The following implementation is sufficient to get the example working, and is simple enough that we probably don't need to discuss it further.
```ruby
module FallingBlocks
class Canvas
SIZE = 10
def initialize
@data = SIZE.times.map { Array.new(SIZE) }
end
def paint(point, marker)
x,y = point
@data[SIZE-y-1][x] = marker
end
def to_s
[separator, body, separator].join("\n")
end
def separator
"="*SIZE
end
def body
@data.map do |row|
row.map { |e| e || " " }.join
end.join("\n")
end
end
end
```
However, things get a little more hairy once we've plucked this low hanging fruit. So far, we've built a tool for painting the picture of what's going on, but that doesn't tell us anything about the underlying structure. This is a good time to start thinking about what Tetris pieces are.
While a full implementation of the game would require implementing rotations and movement, our prototype looks at pieces frozen in time. This means that a piece is really just represented by a collection of points. If we define each piece based on an origin of [0,0], we end up with something like this for a vertical line:
```ruby
line = FallingBlocks::Piece.new([[0,0],[0,1],[0,2],[0,3]])
```
Similarly, a bent S-shaped piece would be defined like this:
```ruby
bent = FallingBlocks::Piece.new([[0,1],[0,2],[1,0],[1,1]])
```
In order to position these pieces on a grid, what we'd need as an anchor point that could be used to translate the positions occupied by the pieces into another coordinate space.
We could use the origin at [0,0], but for aesthetic reason, I didn't like the mental model of grasping a piece by a position that could potentially be unoccupied. Instead, I decided to define the anchor as the top-left position occupied by the piece, which could later be translated to a different position on the canvas. This gives us an anchor of [0,3] for the line, and an anchor of [0,2] for the bent shape. I wrote the following example to outline how the API should work.
```ruby
line = FallingBlocks::Piece.new([[0,0],[0,1],[0,2],[0,3]])
p line.anchor #=> [0,3]
bent = FallingBlocks::Piece.new([[0,1],[0,2],[1,0],[1,1]])
p bent.anchor #=> [0,2]
```
Once again, a simple example gives me enough constraints to make it easy to write an object that implements the desired behavior.
```ruby
class Piece
def initialize(points)
@points = points
establish_anchor
end
attr_reader :points, :anchor
# Gets the top-left most point
def establish_anchor
@anchor = @points.max_by { |x,y| [y,-x] }
end
end
```
As I was writing this code, I stopped for a moment and considered that this logic, as well as the logic written earlier that manipulates (x,y) coordinates to fit inside a row-major data structure are the sort of things I really like to write unit tests for. There is nothing particularly tricky about this code, but the lack of tests makes it harder to see what's going on at a glance. Still, this sort of tension is normal when prototyping, and at this point I wasn't even 30 minutes into working on the problem, so I let the feeling pass.
The next step was to paint these pieces onto the canvas, and I decided to start
with their absolute coordinates to verify my shape definitions. The following example
outlines the behavior I had expected.
```ruby
canvas = FallingBlocks::Canvas.new
bent_shape = FallingBlocks::Piece.new([[0,1],[0,2],[1,0],[1,1]])
bent_shape.paint(canvas)
puts canvas
```
OUTPUTS:
```
==========
#
##
#
==========
```
Getting this far was easy, the following definition of `Piece` does the trick:
```ruby
class Piece
SYMBOL = "#"
def initialize(points)
@points = points
establish_anchor
end
attr_reader :points, :anchor
# Gets the top-left most point
def establish_anchor
@anchor = @points.min_by { |x,y| [y,-x] }
end
def paint(canvas)
points.each do |point|
canvas.paint(point, SYMBOL)
end
end
end
```
This demonstrates to me that the concept of considering pieces as a collection of points can work, and that my basic coordinates for a bent piece are right. But since I need a way to translate these coordinates to arbitrary positions of the grid for this code to be useful, this iteration was only a stepping stone. A new example pushes us forward.
```ruby
canvas = FallingBlocks::Canvas.new
bent_shape = FallingBlocks::Piece.new([[0,1],[0,2],[1,0],[1,1]])
canvas.paint_shape(bent_shape, [2,3])
puts canvas
```
OUTPUTS
```
==========
#
##
#
==========
```
As you can see in the code above, I decided that my `Piece#paint` method was probably better off as `Canvas#paint_shape`, just to collect the presentation logic in one place. Here's what the updated code ended up looking like.
```ruby
class Canvas
# ...
def paint_shape(shape, position)
shape.translated_points(position).each do |point|
paint(point, Piece::SYMBOL)
end
end
end
```
This new code does not rely directly on the `Piece#points` method anymore, but instead, passes a position to the newly created `Piece#translated_points` to get a set of coordinates anchored by the specified position.
```ruby
class Piece
#...
def translated_points(new_anchor)
new_x, new_y = new_anchor
old_x, old_y = anchor
dx = new_x - old_x
dy = new_y - old_y
points.map { |x,y| [x+dx, y+dy] }
end
end
```
While this mapping isn't very complex, it's yet another point where I was
thinking 'gee, I should be writing tests', and a couple subtle bugs that
cropped up while implementing it confirmed my gut feeling. But with the light
visible at the end of the tunnel, I wrote an example to unify piece objects
with the junk left on the grid from previous moves.
```ruby
game = FallingBlocks::Game.new
bent_shape = FallingBlocks::Piece.new([[0,1],[0,2],[1,0],[1,1]])
game.piece = bent_shape
game.piece_position = [2,3]
game.junk += [[0,0], [1,0], [2,0], [2,1], [4,0],
[4,1], [4,2], [5,0], [5,1], [6,0],
[7,0], [8,0], [8,1], [9,0], [9,1],
[9,2]]
puts game
```
OUTPUTS:
```
==========
#
##| |
|#|| ||
||| ||||||
==========
```
The key component that tied this all together is the `Game` object, which essentially is just a container that knows how to use a `Canvas` object to render itself.
```ruby
class Game
def initialize
@junk = []
@piece = nil
@piece_position = []
end
attr_accessor :junk, :piece, :piece_position
def to_s
canvas = Canvas.new
junk.each do |pos|
canvas.paint(pos, "|")
end
canvas.paint_shape(piece, piece_position, "#")
canvas.to_s
end
end
```
I made a small change to `Canvas#paint_shape` so that the symbol used to display pieces on the grid was parameterized rather than stored in `Piece::SYMBOL`. This isn't a major change and was just another attempt at moving display code away from the data models.
After all this work, we've made it back to the output we were getting out of our first example, but without the smoke and mirrors. Still, the model is not as solid as I'd hoped for, and some last minute changes were needed to bridge the gap before this code was ready to implement the two use cases I was targeting.
Since the last iteration would be a bit cumbersome to describe in newsletter form, please just "check out my final commit":http://is.gd/jbvdB for this project on github. With this new code, it's possible to get output identical to our target story through the following two examples.
### CASE 1: line_shape_demo.rb
```ruby
require_relative "falling_blocks"
game = FallingBlocks::Game.new
line_shape = FallingBlocks::Piece.new([[0,0],[0,1],[0,2],[0,3]])
game.piece = line_shape
game.piece_position = [3,3]
game.add_junk([[0,0], [1,0], [2,0], [2,1], [4,0],
[4,1], [4,2], [5,0], [5,1], [6,0],
[7,0], [8,0], [8,1], [9,0], [9,1],
[9,2]])
puts game
puts "\nBECOMES:\n\n"
game.update_junk
puts game
```
### CASE 2: bended_shape_demo.rb
```ruby
require_relative "falling_blocks"
game = FallingBlocks::Game.new
bent_shape = FallingBlocks::Piece.new([[0,1],[0,2],[1,0],[1,1]])
game.piece = bent_shape
game.piece_position = [2,3]
game.add_junk([[0,0], [1,0], [2,0], [2,1], [4,0],
[4,1], [4,2], [5,0], [5,1], [6,0],
[7,0], [8,0], [8,1], [9,0], [9,1],
[9,2]])
puts game
puts "\nBECOMES:\n\n"
game.update_junk
puts game
```
### Reflections
Once I outlined the story by drawing some ascii art, it took me just over 1.5 hours to produce working code that performs the transformations described. Overall, I'd call that a success.
That having been said, working on this problem was not without hurdles. While it turns out that removing completed lines and turning pieces into junk upon collision is surprisingly simple, I am still uneasy about my final design. It seems that there is considerable duplication between the grid maintained by `Game` and the `Canvas` object. But a refactoring here would be non-trivial, and I wouldn't want to attempt it without laying down some tests to minimize the amount of time hunting down subtle bugs.
For me, this is about as far as I can write code organically in a single sitting without either writing tests, or doing some proper design in front of whiteboard, or a combination of the two. I think it's important to recognize this limit, and also note that it varies from person to person and project to project. The key to writing a good prototype is getting as close to that line as you can without flying off the edge of a cliff.
In the end though, what I like about this prototype is that it isn't just an illusion. With a little work, it'd be easy enough to scale up to my initial ambition of demonstrating a free falling piece. By adding some tests and doing some refactoring, it'd be possible to evolve this code into something that could be used in production rather than just treating it as throwaway demo-ware.
Hopefully, seeing how I decomposed the problem, and having a bit of insight into what my though process was like as I worked on this project has helped you understand what goes into making proof-of-concept code in Ruby. I've not actually taught extensively about this process before, so describing it is a bit of an experiment for me. Let me know what you think!
> **NOTE:** This article has also been published on the Ruby Best Practices blog. There [may be additional commentary](http://blog.rubybestpractices.com/posts/gregory/044-issue-12-rapid-prototyping.html#disqus_thread)
over there worth taking a look at.
================================================
FILE: articles/v1/013-obfuscations.md
================================================
Rather than always focusing on SERIOUS BUSINESS, I'd like share something a little more light hearted today. Whether you celebrate Christmas or not, I think you'll find this little holiday themed hack a great deal of fun to play with.
### Christian Neukirchen's Christmas Hack
When I first started programming in Ruby, the ruby-talk mailing list was the best place to interact with the community and keep up with other active Ruby hackers. But because there were a lot more hobbyists in 2004 than there were people doing Ruby as a full time job, the posts focused on sharing fun hacks just as often as they did on discussing practical issues.
One of my favorites was [Christian Neukirchen](http://twitter.com/#!/chneukirchen)'s obfuscated Christmas message to the Ruby community in 2004. I've copied the source code below, and I encourage you to run it and see that it is indeed a valid Ruby program!
```ruby
s="IyBUaGFua3MgZm9yIGxvb2tpbmcgYXQgbXkgY29kZ
S4KIwojIENvcHlyaWdodCAoQykgMjAwMiAgQ2hyaXN0a
WFuI E 5 l d Wtpc
mNoZ W 4 gP G N obmV
1a2l y Y 2hlb k B nbWF
pbC5 j b 20+CiM K I yBUa
GlzI H Byb2dyYW 0 gaXM
gZnJ l Z SBzb2Z0d2F y Z Tsge
W91I G NhbiByZWRpc3 R yaWJ
1dGU g aXQgYW5kL29yCi M g bW9k
aWZ5 I Gl0IHVuZGVyIHRoZ S B0ZX
Jtcy B vZiB0aGUgR05VIEdlb m VyYW
wgUH V ibGljIExpY 2 Vuc2
UuCg p T VERPVVQuc3lu Y y A9IH
RydW U KZDEsIGQyID0gM C 4xNS
wgMC 4 wNgpzID0gIk1lcnJ 5 IGNo
cmlz d G1hcywgLi4uIGFuZCB h IGhh
cHB5 I G5ldyB5ZWFyIgptID0gJ X d7LC
AuID ogISArICogMCBPIEB9CnUg P SAiI
CIgK i BzLnNpemUKCnByaW50ICJcci A gI3t
1fVx y IjsKCigwLi4ocy5z a XplL
TEpK S 50b19hLnNvcnRfYnkg e yByY
W5kI H 0uZWFjaCB7IHxyfAogIH N sZWV
wIGQ x CiAgbmV4dCBpZiBzW3JdID 0 9ICI
gIls wXQogIG0uZWFjaCB7IHxrfAo gICA
gdVt y XSA9IGsKICAgIHByaW50ICIgIC N 7dX1
cciI KICAgIHNsZWVwIGQyCiAgfQogIHV bcl0
gPSB zW3JdCiAgcHJpbnQgIiAgI3t1fVxyI g p9Cg
pzbG VlcCBkMgpwcmludCAiICAje3V9IVxyI jsKc
2xlZ X A gMwpwc m l udCA
iICA j e3V9IS A g LS1j
aHJp c z JcbiI7 C g ojIG
ZpbG x lciBzc G F jZSA
jIyM j I yMjIyM j I yMjI
yMjI y M j I yMjI
yMK";eval s.delete!(" \n").unpack("m*")[0]##
### Copyright (C) 2004 Christian Neukirchen
```
When run, this code prints out <i>"Merry christmas, ... and a happy new year! --chris2"</i> by randomly filling in each character in a little animation. After some folks commented on how cool this hack was, someone inevitably asked how it was done, which lead another Ruby hacker Michael Neumann to post his guess to the list. Here is what he said:
>Pretty easy (except drawing the tree :). Write the source-code first, then `base64` encode it, and insert newlines/whitespace to make the picture.
At the time, I was too much of a beginner with Ruby to fully appreciate the solution discussion, and mostly just chalked it up to magic. But now, the above statement is immediately obvious to me, and since it wasn't further explained in the mailing list thread, I can give an example for those who are in the same shoes now that I was in a few years ago.
What I didn't know at the time is that `Base64` is an encoding that allows you to translate any binary data into purely printable characters by converting the contents into a string of characters that uses basic alphanumeric values. I would have known that if I read the documentation for Ruby's `Base64` standard library, but again, I was a newbie at the time. :)
It turns out that the idea for `Base64` encoding was extracted from how MIME attachments in email are implemented. This is all stuff you can find on wikipedia, so rather than digging into the gory details, let's see how it relates to the problem at hand.
The following small snippet should clear things up a bit.
```ruby
>> source = "puts 'hello world'"
=> "puts 'hello world'"
>> encoded_source = Base64.encode64(source)
=> "cHV0cyAnaGVsbG8gd29ybGQn\n"
>> Base64.decode64(encoded_source)
=> "puts 'hello world'"
>> eval Base64.decode64(encoded_source)
hello world
=> nil
```
Another way of decoding `Base64` encoded strings is via the `String#unpack` method, using the template `"m*"`. You can see this in Christian's code, which is what tipped Michael off in the first place. With that in mind, we can build a tiny obfuscated "Hello World" program.
```ruby
s =
"c H V0cyA
n a G
VsbG 8
g d 2
9 y bGQn"
eval s.delete(" \n").unpack("m*")[0]
```
In the end, Michael was right when he said this was pretty easy to do. As long
as you understand some basic string manipulation and how to decode a `base64`
encoded string, you could use this technique to render your code as pretty much any arbitrary ASCII art.
Of course, one would expect that the guy who eventually would go on to create something as clever and useful as the [Rack web server interface](https://github.com/rack/rack) would have an extra trick or two up his sleeve. Not to disappoint, Christian confirmed Michael's explanation was valid, but in the process revealed that he felt it'd be too fragile and tedious to manually format the code himself into the desired ascii art.
For those curious about how he got around this problem, you can check out his [full solution](http://groups.google.com/group/comp.lang.ruby/msg/aa5b4f8eaa85e6b8?dmode=source)
which implements a code generator that fills in a template with the `base64` encoded source.
While the code should be pretty easy to follow with a little effort, feel free to post questions here if you need help figuring things out. It's a really neat bit of code and is worth exploring, so I don't mind giving some hints where needed.
### Reflections
Writing this article reminded me of two lessons that I sometimes forget, even to this day.
The first lesson is that you can't judge the complexity of something by simply scratching its surface. When I saw this code posted to ruby-talk back in 2004, even though I was a newbie at the time, I could have figured it out if I only took a bit of time to study the topics that were being discussed. But since I saw a bunch of obscure binary data in the shape of a Christmas tree being passed to `eval()`, I judged the snippet as being too complicated for me, appreciated it for its magic, and moved on. That sort of lack of self-confidence can really prevent you from stumbling upon interesting new ideas, tools, and techniques.
The second lesson is that hacking doesn't always have to be SERIOUS BUSINESS.
Because I'm working on things I feel are super important most of the time, it's
easy for me to forget to be playful and generally curious. Sometimes I feel like
I'm too busy to do something just for the joy of the hack, and that worries me a bit.
Writing this article reminded that I should resist this temptation, and make more
time and space in my life for playful discovery, because it is a great way to learn
and have fun at the same time.
> **NOTE:** This article has also been published on the Ruby Best Practices blog. There [may be additional commentary](http://blog.rubybestpractices.com/posts/gregory/045-issue-14-obfuscations.html#disqus_thread)
over there worth taking a look at.
================================================
FILE: articles/v1/014-duck-typing.md
================================================
Type systems are a fundamental part of every programming language. In fact, the way a language designer approaches typing goes a long way towards outlining the way that thoughts are expressed in that language.
Statically typed languages like C++ and Java make us tend to think of objects as abstract data structures that fit within a neatly defined hierarchy. In these languages, there isn't a major distinction between an object's class and its type, as the two concepts are tied together directly at the implementation level. But the marriage of class and type found in these languages is not a universal law shared by all object oriented programming languages.
By contrast, Ruby's dynamic nature facilitates a style of type system known as duck typing. In particular, duck typing breaks the strong association between an object's class and its type by defining types based on what an object can do rather than what class it was born from. This subtle shift in semantics changes virtually everything about how you need to think about designing object oriented systems, making it a great topic for Practicing Ruby to cover.
While duck typing is possible in many other languages, Ruby is designed from the ground up to support this style of objected oriented design. In this issue, we will cover some of the options that are available to us for doing Ruby-style type checking.
### Type Checking Techniques
There are three common ways to do type checking in Ruby, two of which involve
duck typing, and one that does not. Here's an example of the approach
that does *not* involve duck typing.
```ruby
def read_data(source)
case source
when String
File.read(source)
when IO
source.read
end
end
```
If you've been working with Ruby for a while, you've probably written code that
did type checking in this fashion. Ruby's case statement is powerful, and
makes this sort of logic easy to write. Our `read_data()` function works as
expected in the following common scenarios:
```ruby
filename = "foo.txt"
read_data(filename) #=> reads the contents of foo.txt by calling
# File.read()
input = File.open("foo.txt")
read_data(input) #=> reads the contents of foo.txt via
# the passed in file handle
```
But things begin to fall apart a bit when we decide we'd like `read_data()` to
work with a `Tempfile`, or with a `StringIO` object, or perhaps with a mock
object we've defined in our tests. We have baked into our logic the assumption that the input is always either a descendent of `String` or a descendent of `IO`. The purpose of duck typing is to remove these restrictions by focusing only on the messages that are being passed back and forth between objects rather than what class they belong to. The code below demonstrates one way you can do that.
```ruby
def read_data(source)
return source.read if source.respond_to?(:read)
return File.read(source.to_str) if source.respond_to?(:to_str)
raise ArgumentError
end
```
With this modification, our method expects far less of its input. The passed in
object simply needs to implement either a meaningful `read()` or `to_str()`
method. In addition to being backwards compatible with our non-duck-typed code,
this new approach gives us access to many useful standin objects, including: `StringIO`, `Tempfile`, mock objects for testing, and any user defined objects that are either IO-like or String-like but not a descendent of either.
However, the following contrived example illustrates a final corner case that calls for a bit of extreme duck typing to resolve. Try to spot the problem before reading about how to solve it.
```ruby
class FileProxy
def initialize(tempfile)
@tempfile = tempfile
end
def method_missing(id, *args, &block)
@tempfile.send(id, *args, &block)
end
end
```
This code implements a proxy which forwards all of its messages to the wrapped `tempfile` object. However, like many hastily coded proxy objects in Ruby, it does not properly forward `respond_to?()` calls to the object it wraps. The irb session below illustrates the resulting false negative in our test.
```ruby
# Populate our tempfile through the proxy
>> proxy = FileProxy.new(Tempfile.new("foo.txt"))
=> #<FileProxy:0x39461c @tempfile=#<File:/var/f..foo.txt.7910.3>>
>> proxy << "foo bar baz"
=> #<File:/var/folders/sJ/sJo0IkPYFWCY3t5uH+gi0++++TQ/-Tmp-/foo.txt.7910.3>
>> proxy.rewind
=> 0
# Unsuccessfully test for presence of read() method
>> proxy.respond_to?(:read)
=> false
# But read() works as expected!
>> proxy.read
=> "foo bar baz"
```
This issue will cause `read_data()` to raise an `ArgumentError` when passed a `FileProxy`. In this case, the best solution is to fix `respond_to?()` so that it works as expected, but since you may often encounter libraries with bad behaviors like this, it's worth knowing what the duck typing fundamentalist would do in this situation.
```ruby
def read_data(source)
begin
return source.read
rescue NoMethodError
# do nothing, just catch the specific error you'd expect if
# read() was not present.
end
begin
File.read(source.to_str)
rescue NoMethodError
raise ArgumentError # now we've run out of valid cases, so let's
# raise a meaningful error
end
end
```
With this final version, we preserve all the benefits of the previous duck
typing example, but we can work with objects that have dishonest `respond_to?()`
methods. Unfortunately, the cost for such flexibility includes code that is less
pleasant to read and is almost certainly going to run slower than either of our
previous implementations. Using the exception system for control flow isn't cheap,
even if this is the most 'pure' form of type checking we can do.
While we've talked about the benefits and drawbacks of each of these approaches, I haven't given any direct advice on whether one way of doing type checking is better than the others, simply because there is no simple answer to that question.
I will paint a clearer picture in the next article by showing several
realistic examples of why duck typing can come in handy. Until then, I will
leave you with a few things to think about.
### Questions / Study Topics
* Is explicit class checking ever absolutely necessary? Are their situations in which even if other options are available, checking the class of an object is still the best thing to do?
* Name something weird that can happen when you write your contracts on the messages your objects respond to rather than what class of object they are.
* Try to identify some feature of Ruby that relies on duck typing either for its basic functionality or as an extension point meant to be customized by application programmers.
* Share a bit of code which does explicit class comparison that you think would be very difficult to convert to a duck-typing style.
* Share a bit of code (either your own or from a OSS project you like) that you feel uses duck typing effectively.
Feel free to leave a comment below if any of the above topics interest you.
> **NOTE:** This article has also been published on the Ruby Best Practices blog. There [may be additional commentary](http://blog.rubybestpractices.com/posts/gregory/046-issue-14-duck-typing.html#disqus_thread)
over there worth taking a look at.
================================================
FILE: articles/v1/015-duck-typing.md
================================================
Today, I've got a handful of neat examples to share, each which demonstrates an interesting use of duck typing. We'll start by looking a feature built into Ruby's core, and then look at a few examples from other open source Ruby projects.
### Type Coercion, Ruby-style
Many dynamically typed languages that offer both integer and floating point
arithmetic are smart about doing the right thing based on whether or not any
floats are used in a given expression. While I assume that you are already
familiar with Ruby's behavior, the following example demonstrates what
I've just described.
```ruby
>> 3/2
=> 1
>> 3/2.0
=> 1.5
```
This is an obvious candidate for implementation level special casing, but since all the primitive numeric types in Ruby are actually objects, Ruby prefers something a bit more flexible and consistent. What actually happens when an arithmetic operation is performed on a Ruby number is that a method called `coerce()` is called to do any necessary type modifications so that the computations work as expected. The irb session shown below demonstrates calling `coerce()` directly on both a `Fixnum` and a `Float`.
```ruby
>> 3.coerce(2)
=> [2, 3]
>> 3.coerce(2.0)
=> [2.0, 3.0]
>> 3.0.coerce(3)
=> [3.0, 3.0]
>> 3.0.coerce(2.0)
=> [2.0, 3.0]
```
Note that `Fixnum#coerce` only returns an array of Float values when its argument is a Float, but that `Float#coerce` always does this conversion. While what is shown above only demonstrates how floating point coercion works, we can actually create our own objects that duck type to Ruby numbers by simply defining a `coerce()` method on them.
To demonstrate this, I have created a partial implementation of a `BinaryInteger` object. A `BinaryInteger` is meant to act similar to Ruby's `Fixnum` objects but display itself to the user in binary notation. Here's an example of how such an object might be used:
```ruby
>> int = BinaryInteger.new(40)
=> 0b101000
>> 2 + int
=> 0b101010
>> 2.5 + int
TypeError: BinaryInteger can't be coerced into Float
from ./binary_integer.rb:49:in `+'
from (irb):4
from :0
```
The following class definition does not quite produce a complete `Numeric` work-alike but it is sufficient for making the previous example work as shown. It also serves to demonstrate that `coerce()` is indeed the magic that ties all of Ruby's arithmetic operations together.
```ruby
class BinaryInteger
def initialize(value)
@value = value
end
attr_accessor :value
def integer?
true
end
def +(other)
a,b = coerce(other) # use our own coerce here
self.class.new(a.value + b.value)
end
def coerce(other)
raise TypeError unless other.integer?
if other.respond_to?(:value)
[self, other] # no coercion needed
else
[self, self.class.new(other)]
end
end
def inspect
"0b#{@value.to_s(2)}"
end
end
```
While it can be tricky to puzzle through how `coerce()` should work, since you can't know in advance what the calling object will be, it is a lot more dynamic than enforcing class based typing. Getting in the practice of thinking in terms of the interactions between the objects in your project rather than their static definitions can lead to some very good design insights.
In addition to the `coerce()` method for arithmetic, Ruby uses a whole score of other coercion hooks, including `to_int`, `to_str`, and `to_ary`. These methods are called on the arguments passed to a number of `Fixnum`, `String`, and `Array` methods. The neat thing is that there is no strict requirement that these methods actually return `Fixnum`, `String`, or `Array` objects, as long as they act close enough to the real thing where it counts (i.e. for whatever messages that get sent to them).
We could probably spend all day going through other examples of where Ruby uses duck typing for coercion, for extension points, and tons of other uses. This is especially true when you consider that almost every mixin relies on a form of duck typing. For example, all functionality in `Enumerable` can work with anything that implements a sensible `each()` method. Similarly a suitable `<=>` operator unlocks all that `Comparable` has to offer. In both the core and standard library, you will find plenty of examples of this sort of design.
The key point to take away from these observations is that duck-typed APIs aren't some obscure edge case for the extensibility-obsessed, but instead, something baked into Ruby's philosophy from the ground up. This means that you can and should imitate this style in your own libraries when it makes sense to do so.
We'll now take a look at a pair of examples from the wild, one from my own project (Prawn), and another from Aaron Patterson's Rails 3.1 performance tuning adventures. Both involve the use of duck typing not for the purpose of infinite flexibility, but for addressing practical problems that come up in most moderately complex projects.
### Duck typing to avoid scope creep
The first example of duck typing in actual Ruby projects that I want to share is actually quite similar to the contrived `read_data()` example I shared on Tuesday. Today, rather than showing you the usage code first, I want you to take a look at the implementation and try to spot the usage of duck typing and guess at what it gains us before reading on.
```ruby
def image(file, options={})
Prawn.verify_options [:at, :position, :vposition, :height,
:width, :scale, :fit], options
if file.respond_to?(:read)
image_content = file.read
else
raise ArgumentError, "#{file} not found" unless File.file?(file)
image_content = File.binread(file)
end
# additional implementation details omitted.
end
# FULL IMPLEMENTATION OF image() at:
# https://github.com/sandal/prawn/blob/master/lib/prawn/images.rb#L65
```
If you guessed this code is used to make it so that the `image()` method can be called with either a file name or a file handle, you had the right idea. It does all of the things we discussed yesterday, allowing the use of this code with `StringIO`, `Tempfile`, any mock object that implements a `read()` method, etc. But the really interesting use case is the one that we actually wrote this feature for, shown below.
```ruby
require "open-uri"
Prawn::Document.generate("remote_images.pdf") do
image open("http://prawn.majesticseacreature.com/images/prawn.png")
end
```
Through the use of `open-uri`, our duck-typed image method provides a nice way
of rendering remote content! While this might not have been an easy feature to
guess without knowing a bit about Prawn, it represents the elegant compromise that such an implementation affords us. Adding support for remote images was something that our users often asked for, but we wanted to avoid giving people the impression that Prawn was web-aware, and didn't want to support a special case for this sort of logic, as it'd require either an API change or an ugly hack to determine whether the provided string was either a URI or a file name.
The approach of accepting anything with a `read()` method combined with Ruby's standard library `open-uri` made for something that is easy to document and easy for our users to remember. While a simple hack, I was very satisfied with how this design turned out because it seemed to mostly eliminate the problem for our users while simultaneously avoiding some overly complex implementation code that might be brittle and hard to test.
These sort of tough design decisions are certainly not unique to Prawn, so we can now turn our eyes to Aaron Patterson's performance optimization work on Rails 3.1.
### Duck typing for performance tuning
One area Aaron Patterson found was a hotspot for many Rails apps are `ActiveRecord` scopes, which allow the users to create custom filters. For example, consider the following example which filters by email address.
```ruby
class Comment < ActiveRecord::Base
scope :with_email, lambda { |email|
where(:email => email)
}
end
# Above code provides functionality shown below
User.with_email("gregory.t.brown@gmail.com").count #=> 1
```
The block syntax is nice and clean for simple things, but can get a bit unwieldy for complex logic. For example, if we wanted to throw in validations for the entered email addresses, our block would end up getting a bit ugly unless we implemented some private class methods to help out. If you're thinking that private class methods sound weird and might be a bit of a code smell, they are, and that's one indication that this API needs to be more flexible than what it is.
That said, Aaron was on a performance tuning mission, not an API overhaul. The
problem he found with the API was initially not an aesthetic one but an
implementation detail: Executing code stored in a `Proc` object is considerably
more computationally expensive than an ordinary method call. While this isn't
likely to be a bottleneck in ordinary situations, it is common for high traffic
Rails applications to really hammer on their scopes, since they're used for
filtering the data that is presented to users. The key ins
gitextract_ccqrdc7w/
├── .gitignore
├── AUTHORS.md
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── articles/
│ ├── v1/
│ │ ├── 001-method-lookup.md
│ │ ├── 002-method-lookup.md
│ │ ├── 003-configurable.md
│ │ ├── 004-configurable.md
│ │ ├── 005-testing-antipatterns.md
│ │ ├── 006-good-and-bad-code.md
│ │ ├── 007-good-and-bad-code.md
│ │ ├── 008-uses-for-modules.md
│ │ ├── 009-uses-for-modules.md
│ │ ├── 010-uses-for-modules.md
│ │ ├── 010a-uses-for-modules.md
│ │ ├── 011-uses-for-modules.md
│ │ ├── 012-rapid-prototyping.md
│ │ ├── 013-obfuscations.md
│ │ ├── 014-duck-typing.md
│ │ ├── 015-duck-typing.md
│ │ ├── 016-interesting-ruby-hackers.md
│ │ ├── 017-interesting-ruby-writers.md
│ │ ├── 018-testing-dogma.md
│ │ ├── 019-thoughts-on-mocking.md
│ │ ├── 020-thoughts-on-mocking.md
│ │ ├── 021-how-to-practice.md
│ │ ├── 022-how-to-practice.md
│ │ ├── 023-solid-design.md
│ │ ├── 024-connascence.md
│ │ ├── 025-creational-design-patterns.md
│ │ ├── 026-structural-design-patterns.md
│ │ └── README.md
│ ├── v2/
│ │ ├── 001-ways-to-load-code.md
│ │ ├── 002-sticky-problems.md
│ │ ├── 003-closure-double-edged-sword.md
│ │ ├── 004-roll-your-own-enumerable-and-enumerator.md
│ │ ├── 005-regression-testing.md
│ │ ├── 006-learning-new-things-step-by-step.md
│ │ ├── 007-unobtrusive-ruby.md
│ │ ├── 008-singleton-pattern.md
│ │ ├── 009-unix-style-command-line-applications.md
│ │ ├── 010-from-requirements-discovery-to-release.md
│ │ ├── 011-domain-specific-api-construction.md
│ │ ├── 012-working-with-binary-file-formats.md
│ │ ├── 014-arguments-and-results-1.md
│ │ ├── 015-arguments-and-results-2.md
│ │ └── README.md
│ ├── v3/
│ │ ├── 001-quality-software.md
│ │ ├── 002-building-excellent-examples.md
│ │ ├── 003-turing-tarpit.md
│ │ ├── 004-climbing-the-spiral-staircase-of-refactoring.md
│ │ ├── 005-framework-design-and-implementation.md
│ │ ├── 006-framework-design-and-implementation.md
│ │ ├── 007-criteria-for-disciplined-inheritance.md
│ │ ├── 008-criteria-for-disciplined-inheritance.md
│ │ ├── 009-using-games-to-practice-domain-modeling.md
│ │ ├── 010-robustness.md
│ │ └── README.md
│ ├── v4/
│ │ ├── 001-testing-costs-benefits.md
│ │ ├── 002-moving-beyond-the-first-release.md
│ │ ├── 004-cheap-counterfeits-jekyll.md
│ │ ├── 005-scoring-predictions-kata.md
│ │ ├── 006-persisting-relations.md
│ │ ├── 007-confident-ruby.md
│ │ ├── 008-implementing-active-record.md
│ │ ├── 009-the-hidden-costs-of-inheritance.md
│ │ ├── 010-implementing-active-record.md
│ │ ├── 011-responsibility-vs-data-driven.md
│ │ ├── 012-tdd-lessons-learned.md
│ │ ├── 012.1-tdd-lessons-learned-lesson-1.md
│ │ ├── 012.2-tdd-lessons-learned-lesson-2.md
│ │ ├── 012.3-tdd-lessons-learned-lesson-3.md
│ │ ├── 012.4-tdd-lessons-learned-lesson-4.md
│ │ └── README.md
│ ├── v5/
│ │ ├── 001-statistical-modeling.md
│ │ ├── 002-rocket-science-and-lod.md
│ │ ├── 003-evented-io.md
│ │ ├── 004-service-apis.md
│ │ ├── 005-process-spawning-patterns.md
│ │ ├── 006-service-quality.md
│ │ ├── 007-dependencies-notifications-and-adjustments.md
│ │ ├── 008-clojure.md
│ │ ├── 009-ants.md
│ │ ├── 010-prototypes.md
│ │ └── README.md
│ ├── v6/
│ │ ├── 001-parsing-json.md
│ │ ├── 002-code-reading.md
│ │ ├── 003-actors.md
│ │ ├── 004-code-reuse.md
│ │ ├── 005-debugging.md
│ │ ├── 006-recipes-method-bloat.md
│ │ ├── 007-demeter.md
│ │ ├── 008-procedural-to-oop.md
│ │ ├── 009-isolate-responsibilities.md
│ │ ├── 010-concept-before-code.md
│ │ └── README.md
│ ├── v7/
│ │ ├── 001-simulating-tiny-worlds.md
│ │ ├── 002-http-server.md
│ │ ├── 003-stats.md
│ │ ├── 004-incremental.md
│ │ ├── 005-low-level.md
│ │ ├── 006-infrastructure.md
│ │ ├── 007-wumpus.md
│ │ ├── 008-language-learning.md
│ │ ├── 008-oss-quality.md
│ │ ├── 009-course1.md
│ │ ├── 010-information.md
│ │ └── README.md
│ └── v8/
│ ├── 001-problem-discovery.md
│ ├── 002-formula-processing.md
│ └── README.md
└── templates/
└── default.html.erb
Condensed preview — 114 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,847K chars).
[
{
"path": ".gitignore",
"chars": 14,
"preview": "articles-html\n"
},
{
"path": "AUTHORS.md",
"chars": 406,
"preview": "The articles within this repository are copyrighted works, released under a\ncreative commons license by their respective"
},
{
"path": "Gemfile",
"chars": 72,
"preview": "source 'https://rubygems.org'\n\ngem \"rake\"\ngem \"kramdown\"\ngem \"coderay\" \n"
},
{
"path": "LICENSE.txt",
"chars": 22238,
"preview": "Creative Commons Legal Code\n\nAttribution-ShareAlike 3.0 Unported\n\n CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND"
},
{
"path": "README.md",
"chars": 1423,
"preview": "## Practicing Ruby: Manuscripts archive\n\nThis is a collection of publicly released articles from the [Practicing\nRuby](h"
},
{
"path": "Rakefile",
"chars": 842,
"preview": "require \"kramdown\"\nrequire \"coderay\"\nrequire \"fileutils\"\n\nMARKDOWN_FILES = Dir.glob(\"#{__dir__}/articles/**/*.md\")\n\ntask"
},
{
"path": "articles/v1/001-method-lookup.md",
"chars": 7166,
"preview": "I decided to start off this newsletter with one of the most basic but essential pieces of knowledge you can have about R"
},
{
"path": "articles/v1/002-method-lookup.md",
"chars": 16133,
"preview": "In [Issue #1](http://practicingruby.com/articles/29) we discussed Ruby's lookup\npath and proved by example that class in"
},
{
"path": "articles/v1/003-configurable.md",
"chars": 6388,
"preview": "Ruby developers tend to prefer convention over configuration, but that doesn't mean our applications are configuration-f"
},
{
"path": "articles/v1/004-configurable.md",
"chars": 14158,
"preview": "In [Issue #3](http://practicingruby.com/articles/31), we looked at the downsides\nof mixing configuration code with appli"
},
{
"path": "articles/v1/005-testing-antipatterns.md",
"chars": 8572,
"preview": "If you are using `send` to test private methods in your tests, you are almost certainly doing it wrong. Most private met"
},
{
"path": "articles/v1/006-good-and-bad-code.md",
"chars": 5162,
"preview": "In this issue and the next one, I'd like to demonstrate one of my favorite learning exercises while inviting you to foll"
},
{
"path": "articles/v1/007-good-and-bad-code.md",
"chars": 14198,
"preview": "In Issue #6, you got to see my intentionally bad implementation of Tic Tac Toe. For today, I have promised to show you s"
},
{
"path": "articles/v1/008-uses-for-modules.md",
"chars": 11235,
"preview": "> Note: This article series on modules is also available as a [PDF download]. The\n> PDF version has been revised and is "
},
{
"path": "articles/v1/009-uses-for-modules.md",
"chars": 13589,
"preview": "> Note: This article series on modules is also available as a [PDF download]. The\n> PDF version has been revised and is "
},
{
"path": "articles/v1/010-uses-for-modules.md",
"chars": 17153,
"preview": "> Note: This article series on modules is also available as a [PDF download]. The\n> PDF version has been revised and is "
},
{
"path": "articles/v1/010a-uses-for-modules.md",
"chars": 5540,
"preview": "> Note: This article series on modules is also available as a [PDF download]. The\n> PDF version has been revised and is "
},
{
"path": "articles/v1/011-uses-for-modules.md",
"chars": 11159,
"preview": "> Note: This article series on modules is also available as a [PDF download]. The\n> PDF version has been revised and is "
},
{
"path": "articles/v1/012-rapid-prototyping.md",
"chars": 17607,
"preview": "Ruby makes it easy to quickly put together a proof-of-concept for almost any kind of project, as long as you have some e"
},
{
"path": "articles/v1/013-obfuscations.md",
"chars": 7543,
"preview": "Rather than always focusing on SERIOUS BUSINESS, I'd like share something a little more light hearted today. Whether you"
},
{
"path": "articles/v1/014-duck-typing.md",
"chars": 7334,
"preview": "Type systems are a fundamental part of every programming language. In fact, the way a language designer approaches typin"
},
{
"path": "articles/v1/015-duck-typing.md",
"chars": 11749,
"preview": "Today, I've got a handful of neat examples to share, each which demonstrates an interesting use of duck typing. We'll st"
},
{
"path": "articles/v1/016-interesting-ruby-hackers.md",
"chars": 12197,
"preview": "In this article, I've listed five people worth knowing about if you're involved in Ruby. If you're reading this in July "
},
{
"path": "articles/v1/017-interesting-ruby-writers.md",
"chars": 10777,
"preview": "In the [last issue](http://practicingruby.com/articles/45) we covered five folks who are working on really interesting p"
},
{
"path": "articles/v1/018-testing-dogma.md",
"chars": 7382,
"preview": "Today I have a small rant about the test obsessed culture of Ruby. This area in particular is one in which the incredibl"
},
{
"path": "articles/v1/019-thoughts-on-mocking.md",
"chars": 9097,
"preview": "When I originally published my [small rant on testing](http://practicingruby.com/articles/47), it generated a spirited d"
},
{
"path": "articles/v1/020-thoughts-on-mocking.md",
"chars": 25588,
"preview": "In the [last issue](http://practicingruby.com/articles/48), I encouraged everyone to read Martin Fowler's classic articl"
},
{
"path": "articles/v1/021-how-to-practice.md",
"chars": 10779,
"preview": "When I was 17 years old, I was asked by an Air Force military training\ninstructor how to get to Carnegie Hall. Before I "
},
{
"path": "articles/v1/022-how-to-practice.md",
"chars": 17562,
"preview": "> **NOTE:** I generally remove temporal references in Practicing Ruby \narticles to keep them disconnected from a particu"
},
{
"path": "articles/v1/023-solid-design.md",
"chars": 29082,
"preview": "SOLID is a collection of five object oriented design principles that go nicely\ntogether. Here's a super brief summary pu"
},
{
"path": "articles/v1/024-connascence.md",
"chars": 17307,
"preview": "My article on the [SOLID design\nprinciples](http://practicingruby.com/articles/52) was inspired by a great talk\nI saw by"
},
{
"path": "articles/v1/025-creational-design-patterns.md",
"chars": 22371,
"preview": "In this issue and the next one, I look at several design patterns laid out by\nthe Gang of Four and explore their relevan"
},
{
"path": "articles/v1/026-structural-design-patterns.md",
"chars": 23374,
"preview": "In this two part series, I've been looking at the classical design patterns laid out by the Gang of Four and exploring t"
},
{
"path": "articles/v1/README.md",
"chars": 3322,
"preview": "These articles are from Practicing Ruby's first volume, which ran from \n2010-11-09 to 2011-02-29. The manuscripts in thi"
},
{
"path": "articles/v2/001-ways-to-load-code.md",
"chars": 25363,
"preview": "There are many ways to load Ruby code, and that has lead to confusion over the years. In this article, I will give you t"
},
{
"path": "articles/v2/002-sticky-problems.md",
"chars": 14811,
"preview": "One project that I've always wanted to work on is the creation of a generic table datastructure for Ruby. I've partially"
},
{
"path": "articles/v2/003-closure-double-edged-sword.md",
"chars": 9771,
"preview": "Every `Proc` object is a closure, which means that each code block you write captures references to data from its surrou"
},
{
"path": "articles/v2/004-roll-your-own-enumerable-and-enumerator.md",
"chars": 19646,
"preview": "When I first came to Ruby, one of the things that impressed me the most was the killer features provided by the `Enumera"
},
{
"path": "articles/v2/005-regression-testing.md",
"chars": 16076,
"preview": "The most simple and unambiguous benefit that automated testing provides is that it can be used to minimize the impact of"
},
{
"path": "articles/v2/006-learning-new-things-step-by-step.md",
"chars": 30177,
"preview": "One of the lessons I always try to teach programmers of various skill levels is that it is very important to work in sma"
},
{
"path": "articles/v2/007-unobtrusive-ruby.md",
"chars": 20599,
"preview": "When Mike Burns outlined his vision of [Unobtrusive Ruby](http://robots.thoughtbot.com/post/10125070413/unobtrusive-ruby"
},
{
"path": "articles/v2/008-singleton-pattern.md",
"chars": 25268,
"preview": "Many design patterns that originated in other object-oriented languages have elegant Ruby translations. However, the [Si"
},
{
"path": "articles/v2/009-unix-style-command-line-applications.md",
"chars": 22405,
"preview": "Ruby is best known as a web development language, but in its early days it was\nmainly used on the command line. In this "
},
{
"path": "articles/v2/010-from-requirements-discovery-to-release.md",
"chars": 33740,
"preview": "Every time we start a greenfield software project, we are faced with the overwhelming responsibility of creating somethi"
},
{
"path": "articles/v2/011-domain-specific-api-construction.md",
"chars": 27886,
"preview": "Many people are attracted to Ruby because of its flexible syntax. Through various tricks and techniques, it is possible "
},
{
"path": "articles/v2/012-working-with-binary-file-formats.md",
"chars": 20824,
"preview": "Even if we rarely give them much thought, binary file formats are everywhere.\nRanging from images to audio files to near"
},
{
"path": "articles/v2/014-arguments-and-results-1.md",
"chars": 18529,
"preview": "Back in 1997, James Noble published a paper called [Arguments and Results](http://www.laputan.org/pub/patterns/noble/nob"
},
{
"path": "articles/v2/015-arguments-and-results-2.md",
"chars": 19363,
"preview": "Back in 1997, James Noble published a paper called [Arguments and Results](http://www.laputan.org/pub/patterns/noble/nob"
},
{
"path": "articles/v2/README.md",
"chars": 2028,
"preview": "These articles are from Practicing Ruby's second volume, which ran from \n2011-08-23 to 2011-11-30. The manuscripts in th"
},
{
"path": "articles/v3/001-quality-software.md",
"chars": 10927,
"preview": "I ended the second volume of Practicing Ruby by launching an exploration into\nthe uncomfortable question of what it mean"
},
{
"path": "articles/v3/002-building-excellent-examples.md",
"chars": 24152,
"preview": "Good code examples are the secret sauce that makes Practicing Ruby a high-quality learning resource. That said, the art "
},
{
"path": "articles/v3/003-turing-tarpit.md",
"chars": 4155,
"preview": "> NOTE: This article describes an interactive challenge that was done in\n> realtime at the time it was published. You ca"
},
{
"path": "articles/v3/004-climbing-the-spiral-staircase-of-refactoring.md",
"chars": 23495,
"preview": "In [Issue 3.3](http://practicingruby.com/articles/shared/bwgflabwncjv), I presented a proof-of-concept Ruby implementati"
},
{
"path": "articles/v3/005-framework-design-and-implementation.md",
"chars": 3042,
"preview": "Ruby is a great language for building application frameworks, particularly\nmicro-frameworks. The sad thing is that by th"
},
{
"path": "articles/v3/006-framework-design-and-implementation.md",
"chars": 14306,
"preview": "In [Issue 3.5](http://practicingruby.com/articles/22), I challenged Practicing Ruby subscribers to read through and pla"
},
{
"path": "articles/v3/007-criteria-for-disciplined-inheritance.md",
"chars": 20130,
"preview": "Inheritance is a key concept in most object-oriented languages, but applying it\nskillfully can be challenging in practic"
},
{
"path": "articles/v3/008-criteria-for-disciplined-inheritance.md",
"chars": 21073,
"preview": "In [Issue 3.7](http://practicingruby.com/articles/24), I started to explore the criteria laid out by Sakkinen's\n[Discipl"
},
{
"path": "articles/v3/009-using-games-to-practice-domain-modeling.md",
"chars": 23134,
"preview": "As programmers, it is literally our job to make [domain models](http://en.wikipedia.org/wiki/Domain_model) understandabl"
},
{
"path": "articles/v3/010-robustness.md",
"chars": 13909,
"preview": "Writing robust code is always challenging, even when dealing with extremely well controlled environments. But when you e"
},
{
"path": "articles/v3/README.md",
"chars": 1639,
"preview": "These articles are from Practicing Ruby's third volume, which ran from\n2012-01-03 to 2012-03-13. The manuscripts in this"
},
{
"path": "articles/v4/001-testing-costs-benefits.md",
"chars": 21554,
"preview": "Over the last several years, Ruby programmers have gained a reputation of being\n*test obsessed* -- a designation that ma"
},
{
"path": "articles/v4/002-moving-beyond-the-first-release.md",
"chars": 23655,
"preview": "In Issue 2.10, I described the path I took [from requirements discovery to\nrelease](http://practicingruby.com/articles/1"
},
{
"path": "articles/v4/004-cheap-counterfeits-jekyll.md",
"chars": 18564,
"preview": "While it may not seem like it at first, you can learn a great deal about Ruby by building something as simple as a stati"
},
{
"path": "articles/v4/005-scoring-predictions-kata.md",
"chars": 11766,
"preview": "*This article is written by James Edward Gray II. James is an old friend of\nGreg's, so he was thrilled to contribute. F"
},
{
"path": "articles/v4/006-persisting-relations.md",
"chars": 19644,
"preview": "*This article is written by Piotr Szotkowski. Greg invited Piotr to contribute\nto Practicing Ruby after seeing his RubyC"
},
{
"path": "articles/v4/007-confident-ruby.md",
"chars": 20953,
"preview": "*This article was contributed by [Avdi Grimm](http://avdi.org). Avdi has been wrangling Ruby code for over a\ndecade and "
},
{
"path": "articles/v4/008-implementing-active-record.md",
"chars": 19405,
"preview": "> (ORM) is one of the most complex things you could ever touch, and we choose it\n> over and over again without thinking "
},
{
"path": "articles/v4/009-the-hidden-costs-of-inheritance.md",
"chars": 18472,
"preview": "As a Ruby programmer, you almost certainly make use of inheritance-based object\nmodeling on a daily basis. In fact, exte"
},
{
"path": "articles/v4/010-implementing-active-record.md",
"chars": 23285,
"preview": "> This two part article explores the challenges involved in\n> building a minimal implementation of the Active Record pat"
},
{
"path": "articles/v4/011-responsibility-vs-data-driven.md",
"chars": 18221,
"preview": "_This article was contributed by Greg Moeck. Greg is a software \ncraftsman who has been working with Ruby since 2004. Wh"
},
{
"path": "articles/v4/012-tdd-lessons-learned.md",
"chars": 2363,
"preview": "Test-driven development (TDD) is a topic that never gets old among programmers, \neven though we can hardly agree on what"
},
{
"path": "articles/v4/012.1-tdd-lessons-learned-lesson-1.md",
"chars": 8924,
"preview": "> **NOTE:** This is one of [four lessons\n> learned](http://practicingruby.com/articles/65) from my 90 day [self-study on"
},
{
"path": "articles/v4/012.2-tdd-lessons-learned-lesson-2.md",
"chars": 12810,
"preview": "> **NOTE**: This is one of [four lessons learned](http://practicingruby.com/articles/65) \nfrom my [90 day self-study on "
},
{
"path": "articles/v4/012.3-tdd-lessons-learned-lesson-3.md",
"chars": 9973,
"preview": "> **NOTE:** This is one of [four lessons\n> learned](http://practicingruby.com/articles/65) from my 90 day [self-study on"
},
{
"path": "articles/v4/012.4-tdd-lessons-learned-lesson-4.md",
"chars": 13966,
"preview": "> **NOTE:** This is one of [four lessons\n> learned](http://practicingruby.com/articles/65) from my 90 day [self-study on"
},
{
"path": "articles/v4/README.md",
"chars": 2256,
"preview": "These articles are from Practicing Ruby's fourth volume, which ran from\nApril 2012 to July 2012. The manuscripts in this"
},
{
"path": "articles/v5/001-statistical-modeling.md",
"chars": 20092,
"preview": "> This issue was a collaboration with my wife, Jia Wu. Jia is an associate\n> scientist at the Yale Child Study Center, w"
},
{
"path": "articles/v5/002-rocket-science-and-lod.md",
"chars": 23497,
"preview": "The [Law of Demeter](http://www.ccs.neu.edu/home/lieber/LoD.html) is a well-known \nsoftware design principle for reducin"
},
{
"path": "articles/v5/003-evented-io.md",
"chars": 17441,
"preview": "*This issue of Practicing Ruby was contributed by Magnus Holm ([@judofyr][judofyr]), \na Ruby programmer from Norway. Ma"
},
{
"path": "articles/v5/004-service-apis.md",
"chars": 15309,
"preview": "*This article was contributed by Carol Nichols\n([@carols10cents](http://twitter.com/carols10cents),\n[carols10cents@rstat"
},
{
"path": "articles/v5/005-process-spawning-patterns.md",
"chars": 18081,
"preview": "*This article was contributed by [Jesse Storimer](http://jstorimer.com). He is\nthe author of [Working with Unix Processe"
},
{
"path": "articles/v5/006-service-quality.md",
"chars": 27856,
"preview": "Software projects need to evolve over time, but they also need to avoid\ncollapsing under their own weight. This balancin"
},
{
"path": "articles/v5/007-dependencies-notifications-and-adjustments.md",
"chars": 21409,
"preview": "> **CREDIT:** Although this article is my own work, it is based on ideas I got from\n> a very different but interesting ["
},
{
"path": "articles/v5/008-clojure.md",
"chars": 25800,
"preview": "An interesting thing about learning new programming languages is that it takes\nmuch less time to learn how to read progr"
},
{
"path": "articles/v5/009-ants.md",
"chars": 18223,
"preview": "*This article is based on a [heavily modified Ruby port][rubyantsim] \nof Rich Hickey's [Clojure ant simulator][hickey]. "
},
{
"path": "articles/v5/010-prototypes.md",
"chars": 25586,
"preview": "*This article was written by Avdi Grimm. Avdi is a [Ruby Rogue][rogue], a\nconsulting pair programmer, and the head chef "
},
{
"path": "articles/v5/README.md",
"chars": 177,
"preview": "The articles in this folder are from Practicing Ruby's fifth volume, which ran from\nAugust 2012 to December 2012.\n\nYou c"
},
{
"path": "articles/v6/001-parsing-json.md",
"chars": 20659,
"preview": "*This article was written by Aaron Patterson, a Ruby\ndeveloper living in Seattle, WA. He's been having fun writing Ruby"
},
{
"path": "articles/v6/002-code-reading.md",
"chars": 2309,
"preview": "> **NOTE:** This issue of Practicing Ruby is one of several content experiments that was published in Volume 6. It inten"
},
{
"path": "articles/v6/003-actors.md",
"chars": 21030,
"preview": "> This issue was a collaboration with [Alberto Fernández Capel][afcapel], a Ruby developer\nfrom Spain. Although it has b"
},
{
"path": "articles/v6/004-code-reuse.md",
"chars": 22993,
"preview": "% Code reuse in Ruby -- It's complicated \n% Gregory Brown (practicingruby.com)\n% February 12, 2013\n\n\\begin{abstract} \nRu"
},
{
"path": "articles/v6/005-debugging.md",
"chars": 15539,
"preview": "*This article was contributed by Carol Nichols\n([@carols10cents](http://twitter.com/carols10cents),\n[carols10cents@rstat"
},
{
"path": "articles/v6/006-recipes-method-bloat.md",
"chars": 8496,
"preview": "> **NOTE:** This issue of Practicing Ruby was one of several content experiments \nthat was run in Volume 6. It uses a co"
},
{
"path": "articles/v6/007-demeter.md",
"chars": 19671,
"preview": "*This article was contributed by [David A. Black](https://twitter.com/david_a_black), Lead Developer at Cyrus Innovation"
},
{
"path": "articles/v6/008-procedural-to-oop.md",
"chars": 10959,
"preview": "> **NOTE:** This issue of Practicing Ruby was one of several content experiments \nthat was run in Volume 6. It uses a co"
},
{
"path": "articles/v6/009-isolate-responsibilities.md",
"chars": 14642,
"preview": "> **NOTE:** This issue of Practicing Ruby was one of several content experiments \nthat was run in Volume 6. It uses a co"
},
{
"path": "articles/v6/010-concept-before-code.md",
"chars": 17835,
"preview": "> **NOTE:** This issue of Practicing Ruby was one of several content experiments \nthat was run in Volume 6. It uses a co"
},
{
"path": "articles/v6/README.md",
"chars": 173,
"preview": "The articles in this folder are from Practicing Ruby's sixth volume, which ran from\nJanuary 2013 to May 2013.\n\nYou can a"
},
{
"path": "articles/v7/001-simulating-tiny-worlds.md",
"chars": 20544,
"preview": "As programmers we are very comfortable with the idea of using\nsoftware to solve concrete problems. However, it is easy t"
},
{
"path": "articles/v7/002-http-server.md",
"chars": 15737,
"preview": "*This article was written by Luke Francl, a Ruby developer living in\nSan Francisco. He is a developer at [Swiftype](http"
},
{
"path": "articles/v7/003-stats.md",
"chars": 22816,
"preview": "> This issue was a collaboration with my wife, Jia Wu. Jia is an associate scientist at the Yale Child Study Center, whe"
},
{
"path": "articles/v7/004-incremental.md",
"chars": 39048,
"preview": "When you look at this photograph of highway construction, what do you see?\n\n\n\nIf your"
},
{
"path": "articles/v7/005-low-level.md",
"chars": 38105,
"preview": "> This issue of Practicing Ruby was directly inspired by Nick Morgan's\n> [Easy 6502](http://skilldrick.github.io/easy650"
},
{
"path": "articles/v7/006-infrastructure.md",
"chars": 29516,
"preview": "> This issue of Practicing Ruby was a collaboration with Mathias Lafeldt\n([@mlafeldt](https://twitter.com/mlafeldt)), an"
},
{
"path": "articles/v7/007-wumpus.md",
"chars": 28874,
"preview": " [Hunt the Wumpus][wikipedia] is a hide-and-seek game that takes place in an underground\ncave network full of interconne"
},
{
"path": "articles/v7/008-language-learning.md",
"chars": 30026,
"preview": "[ ] Day 1 review\n[ ] Day 2 review\n[ ] Day 3 review\n[ ] Day 4 review\n[ ] Day 5 review\n[ ] Explain four step system and pr"
},
{
"path": "articles/v7/008-oss-quality.md",
"chars": 27821,
"preview": "> This article was written in collaboration with Eric Hodel\n> ([@drbrain](http://twitter.com/drbrain)), a developer from"
},
{
"path": "articles/v7/009-course1.md",
"chars": 2222,
"preview": "This self-guided course will help you learn how to work with the low level \ntools that you'd usually rely on libraries a"
},
{
"path": "articles/v7/010-information.md",
"chars": 32151,
"preview": "Suppose that you want catch up with your friends \nAlice, Bob, and Carol. To do this, you might log into your favorite\nch"
},
{
"path": "articles/v7/README.md",
"chars": 129,
"preview": "The articles in this folder are from Practicing Ruby's 7th volume.\nYou can also read them for free online at practicingr"
},
{
"path": "articles/v8/001-problem-discovery.md",
"chars": 9748,
"preview": "Imagine you're a programmer for a dental clinic, and they need your help to build a vacation scheduling system for their"
},
{
"path": "articles/v8/002-formula-processing.md",
"chars": 22905,
"preview": "> This article was written in collaboration with Solomon White ([@rubysolo](http://twitter.com/rubysolo)). Solomon is a "
},
{
"path": "articles/v8/README.md",
"chars": 129,
"preview": "The articles in this folder are from Practicing Ruby's 8th volume.\nYou can also read them for free online at practicingr"
},
{
"path": "templates/default.html.erb",
"chars": 7493,
"preview": "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n <meta http-equiv=\"Content-Type\" content=\"application/xhtml+xml; cha"
}
]
About this extraction
This page contains the full source code of the elm-city-craftworks/practicing-ruby-manuscripts GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 114 files (1.7 MB), approximately 419.1k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.