Home
back in the ussr Navigation
|
|
Back In The Ussr To The Moon And Back Red Baron Back To Paris Lexington Bridge Kick Back
New interface design for MythTV MythTV 0.22 will be sporting a new interface design. Features include animation, better interactivity, and faster and easier development for themers and developers...
]]> Zap2It Labs discontinuing free TV guide service Zap2It Labs have announced (cache) via their webpage that, due to abuse of the service, data will no longer be available after September 1st. There is no other direct source, and no option to pay for the service even if the users wanted to...
]]> UK petition for free TV listings http://petitions.pm.gov.uk/Free-TV-listings/ being run to make all UK television listings freely available under royalty-free terms such as a Creative Commons License....
]]> New server DreamHosts.
I have had to drop the mirrors, atleast temporarily, as the new site is bandwidth limited.
]]> Sky Anytime for Any PC? Advogato has pointed out (cache) that Sky's advertising of their new Anytime package doesn't actually run on *any* PC. It requires Windows.
lkcl suggests the advertising is in breach of the ASA guidelines and goes on to point out the many devices runing GNU/Linux Sky is now utilising, including the set-top box, and the modified/pre-configured Netgear DG834GT for the broadband service.
Under the GPL license, Sky should provide the source code free of charge...
]]> Interview with pcHDTV Founder/CEO Open Addict has an interview (cache) with Jack Kelliher, Founder and CEO of pcHDTV, the Linux-focused hardware company that markets HDTV cards.
Their flagship product is the HD-5500 (cache) HDTV PCI card which supports the popular MythTV Linux PVR application...
]]> New HDTV chips announced at Consumer Electronics Show CES show has seen the launch of a raft of new HDTV chips.
Conexant has added two video decoders for HDTV personal video recording (PVR) set-top boxes. The CX2427X is a dual-channel video decoder that can decode two HDTV programmes simultaneously, and supporting PVR applications on up to two televisions, eliminating the need for a dedicated STB receiver for each TV.
For the cable market, Broadcom has developed an HDTV Chip with a programmable security engine that has the hardware included to support all the current conditional access systems. This will avoid the need for subscriber cards, which are costly to distribute and vulnerable to hackers, and allow new CA algorithms to be downloaded to the cableboxes...
]]> Sky+ tops 2 million mark
The rapid growth of Sky+ highlights increasing demand from customers for the ability to take control over their television viewing. With 2 million active boxes, almost 5 million viewers are using Sky+ to record without video tape, pause and rewind live TV, and record all episodes of a favourite series at the touch of a button...
]]> KWorld introduces dual hybrid TV tuner KWorld has announced a new TV tuner in the form of the DVB-T PE310 (cache). The DVB-T PE310 is a dual hybrid TV tuner PCI-Express card initially designed for the UK market.
The DVB-T PE310 sports two tuners, both of which are capable of displaying analog and digital signals, which means that you can tune into two analog sources, or two digital sources or even one analog and one digital at the same time.
On top of that, you can use the additional AV/S-Video input for CVBS, S-video or SPDIF connections...
]]> MythTV developer on ExtremeTech MythTV, has an article on ExtremeTech (cache) about his book Hacking MythTV (cache). In this article, he reviews the 'Top Plugins for MythTV' ...
]]>
|
|
|
Below, you'll find extensive information on leading
back in the ussr articles and products to help you on your way
to success.
Quitting Smoking Through Hypnosis By Abbey Grace Yap
Smoking is one of the most difficult vice to let go. It is because it is difficult to drop the habit that techniques and devices were created to help smokers in their fight to become smoke-free. It includes the use of smoking aids like: nicotine patches, artificial cigarettes, nicotine gums that help smokers get through nicotine cravings. Some techniques use the help of relaxation exercises like deep-breathing exercises or yoga to help calm a person down during moments of restlessness when withdrawal symptoms attack. And some people find it easy to just undergo hypnosis to get rid of their smoking habits. But how does hypnosis help in the fight to stop smoking? Hypnosis isn't just a simple technique wherein a trained professional embeds thoughts into your mind and you'll wake up wanting to do what they tell you. It also involves positive affirmations and suggestions to you up on your chosen cause. Hypnotherapy has a particularly high success rate in helping smokers fully quit, making it one of the most commonly sought out treatments for quitting smoking. It is also partly because, instead of focusing on the negative aspects of smoking, it informs the smoker of the positive effects they can enjoy if they stop smoking. Usually people who use the natural method of quitting smoking complain about the most crucial part of the process, this is the time when withdrawal symptoms start kicking in. These withdrawal symptoms include restlessness, dry mouth, nicotine craving, quitter's flu, irritability, fatigue, an inability to concentrate, constipation, and a feeling of tightness in the chest. These symptoms are largely a result of powerful conditioned responses. With hypnotherapy as a means to quit smoking, you can do away with the hassles of experiencing these withdrawal symptoms. With hypnosis, we reinforce these conditioned responses with positive thoughts. This means creating new conditioned responses to override those that think you will fail to stop smoking. Here is an easy and simple way to get yourself started in stopping smoking for good: make a list of all the benefits you can enjoy from being a non-smoker. Close your eyes and imagine your future self where you are no longer a smoker. Let your future self think on the time line and remember how quick and easy it was for you to stop smoking. Reflect on the wonderful feeling you felt when you realized the
Presenting for Presenters <p style="padding-left:3em;"><em>If you are speaking at RubyConf this year, we have a special
opportunity for you.</em></p>
<h2>Are You Speaking at RubyConf 2008?</h2>
<p>If so, congratuations! And have we got a deal for you …</p>
<p>Wednesday evening, Nov 5, at 6:00 pm, (that’s the night before the
conference) we are inviting all speakers to a special training
session. I’m going to be sharing some ideas for putting together and
delivering a good presentation.</p>
<p>After my talk, Patrick Ewing and Adam Keys are geared up to do some
Powerpoint Karaoke with everyone there. I’m not even sure what
Powerpoint Karaoke is, but it sounds like fun.</p>
<p>I hope to see everyone there.</p>
<h2>Update (4/Nov/08)</h2>
<p>I’ve talked to Adam today. He says that Patrick isn’t going to
able to make RubyConf this year, but we will be ready to roll with
Powerpoint Karaoke anyways.</p>
<h2>Update (5/Nov/08)</h2>
<p>It looks like the speakers training will be in the Olympic Room
tonight. The Olympic Room is on the same floor as the registration
desk. Go to the left past the elevators and turn right down that hall
(or ask someone who looks like they know what they are doing).</p> Articles are Back! <p style="padding-left:3em;"><em>I’ve received a lot of requests for my old articles …</em></p>
<h2>The Article Section has been Restored</h2>
<p>When I changed to my new hosting machine, I moved all my blog posts
but didn’t move any of the articles. Of course I <em>intended</em> to move
them eventually but never got around to it.</p>
<p>A lot of people have been asking for this article or that
presentation, or pointing out that a number of old bookmarked links
are no longer any good. So due to popular demand the <b>Articles and
Presentations</b> section of onestepback.org is now restored.</p>
<p>Enjoy</p> Comments Are Now Enabled <p style="padding-left:3em;"><em>I’ve gone without comments on this blog for a long time …</em></p>
<h2>Comments via Disqus</h2>
<p>I’ve gone through several commenting systems for this blog over
time. First was the really cool
<a href="http://onestepback.org/index.cgi/Tech/Web/MoreWebApps.rdoc">TagSurf</a>
application that allowed commenting on about any web page on the
internet arbitrary tags. Unfortunately, TagSurf died a (in the words
of its creator) “well deserved” death.</p>
<p>Then I tried a wiki for comments. That worked pretty good (aside from
spam issues), but setting up a new page for comments for each new post
was just too much hassle.</p>
<p>Now I’m trying <a href="http://disqus.com/docs/about/">Disqus</a> for comments.
It only took an hour or so to integrate Disqus with my ancient
blogging engine (anyone else still using Rublog?).</p>
<p>Kick the tires and see how it works. If you have feedback … well,
just leave a comment.</p>
<p>I guess this means I’ll have to start writing some <em>real</em> content
here so there will be something worth commenting on … let’s see if
there is anything I feel like ranting about …</p>
<p>(Oh, and a hat tip to <a href="http://brionesandco.com/ryanbriones/">Ryan
Briones</a> for pointing out Disqus
when I was ready to go out and implement something from scratch.)</p> RedMine For Rake <p style="padding-left:3em;"><em>The is now a RedMine setup for Rake, FlexMock and Builder.</em></p>
<h2>RedMine</h2>
<p>As part of an effort to get better control of changes to the my open
source projects, I’ve setup a RedMine issue tracking site for Rake,
FlexMock and Builder. You can find it at
<a href="http://onestepback.org/redmine">http://onestepback.org/redmine</a>.</p> Moving Blog Host <p style="padding-left:3em;"><em>I am changing host for the One Step Back blog.</em></p>
<h2>It’s Time to Move</h2>
<p>This is just a quick little post to let you know that the One Step
Back blog is moving. In fact, it has already moved. But don’t worry,
we aren’t going far.</p>
<p>Originally this blog was hosted on a shared co-op system run by
<a href="http://www.n2net.net/">N2Net</a>. It was dirt cheap and easy to maintain.
The down side was that support was sporadic. As the hardware has aged,
the Co-op has decided to let the current system run until the hardware
dies, and then disolve the co-op.</p>
<p>Today there are tons more hosting opportunities available than there
were when the co-op was first formed. I’m now leasing a Linode
<a href="http://www.linode.com/">node</a> and running the blog and other
associated software from there. Its almost as inexpensive and the
co-op and uptime <em>should</em> be better.</p>
<p>Write now the blog has been moved. As time passes I’ll move the
article archive as well. Let me know if anything looks amiss.</p>
<p>—Jim Weirich</p> How did you get started in software development. <h2>Tagged</h2>
<p>Looks like <a href="http://objo.com/2008/6/7/how-did-you-get-started-in-programming">Joe
O’Brien</a>
tagged me for answers to the following questions. He, in turn, was
tagged by <a href="http://joshholmes.com/">Josh Owens</a>, who in turn was tagged
by <a href="http://www.jeffblankenburg.com/index.html">Jeff Blankenburg</a>. It
looks like <a href="http://www.codinggeekette.com">Sarah Dutkiewicz</a> and
<a href="http://michaeleatonconsulting.com/blog/archive/2008/06/04/how-did-you-get-started-in-software-development.aspx">Micheal
Eaton</a> started this.</p>
<p>OK, sounds like fun. Here goes.</p>
<h2>How old were you when you started programming?</h2>
<p>I was introduced to programming in high school by reading a book on
the topic. The book taught me how to write machine code for a strange
decimal-based machine. Unfortunately, there was no actual computer
involved in the process. Shoot, who had computers back then? Certainly
not our high school (the personal computers? not invented yet!)</p>
<p>In college, I learned a smattering of <span class="caps">FORTRAN</span>. Just enough to drive a
Calcomp plotter to plot data from my undergraduate physics courses.
But didn’t really get into programming until my junior year in
college. (Story continued in next question)</p>
<h2>How did you get started in programming?</h2>
<p>So, I was planning out the courses for my junior year in college and I
had a hole in my math courses. The math class I needed was not offered
that semester, so my adviser suggested taking a computer programming
course. He said it would be useful and, who knows, I might enjoy it.</p>
<p>So I signed up for an introduction to <span class="caps">FORTRAN</span> course, figuring it
would be easy because I already knew a little bit of <span class="caps">FORTRAN</span>. I show
up on the first day of class and after a few preliminaries the
instructor jumps right into some code, that looked like this:</p>
<pre>
(de member (pip deck) (cond
((null deck) nil)
((eq pip (car deck)) t)
(t (member pip (cdr deck)))))
</pre>
<p>I remember scratching my head and thinking this was the strangest
<span class="caps">FORTRAN I</span> had ever seen. I was totally confused for about three days,
then something clicked on the third day of class. I suddenly
“<em>got</em>” what the instructor was trying to get across and it all
made perfect sense.</p>
<p>If you haven’t figured it out yet, the instructor taught us Lisp as
part of an introduction to <span class="caps">FORTRAN</span>. The instructor turned out to be
Daniel Friedman, the author of <a href="http://www.amazon.com/Little-LISPer-Third-Daniel-Friedman/dp/0023397632"><em>The Little
Lisper</em></a>,
and was well known in the Lisp community. That small exposure to Lisp
hooked me on programming from that point on. I took as many CompSci
courses as I could in my remaining year and a half in college. I
eventually graudated with a BS in Physics, but had a strong background
in Computer Science as well.</p>
<h2>What was your first language?</h2>
<p>Technically, <span class="caps">FORTRAN</span> was my first language. But Lisp is the language I
fell in love with and is what got me hooked on programming.</p>
<h2>What was the first real program you wrote?</h2>
<p>I have a very clear memory of the very first program I wrote
professionally. The reason it is so clear is that this was the first
program I wrote that was intended for actual use by someone who wanted
it. Everything else up to that time was done for my own personal
enjoyment or to satisfy some course requirement.</p>
<p>The program calculated the “critical angles” of “pieces”. I was given
the requirements by Anne Exline, a senior programmer, and proceeded to
write the program to spec. It took a few days, but when I was done I
showed the result to Anne and she was pleased with the result.</p>
<p>The funny thing is that I had no idea what a “piece” was nor what was
so critical about the angles I was calculating. I was so excited about
writing an actual program that I did not ask until the software was
done. When asked, Anne just looked at me funny and said “Rocket
Pieces”. When Cape Canaveral lauches a rocket, they track it very
carefully to make sure it stays on course. If it strays, the range
safety officer is required to activate the self destruct. The critical
angles are those angles that would cause the “rocket pieces” to land
outside the safety area of the flight path.</p>
<p>So, my very first professional program was not only useful, it might
actually save lives.</p>
<h2>What languages have you used since you started programming?</h2>
<p>Languages I have used as part of my professional career (in roughly
chronological order) include <span class="caps">FORTRAN</span>, various assembly languages,
<span class="caps">FORTH</span>, C, PL/M, C++, Java, Ruby.</p>
<p>Languages I have used in addition to those mentioned above: Pascal,
Perl, Eiffel, and Lisp/Scheme.</p>
<p>Languages I can read, but never wrote anything significant in them:
Ada, Python, Erlang, Smalltalk, <span class="caps">SNOBOL</span>, Algol, Pascal.</p>
<h2>What was your first professional programming gig?</h2>
<p>I was hired by the <span class="caps">RCA</span> Missile Test project in Cape Canaveral, Florida
as a Near Real Time Analyst. Duties included programming various
launch related software (e.g. the critical angle program mentioned
above) and working launch support.</p>
<p>The launch support was the “Near Real Time” part of the job
description. From the moment a rocket is launched until it reaches
orbital velocity, any malfunction could cause it to fall back to
earth. During this initial portion of the launch, the launch is
monitored in “real-time” so that we know exactly where it would land
if the engines were to cut off <span class="caps">NOW</span>. Trajectory calculations had to be
done in fractions of a second and updated constantly in real time.</p>
<p>After the rocket reaches oribital velocity (usually somewhere between
8 and 14 minutes into its flight), it won’t fall back to earth. At
this point the real time trajectory program is shut down and the near
real time program is started. The near real time program can take a
few minutes to calculate a more exact orbital prediction and then send
that prediction to downrange radars (e.g. the the <a href="http://en.wikipedia.org/wiki/Ascension_Island">Ascension
Island</a> station) that
won’t see the rocket until about 20 minutes after launch. It was the
job of the Near Real Time analyst to run that program and provide
oribital predictions for downrange station.</p>
<h2>If there is one thing you learned along the way that you would tell new developers, what would it be?</h2>
<p>Find something that you enjoy and do that. Life is too short to work
in a job that you dislike.</p>
<h2>What?s the most fun you?ve ever had ? programming?</h2>
<p>Oh, the fun I have had. This story still makes me smile.</p>
<p>My first computer was a single board <span class="caps">Z80</span> microcomputer with 4 KB of
memory. I wrote a small <span class="caps">FORTH</span>-like interpreter for it and hacked a
version of the animal game in <span class="caps">FORTH</span>. The animal game is a program that
plays 20 questions to figure out what animal you are thinking of. It
constructs a binary tree where each node is a question and the
subtrees are the yes and no answers to the question. To play the game,
all the program does is walk the tree, ask the question at the current
node and follow either the <span class="caps">YES</span> branch or the NO branch as appropriate.</p>
<p>If the program guesses wrong, it will ask you for your animal and a
question that will distinguish your animal from the one it guessed. It
then adds your question to the tree. By this extremely simple
mechanism, it is able to expand its knowledge base. (see <a href="http://www.rubyquiz.com/quiz15.html">Ruby Quiz
#15</a> for more details).</p>
<p>I had just finished the program and had seeded it with a single
animal, a mouse. I turned to my wife and asked her to play the game.
She thinks of an animal and starts the program, which immediately
asked her “Is it a mouse?”. She turned to me with surprise and said
“How did it know?”. Of course, the animal she picked was a mouse.</p>
<p>I don’t think I have ever impressed anyone with my programming skills
as much as she was impressed with that game.</p>
<h2>Who’s up next?</h2>
<p>I’m tagging the following people. Remember, this is entirely
voluntary so don’t feel obligated to answer. But I’m betting the
answers are interesting:</p>
<ul>
<li><a href="http://mysterycoder.blogspot.com/">Chris Nelson</a></li>
<li><a href="http://clarkware.com/cgi/blosxom">Mike Clark</a></li>
<li><a href="http://gilesbowkett.blogspot.com/">Giles Bowkett</a></li>
<li><a href="http://railsstudio.com/">Mark Windholtz</a></li>
<li><a href="http://www.vanderburg.org/Blog">Glenn Vanderburg</a></li>
</ul> Rails Conf 2008 Summary <h2>Conference Summary Video</h2>
<p>Wow, what a great conference! There was a lot of energy flowing at
RailsConf this year. Overall I’d rate this year as head and shoulders
above last year. I’m not going cover much here, but will direct you
attention to a <a href="http://www.railsenvy.com/2008/6/2/Railsconf-videos">Rails Envy
VideoCase</a> that
Greg Pollack put together. The video is a series of very short
interviews with a number of presenters giving summaries of their own
talks. The only downside with the video is that I wish it was
available <em>before</em> the conference. I see there were a number of
interesting talks that I missed.</p>
<h2>Followup on the “Modelling Dialogue”</h2>
<p>Joe O’Brien, Chris Nelson and myself did a dialogue style presentation
on the difference between object modelling and data modelling. The
most common question I got after the talk was requests for book titles
to learn more about object oriented modelling. Here are the books
that Joe, Chris and I have recommended:</p>
<ul>
<li><em><a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1212463473&sr=1-1">Domain Driven Design</a></em>—Eric Evans</li>
<li><em><a href="http://www.amazon.com/Software-Development-Principles-Patterns-Practices/dp/0135974445/ref=sr_1_1?ie=UTF8&s=books&qid=1212502027&sr=1-1">AgileSoftware Development, Principles, Patterns, and Practices</a></em>—Bob Martin</li>
<li><em><a href="http://www.amazon.com/Refactoring-Improving-Existing-Addison-Wesley-Technology/dp/0201485672/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1212465268&sr=1-1">Refactoring: Improving the Design of Existing Code</a></em>—Martin Fowler</li>
</ul> Artichoke Music Rocks <p style="float: right; padding: 0.5em;"><a href="http://www.artichokemusic.com/index2.htm"><img border="0" src="http://www.artichokemusic.com/LogocommUnity-sm.jpg"/></a></p>
<p>The Musician’s Birds of a Feather gathering at RailsConf was great. We
had a room full people, two guitars, a ukulele, a flute, several
harmonicas and an improvised drum set. Unfortunately, one of the
guitars was an electric travel guitar which had a dead battery,
therefore no way to really hear it.</p>
<p>However, the other guitar was a nice Epiphone accoustic which was
passed from player to player. It became the quickly became the basis
for most of the music performed that night.</p>
<p>I want to thank <a href="http://www.artichokemusic.com/index2.htm">Artichoke Community
Music</a> for supplying the
guitar. Travelling with a guitar by plane is a big pain, so I arrived
with nothing to bring to the music <span class="caps">BOF</span>. I called several local music
stores looking for a guitar that I could rent for an evening.
Artichoke music said they had a “not-for-profit” guitar that they
would let me borrow for a day. Not many stores would do that for an
out-of-town stranger.</p>
<p>So, if you’re in Portland looking for a good guitar store, check out
the great people at <a href="http://www.artichokemusic.com/index2.htm">Artichoke Community
Music</a>.</p> Test Driven Studio in June 2008 <p><em>Joe O’Brien and I will be leading another Test Driven
Studio in Denver, June 9-11.</em></p>
<p style="float: right; padding: 0.5em;"><a href="http://pragmaticstudio.com/images/studio/tdd-with-rails-icon.jpg"><img border="0" src="http://onestepback.org/images/pragstudio/studio-medium.gif"/></a></p>
<h2>Testing, Colorado, June … What’s not to like?</h2>
<p>About 8 years ago I come upon a technique that radically changed the
way I developed code. I was reading Martin Fowler’s “Refactoring”
book and came across this paragraph:</p>
<p style="padding-left:3em;"><em>“Whenever I do refactoring, the first step is always the
same. I need to build a solid set of tests for that section of code.
The test are essential because even though I follow refactorings
structured to avoid most of the opportunities for introducing bugs,
I’m still human and still make mistakes. Thus I need solid
tests.” </em>—Martin Fowler</p>
<p>Chapter 4 of “Refactoring” was my first introduction to JUnit and got
me interested in “Test First Design” (what we now tend to call “Test
Driven Development”). Although I wrote <em>good</em> code before, the
confidence I had in my code took a dramatic leap forward after I
started adopting <span class="caps">TDD</span> practices.</p>
<p>On June 9 through 11, <a href="http://objo.com">Joe O’Brien</a> and I will have
the pleasure of leading the next Pragmatic Programmer’s <a href="http://pragmaticstudio.com/testing-rails">Test-Driven
Development with Rails
Studio.</a> in Denver. We will
have an opportunity to share with you some of our experiences in using
<span class="caps">TDD</span> with Ruby and Rails.</p>
<p>There are still seats available, so its not too late to sign up. More
information is available
<a href="http://pragmaticstudio.com/testing-rails">here</a>.</p> Lisp in Ruby <p style="padding-left:3em;"><em>I stumbled across <a href="http://bc.tech.coop/blog/080101.html">this</a> and it got me thinking …</em></p>
<h3>Update</h3>
<p style="padding-left:3em;"><em>I’ve updated the Textile formatter on the site and the code
for this entry is now displaying correctly. The previous version was
swalling the == operators in the code.</em></p>
<h2>Lisp 1.5 Programmer’s Manual</h2>
<p>I stumbled across <a href="http://bc.tech.coop/blog/080101.html">this</a> in
Bill Clementson’s blog and remembered using the Lisp 1.5 Prgrammers
manual from the college years. I have strong memories of pouring over
that particular page in the manual and attempting to understand all
the nuances.</p>
<p>If you’ve never read the Lisp 1.5 Programamers Manual, page 13 is
the guts of a Lisp Interpreter, the “eval” and “apply” functions. It
is written in Lisp, although the notation used is a bit funky. The
entire interpreter (minus two utility functions) is presented on a
single page of the book. Talk about a concise language definition!</p>
<h2>In Ruby?</h2>
<p>I had often thought about implementing a Lisp interpreter, but back in
the “old days”, the thought of implementing garbage collection and the
whole runtime thing was a bit daunting. This was in the day before C,
so my implementation language would have been assembler … yech.</p>
<p>But as I was reviewing the page, I realized that with today’s modern
languages, I could problably just convert the funky M-Expressions used
on page 13 directly into code. So … why not?</p>
<h2>The Code</h2>
<p>Here is the complete Ruby source code for the Lisp interpreter from
page 13 of the Lisp Programmers manual:</p>
<pre>
# Kernel Extensions to support Lisp
class Object
def lisp_string
to_s
end
end
class NilClass
def lisp_string
"nil"
end
end
class Array
# Convert an Array into an S-expression (i.e. linked list).
# Subarrays are converted as well.
def sexp
result = nil
reverse.each do |item|
item = item.sexp if item.respond_to?(:sexp)
result = cons(item, result)
end
result
end
end
# The Basic Lisp Cons cell data structures. Cons cells consist of a
# head and a tail.
class Cons
attr_reader :head, :tail
def initialize(head, tail)
@head, @tail = head, tail
end
def ==(other)
return false unless other.class == Cons
return true if self.object_id == other.object_id
return car(self) == car(other) && cdr(self) == cdr(other)
end
# Convert the lisp expression to a string.
def lisp_string
e = self
result = "("
while e
if e.class != Cons
result << ". " << e.lisp_string
e = nil
else
result << car(e).lisp_string
e = cdr(e)
result << " " if e
end
end
result << ")"
result
end
end
# Lisp Primitive Functions.
# It is an atom if it is not a cons cell.
def atom?(a)
a.class != Cons
end
# Get the head of a list.
def car(e)
e.head
end
# Get the tail of a list.
def cdr(e)
e.tail
end
# Construct a new list from a head and a tail.
def cons(h,t)
Cons.new(h,t)
end
# Here is the guts of the Lisp interpreter. Apply and eval work
# together to interpret the S-expression. These definitions are taken
# directly from page 13 of the Lisp 1.5 Programmer's Manual.
def apply(fn, x, a)
if atom?(fn)
case fn
when :car then caar(x)
when :cdr then cdar(x)
when :cons then cons(car(x), cadr(x))
when :atom then atom?(car(x))
when :eq then car(x) == cadr(x)
else
apply(eval(fn,a), x, a)
end
elsif car(fn) == :lambda
eval(caddr(fn), pairlis(cadr(fn), x, a))
elsif car(fn) == :label
apply(caddr(fn), x, cons(cons(cadr(fn), caddr(fn)), a))
end
end
def eval(e,a)
if atom?(e)
cdr(assoc(e,a))
elsif atom?(car(e))
if car(e) == :quote
cadr(e)
elsif car(e) == :cond
evcon(cdr(e),a)
else
apply(car(e), evlis(cdr(e), a), a)
end
else
apply(car(e), evlis(cdr(e), a), a)
end
end
# And now some utility functions used by apply and eval. These are
# also given in the Lisp 1.5 Programmer's Manual.
def evcon(c,a)
if eval(caar(c), a)
eval(cadar(c), a)
else
evcon(cdr(c), a)
end
end
def evlis(m, a)
if m.nil?
nil
else
cons(eval(car(m),a), evlis(cdr(m), a))
end
end
def assoc(a, e)
if e.nil?
fail "#{a.inspect} not bound"
elsif a == caar(e)
car(e)
else
assoc(a, cdr(e))
end
end
def pairlis(vars, vals, a)
while vars && vals
a = cons(cons(car(vars), car(vals)), a)
vars = cdr(vars)
vals = cdr(vals)
end
a
end
# Handy lisp utility functions built on car and cdr.
def caar(e)
car(car(e))
end
def cadr(e)
car(cdr(e))
end
def caddr(e)
car(cdr(cdr(e)))
end
def cdar(e)
cdr(car(e))
end
def cadar(e)
car(cdr(car(e)))
end
</pre>
<h2>An Example</h2>
<p>And to prove it, here’s an example program using Lisp. I didn’t
bother to write a Lisp parser, so I need to express the lists in
standard Ruby Array notation (which is converted to a linked list via
the “sexp” method).</p>
<p>Here’s the ruby program using the lisp interpreter. The Lisp system
is very primitive. The only way to define the function needed is to
put them in the environment structure, which is simply an association
list of keys and values.</p>
<pre>
require 'lisp'
# Create an environment where the reverse, rev_shift and null
# functions are bound to an appropriate identifier.
env = [
cons(:rev_shift,
[:lambda, [:list, :result],
[:cond,
[[:null, :list], :result],
[:t, [:rev_shift, [:cdr, :list],
[:cons, [:car, :list], :result]]]]].sexp),
cons(:reverse,
[:lambda, [:list], [:rev_shift, :list, nil]].sexp),
cons(:null, [:lambda, [:e], [:eq, :e, nil]].sexp),
cons(:t, true),
cons(nil, nil)
].sexp
# Evaluate an S-Expression and print the result
exp = [:reverse, [:quote, [:a, :b, :c, :d, :e]]].sexp
puts "EVAL: #{exp.lisp_string}"
puts " => #{eval(exp,env).lisp_string}"
</pre>
<p>The program will print:</p>
<pre><code>$ ruby reverse.rb
EVAL: (reverse (quote (a b c d e)))
=> (e d c b a)</code></pre>
<p>All I need to do is write a Lisp parser and a <span class="caps">REPL</span>, and I’m in business!</p>
<h2>The Example in Standard Lisp Notation</h2>
<p>If you found the Ruby-ized Lisp code hard to read, here is the reverse
funtions written in a more Lisp-like manner.</p>
<pre>
(defun reverse (list)
(rev-shift list nil))
(defun rev-shift (list result)
(cond ((null list) result)
(t (rev-shift (cdr list) (cons (car list) result))) ))
</pre>
one day you've let go of the desire to smoke and stopped giving it any thought. Think of how proud you will feel the next time somebody offers you a light and you were able to successfully refuse. Enjoy that freedom and bring it with you to your present self. To create an anchor for this feeling, press your thumb and forefinger together on your right hand and hold it for about thirty seconds.
After having anchored that new, powerful condition response follow these steps when you feel a craving to have the treatment work more effectively: 1.Take three deep breaths, hold each breath for at least eight counts, and then exhale fully. 2.Drink a large glass of water all at once. 3.Use the anchor you've created and have a nice, long moment of peace and quiet. 4.Eat an orange. Oranges have bioflavinoids that combat cravings. The act of peeling an orange also gives your hands something to do, and the smell of the orange is a lot better than that of cigarette.
Hypnosis is more than what we see in television shows or movies. In fact, you cannot make people do anything using hypnosis. The truth is, if someone doesn't want to stop smoking, they will be even more definite about that during hypnosis sessions! People can always lie during hypnosis sessions, the effectivity of this treatment only depends on a person's willingness to let go of this habit and finally stop smoking. Article Directory: http://www.articlecube.com The writer, Abbey Grace Yap, is an active advocate for health consciousness and disease awareness. She possesses a deep passion in discovering new health-related information and sharing it to her readers.DrugstoreTM.com is a reputable online drug store. From sexual health to a woman's health, sleeping aids to weight loss pills, our online pharmacy offers convenient customer access to various health medicines, including an array of health product and medicare prescription drug.www.drugstoretm.com/soma.php">Buy Soma | Buy Tramadol
|
|
We strive to provide only quality articles, so if there
is a specific topic related to back that you
would like us to cover, please contact us at any time.
And again, thank you to those contributing daily to our
back in the ussr website.
Lisp in Ruby <p style="padding-left:3em;"><em>I stumbled across <a href="http://bc.tech.coop/blog/080101.html">this</a> and it got me thinking …</em></p>
<h3>Update</h3>
<p style="padding-left:3em;"><em>I’ve updated the Textile formatter on the site and the code
for this entry is now displaying correctly. The previous version was
swalling the == operators in the code.</em></p>
<h2>Lisp 1.5 Programmer’s Manual</h2>
<p>I stumbled across <a href="http://bc.tech.coop/blog/080101.html">this</a> in
Bill Clementson’s blog and remembered using the Lisp 1.5 Prgrammers
manual from the college years. I have strong memories of pouring over
that particular page in the manual and attempting to understand all
the nuances.</p>
<p>If you’ve never read the Lisp 1.5 Programamers Manual, page 13 is
the guts of a Lisp Interpreter, the “eval” and “apply” functions. It
is written in Lisp, although the notation used is a bit funky. The
entire interpreter (minus two utility functions) is presented on a
single page of the book. Talk about a concise language definition!</p>
<h2>In Ruby?</h2>
<p>I had often thought about implementing a Lisp interpreter, but back in
the “old days”, the thought of implementing garbage collection and the
whole runtime thing was a bit daunting. This was in the day before C,
so my implementation language would have been assembler … yech.</p>
<p>But as I was reviewing the page, I realized that with today’s modern
languages, I could problably just convert the funky M-Expressions used
on page 13 directly into code. So … why not?</p>
<h2>The Code</h2>
<p>Here is the complete Ruby source code for the Lisp interpreter from
page 13 of the Lisp Programmers manual:</p>
<pre>
# Kernel Extensions to support Lisp
class Object
def lisp_string
to_s
end
end
class NilClass
def lisp_string
"nil"
end
end
class Array
# Convert an Array into an S-expression (i.e. linked list).
# Subarrays are converted as well.
def sexp
result = nil
reverse.each do |item|
item = item.sexp if item.respond_to?(:sexp)
result = cons(item, result)
end
result
end
end
# The Basic Lisp Cons cell data structures. Cons cells consist of a
# head and a tail.
class Cons
attr_reader :head, :tail
def initialize(head, tail)
@head, @tail = head, tail
end
def ==(other)
return false unless other.class == Cons
return true if self.object_id == other.object_id
return car(self) == car(other) && cdr(self) == cdr(other)
end
# Convert the lisp expression to a string.
def lisp_string
e = self
result = "("
while e
if e.class != Cons
result << ". " << e.lisp_string
e = nil
else
result << car(e).lisp_string
e = cdr(e)
result << " " if e
end
end
result << ")"
result
end
end
# Lisp Primitive Functions.
# It is an atom if it is not a cons cell.
def atom?(a)
a.class != Cons
end
# Get the head of a list.
def car(e)
e.head
end
# Get the tail of a list.
def cdr(e)
e.tail
end
# Construct a new list from a head and a tail.
def cons(h,t)
Cons.new(h,t)
end
# Here is the guts of the Lisp interpreter. Apply and eval work
# together to interpret the S-expression. These definitions are taken
# directly from page 13 of the Lisp 1.5 Programmer's Manual.
def apply(fn, x, a)
if atom?(fn)
case fn
when :car then caar(x)
when :cdr then cdar(x)
when :cons then cons(car(x), cadr(x))
when :atom then atom?(car(x))
when :eq then car(x) == cadr(x)
else
apply(eval(fn,a), x, a)
end
elsif car(fn) == :lambda
eval(caddr(fn), pairlis(cadr(fn), x, a))
elsif car(fn) == :label
apply(caddr(fn), x, cons(cons(cadr(fn), caddr(fn)), a))
end
end
def eval(e,a)
if atom?(e)
cdr(assoc(e,a))
elsif atom?(car(e))
if car(e) == :quote
cadr(e)
elsif car(e) == :cond
evcon(cdr(e),a)
else
apply(car(e), evlis(cdr(e), a), a)
end
else
apply(car(e), evlis(cdr(e), a), a)
end
end
# And now some utility functions used by apply and eval. These are
# also given in the Lisp 1.5 Programmer's Manual.
def evcon(c,a)
if eval(caar(c), a)
eval(cadar(c), a)
else
evcon(cdr(c), a)
end
end
def evlis(m, a)
if m.nil?
nil
else
cons(eval(car(m),a), evlis(cdr(m), a))
end
end
def assoc(a, e)
if e.nil?
fail "#{a.inspect} not bound"
elsif a == caar(e)
car(e)
else
assoc(a, cdr(e))
end
end
def pairlis(vars, vals, a)
while vars && vals
a = cons(cons(car(vars), car(vals)), a)
vars = cdr(vars)
vals = cdr(vals)
end
a
end
# Handy lisp utility functions built on car and cdr.
def caar(e)
car(car(e))
end
def cadr(e)
car(cdr(e))
end
def caddr(e)
car(cdr(cdr(e)))
end
def cdar(e)
cdr(car(e))
end
def cadar(e)
car(cdr(car(e)))
end
</pre>
<h2>An Example</h2>
<p>And to prove it, here’s an example program using Lisp. I didn’t
bother to write a Lisp parser, so I need to express the lists in
standard Ruby Array notation (which is converted to a linked list via
the “sexp” method).</p>
<p>Here’s the ruby program using the lisp interpreter. The Lisp system
is very primitive. The only way to define the function needed is to
put them in the environment structure, which is simply an association
list of keys and values.</p>
<pre>
require 'lisp'
# Create an environment where the reverse, rev_shift and null
# functions are bound to an appropriate identifier.
env = [
cons(:rev_shift,
[:lambda, [:list, :result],
[:cond,
[[:null, :list], :result],
[:t, [:rev_shift, [:cdr, :list],
[:cons, [:car, :list], :result]]]]].sexp),
cons(:reverse,
[:lambda, [:list], [:rev_shift, :list, nil]].sexp),
cons(:null, [:lambda, [:e], [:eq, :e, nil]].sexp),
cons(:t, true),
cons(nil, nil)
].sexp
# Evaluate an S-Expression and print the result
exp = [:reverse, [:quote, [:a, :b, :c, :d, :e]]].sexp
puts "EVAL: #{exp.lisp_string}"
puts " => #{eval(exp,env).lisp_string}"
</pre>
<p>The program will print:</p>
<pre><code>$ ruby reverse.rb
EVAL: (reverse (quote (a b c d e)))
=> (e d c b a)</code></pre>
<p>All I need to do is write a Lisp parser and a <span class="caps">REPL</span>, and I’m in business!</p>
<h2>The Example in Standard Lisp Notation</h2>
<p>If you found the Ruby-ized Lisp code hard to read, here is the reverse
funtions written in a more Lisp-like manner.</p>
<pre>
(defun reverse (list)
(rev-shift list nil))
(defun rev-shift (list result)
(cond ((null list) result)
(t (rev-shift (cdr list) (cons (car list) result))) ))
</pre> The Arc Challenge <p style="padding-left:3em;"><em>Paul Graham issues the Arc Challenge … who could resist?</em></p>
<h2>Paul Graham’s Arc Challenge</h2>
<p>You can read about the Arc Challenge here: <a href="http://www.paulgraham.com/arcchallenge.html">The Arc
Challenge</a>. Go ahead a
read it now, but I will summarize the challenge.</p>
<p><strong>Write a web program such that:</strong></p>
<ul>
<li>The first page of the program displays nothing but a text box and a
submit button. You enter some arbitrary text and press the submit
button, which takes you to …</li>
</ul>
<ul>
<li>The second page is nothing but a single link labeled “click here”.
The <span class="caps">URL</span> linked to must not contain the text entered in the first
step (i.e. you are not supposed to pass the text as a parameter on
the link). Clicking the link takes you to …</li>
</ul>
<ul>
<li>The third page which contains “You said: <span class="caps">XXX</span>” (where <span class="caps">XXX</span> is the text
you entered in the first step).</li>
</ul>
<p>Here’s a screen cast demoing my solution to the Arc Challenge. (We
will show the code shortly).</p>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="466" height="281"> <param name="movie" value="http://content.screencast.com/bootstrap.swf"></param> <param name="quality" value="high"></param> <param name="bgcolor" value="#FFFFFF"></param> <param name="flashVars" value="thumb=http://content.screencast.com/media/762eebca-fa50-49f8-9b88-dc7652bd3c9a_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_Thumbnail.gif&content=http://content.screencast.com/media/499ec89e-b124-4dcb-bcd0-e74f6fac495f_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_00000084.swf&width=466&height=281"></param> <param name="allowFullScreen" value="true"></param> <param name="scale" value="showall"></param> <param name="allowScriptAccess" value="always"></param> <embed src="http://content.screencast.com/bootstrap.swf" quality="high" bgcolor="#FFFFFF" width="466" height="281" type="application/x-shockwave-flash" allowScriptAccess="always" flashVars="thumb=http://content.screencast.com/media/762eebca-fa50-49f8-9b88-dc7652bd3c9a_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_Thumbnail.gif&content=http://content.screencast.com/media/499ec89e-b124-4dcb-bcd0-e74f6fac495f_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_00000084.swf&width=466&height=281" allowFullScreen="true" scale="showall"></embed> </object>
<h2>Paul’s Solution</h2>
<p>Paul has been working on designing Arc, his ideal programming language
for the future. Given Paul’s language preferences, it is no surprise
that Arc is very Lisp-like. Here is Paul’s solution written in Arc:</p>
<pre class="testcode">
(defop said req
(aform [w/link (pr "you said: " (arg _ "foo"))
(pr "click here")]
(input "foo")
(submit)))
</pre>
<p>Paul points out that the solution is very short and elegant, only 23
nodes in the codetree. I’m sure I don’t quite understand exactly what
it is doing (I’d love to see a step by step explanation of the code).
He wonders what it would look like in other languages.</p>
<p>Several people have responded with solutions in their own languages.
I’ve seen a <a href="http://www.lukas-renggli.ch/blog/take-the-arc-challenge?_s=BXjPNOJFnBmoYxtA&_k=lERhwwWC">Smalltalk
Solution</a>
as well as a <a href="http://arc-challenge.heroku.com/">Ruby solution</a> (which
pretty closely mimics the Arc code from Paul) on the <a href="http://arclanguage.org/item?id=722">Arc Language
Forum</a> page that was setup for
responses.</p>
<h2>Continuation Web Servers</h2>
<p>The Arc challenge is a perfect candidate for a continuation based
server solution. And I recalled that Chad Fowler and I had written a
demo continuation based server for the <a href="http://onestepback.org/articles/callcc/">Continuations
Demystified</a> talk we did at
RubyConf 2005. (Look for the “Poor Man’s Seaside Demo in that
presentation.) I wondered how easy it be to code up an Arc challenge
solution using that code base.</p>
<p>The key to a continuation based server is that it allows the
programmer to code in a linear fashion. All the request/response
nature of web interaction is completely hidden from you as a
programmer.</p>
<p>For example, let’s pretend we wanted to solve the Arc challenge using
a terminal and command line rather than a web based solution. How
would you write it? Probably something like this:</p>
<pre class="rubycode">
text = gets
puts "click here"
gets
puts "You said: #{text}"
</pre>
<p>Simple, linear programming. (OK, printing “click here” is silly in a
text program, but you get the idea). You ask a question and read a
response. You pause for a click. You then tell the user what the
result is.</p>
<p>Ask. Pause. Tell.</p>
<p>Those are our basic abstract operations for this problem. Lets
rewrite our text based solution using these abstractions. We’ll put
this in a file called “arc_challenge.rb”.</p>
<pre class="rubycode">
Conversation.interact do |io|
text = io.ask
io.pause("click here")
io.tell("You said: #{text}")
end
</pre>
<p>I’ve introduced three operations (methods) that are provided by an I/O
object (let’s ignore the interact line for now). “ask” will ask the
user for input, returning the string. “pause” will pause until the
user indicates he/she is ready to continue (e.g. pressing return in our
command line version). “tell” sends the given string to the user.</p>
<p>So, what does “Conversation.interact” do? It creates the environment
where the user have a conversation with the program. The interation
is controlled through our ask/pause/tell functions provided by the I/O
object passed to the interact block.</p>
<p>Here is an implementation of a text based conversation.</p>
<pre class="rubycode">
class TextBased
def interact
yield(self)
end
def ask(prompt=nil)
print prompt, " " if prompt
gets.chomp
end
def pause(prompt="")
print prompt, " " if prompt
gets
end
def tell(message)
puts message
end
end
Conversation = TextBased.new
</pre>
<p>To run the text based conversation, just require the text. Here’s a demo:</p>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="465" height="238"> <param name="movie" value="http://content.screencast.com/bootstrap.swf"></param> <param name="quality" value="high"></param> <param name="bgcolor" value="#FFFFFF"></param> <param name="flashVars" value="thumb=http://content.screencast.com/media/1ae5f9ce-5bc5-4360-8cbc-83b165a434ab_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_Thumbnail.gif&content=http://content.screencast.com/media/90dd373a-0352-4710-acb1-6b18620a5609_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_00000080.swf&width=465&height=238"></param> <param name="allowFullScreen" value="true"></param> <param name="scale" value="showall"></param> <param name="allowScriptAccess" value="always"></param> <embed src="http://content.screencast.com/bootstrap.swf" quality="high" bgcolor="#FFFFFF" width="465" height="238" type="application/x-shockwave-flash" allowScriptAccess="always" flashVars="thumb=http://content.screencast.com/media/1ae5f9ce-5bc5-4360-8cbc-83b165a434ab_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_Thumbnail.gif&content=http://content.screencast.com/media/90dd373a-0352-4710-acb1-6b18620a5609_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_00000080.swf&width=465&height=238" allowFullScreen="true" scale="showall"></embed> </object>
<h2>Arc on the Web</h2>
<p>Well, anybody can solve the challenge in text mode. How much work do
we have to do to get it on the web.</p>
<p>The answer: Zero!</p>
<p>The code Chad and I wrote for <a href="http://onestepback.org/articles/callcc/">Continuations
Demystified</a> includes a
web-based version of the conversation object that is ready to go. All
we have to do is plug it in and run it. No changes are required to
our basic Arc challenge solution.</p>
<p>Again, a screen demo:</p>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="538" height="352"> <param name="movie" value="http://content.screencast.com/bootstrap.swf"></param> <param name="quality" value="high"></param> <param name="bgcolor" value="#FFFFFF"></param> <param name="flashVars" value="thumb=http://content.screencast.com/media/a8773d13-5fe0-46f2-adcf-8ae4830c6e53_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_Thumbnail.gif&content=http://content.screencast.com/media/2918dffc-1f80-401b-8063-d8c8bb908016_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_00000082.swf&width=538&height=352"></param> <param name="allowFullScreen" value="true"></param> <param name="scale" value="showall"></param> <param name="allowScriptAccess" value="always"></param> <embed src="http://content.screencast.com/bootstrap.swf" quality="high" bgcolor="#FFFFFF" width="538" height="352" type="application/x-shockwave-flash" allowScriptAccess="always" flashVars="thumb=http://content.screencast.com/media/a8773d13-5fe0-46f2-adcf-8ae4830c6e53_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_Thumbnail.gif&content=http://content.screencast.com/media/2918dffc-1f80-401b-8063-d8c8bb908016_e67edb68-7ed6-4b26-9b5e-cd2fd2207a40_static_0_0_00000082.swf&width=538&height=352" allowFullScreen="true" scale="showall"></embed> </object>
<p>Yes, we know that although we now have our Arc Challenge on the web,
we haven’t quite conformed to the exact requirements of the challenge.
We will handle that next.</p>
<h2>The Final Arc Solution</h2>
<p>The problem is that the current Web based conversation object makes
all kinds of assumptions that are not appropriate for the final Arc
solution.</p>
<p>In particular, we need to change:</p>
<ul>
<li>Get rid the head line, restart link and other extraneous <span class="caps">HTML</span>
elements.</li>
</ul>
<ul>
<li>Don’t keep a running log of the conversation. When you move to a
new page, you start from scratch.</li>
</ul>
<ul>
<li>The “click here” should be a real link, not just a text box where
you can press enter.</li>
</ul>
<p>To get to here, we will have to make some modifications to the
conversation web library. It turns out the changes are pretty
straight forward. The whole interaction framework is controlled by
the Conversation object that implements ask/pause/tell methods. You
can see the changes made for the Arc challenge in the
“noecho_web_based.rb” file (see the end of this post for the
availability of the source code).</p>
<h2>The Final Conversation Based Solution</h2>
<p>In cased you missed it, here is the Arc Challenge Solution:</p>
<pre class="rubycode">
Conversation.interact do |io|
text = io.ask
io.pause("click here")
io.tell("You said: #{text}")
end
</pre>
<p>Yep, it’s the exact same file we used for the text based solution. I
don’t know if it is as elegant as Paul’s version, but I certainly find
it easy to read and understand. (Rerun the <a href="http://www.screencast.com/t/mFoZAA7N">very first screen
cast</a> in this posting if you want
to see it in action again).</p>
<p>If you want to look at the code, there is a
<a href="http://onestepback.org/download/conversations.tgz">tarball</a> available
that contains all the continuation server demo code from
<a href="http://onestepback.org/articles/callcc/">Continuations Demystified</a>
talk, as well as the two new files I added for the Arc challenge.
“arc_challenge.rb” is the actually solution and “noecho_web_based.rb”
is the conversation library that renders the solution in the style set
forth by the challenge.</p>
<p>Enjoy.</p> Erlang-like Method Definition in FlexMock <p style="padding-left:3em;"><em>Some fun with Erlang and FlexMock.</em></p>
<h2>Erlang Function Definitions</h2>
<p>Erlang defines functions by listing a set of possible argument lists
and the body of the function to be executed for each argument list.
For example, the factorial function might be defined in Erlang as:</p>
<pre>
factorial(0) -> 1;
factorial(N) -> N * fac(N-1).
</pre>
<p>If factorial is called with a 0 (zero) for an argument, the first
argument list will be chosen and the value of the factorial function
will be 1. Otherwise, the value returned will be calculated by a
recursive call to factorial.</p>
<h2>FlexMock and Erlang</h2>
<p>While playing around with FlexMock the other day, I realized that it
does parameter matching, much like Erlang, when deciding what mock
method to call. So I started wondering if you could write Erlang-like
function definitions in FlexMock.</p>
<p>Here’s the result.</p>
<pre>
mock = flexmock('fact')
mock.should_receive(:factorial).with(0).and_return(1)
mock.should_receive(:factorial).with(Integer).
and_return { |n| n * mock.factorial(n-1) }
</pre>
<p>Ok, that was fun. But let’s not start building entire systems using
nothing but FlexMock.</p> FlexMock 0.6.4 Release <p style="padding-left:3em;"><em>New Release of FlexMock</em></p>
<h2>FlexMock 0.6.4 Release</h2>
<p>Just wanted to drop a quick note that a new version of FlexMock is now
available.</p>
<p>There are two nice enhancements and a minor bug fix in this version.</p>
The first enhancement is for mocking ActiveRecord objects. The folks
at EdgeCase use a mockmodel() method for the RSpec mock that returns a
mock that has some common ActiveRecord methods mocked (stubbed) with
some reasonable values. This make is a bit more convenient when
mocking Rails models. FlexMock now supports this natively, just say
<code>flexmock(:model, YourRailsModel)</code> to create a mock object
that mimics a YourRailsModel object.
<p>The second enhancement is in regard to the <a href="http://onestepback.org/index.cgi/Tech/Ruby/FlexMockReturns.red">What Should
flexmock(real_obj)
Return?</a>
question I blogged about last May. I asked the question: What should
flexmock(real_obj) return, the real object or the mock object?
Someone had suggested returning the real object when flexmock() is
given a block. There was some positive response to that, so that was
included in the FlexMock release.</p>
<p>But after several months of using it, I found it difficult to remember
which version of flexmock() returned what. At one point I found
myself caling flexmock() with an empty block, just to get the real
object back. That was madness.</p>
<p>So starting with release 0.6.4, flexmock will always return the real
object. This is the best of both worlds, but it comes with a small
price. Real objects partially mocked by FlexMode will now be enhanced
with some extra methods, just enough methods so that addition mock
behavior can be added to it. For example, <code>should_receive</code>
is added to the partially mocked real object. This pollutes the
method namespace for an object, but the result is much simplier for
the programmer to use. If you <strong>really</strong> want to avoid method namespace
pollution, there is a :safe mode offered. Read the docs for all the
gory details.</p>
<h2>By The Way, If You Grabbed Version 0.6.3 …</h2>
<p>If you are one of the handful of people that downloaded verion 0.6.3
yesterday, then go ahead and grab 0.6.4. The only difference is in
the <span class="caps">API</span> for mocking ActiveRecord models. After using it for a bit, I
realized that the <span class="caps">API</span> could be improved, hence version 0.6.4. Sorry
about that.</p> Using FlexMock to Test Computational Fluid Dynamics Code <p style="padding-left:3em;"><em>This is a fun example of using FlexMock</em></p>
<h2>Andrew Sweeney Asks:</h2>
<p>Andrew Sweeney emailed me with the following question:</p>
<p style="padding-left:3em;"><em>I am currently working on a ruby project in which I think
flexmock would be a good fit for unit testing. I have read the
documentation and gone over the examples however fail to wrap my head
around how to apply flexmock to my own app. I was hoping that you
could give me some guidence and get me started or point me in the
right direction. </em></p>
<p>You can find his original source code <a href="http://wikis.onestepback.org/OSB/page/show/OriginalF3DQueueCode">here</a>.</p>
<p>I thought his problem was interesting enough to write it up as an
example of using FlexMock. Andrew and his mentor, <a href="http://www.workingwithrails.com/person/6007-bil-kleb">Bil
Kleb</a> gave
permission for me to reproduce the code in my blog. The F3DQueue
class is part of a <a href="http://fun3d.larc.nasa.gov">Computational Fluid
Dynamics</a> project
(<a href="http://fun3d.larc.nasa.gov">http://fun3d.larc.nasa.gov</a>) at <span class="caps">NASA</span>.</p>
<h2>Quick Code Review</h2>
<p>The F3DQueue class is small, so there’s not a lot of code we need to
wade through. We see it uses a second class named AutoF3D, but the
only clues we have to what AutoF3D might do are the four method calls
on the “job” object in the <ins>run</ins> method.</p>
<p>It looks like the main interface to the queue object is the
<ins>add_to_queue</ins> method. There is a thread started that pulls jobs
(i.e. AutoF3D objects) from the queue and processes them in turn.
There is some server delays built into the system. I presume that
Computational Fluid Dynamics is, ummm, computationally complex and the
delays are just there to make sure the workload does eat up <em>all</em> the
<span class="caps">CPU</span> time on the server.</p>
<h2>Starting Testing</h2>
<p>When writing new code, I always like to approach it in a Test-First
manner. Because I won’t write solution code without a test that
forces me to write it, I have a high confidence that the code is well
covered with tests.</p>
<p>Unfortunately, dealing with legacy code means that the code is already
written and the test-first approach won’t work. That’s ok, I have a
little trick that I use. Just comment out the bodies of all the
methods in the class you are about to test. Then write the tests that
force you to <em>uncomment</em> the code. Just uncomment only enought to get
the tests to pass, don’t uncomment anything you don’t have to. You
have enough tests when all the code has been uncommented. The
technique is <em>almost</em> as good as doing real test-first.</p>
<h2>The Commented Out Version</h2>
<p><a href="http://wikis.onestepback.org/OSB/page/show/CommentedF3DQueueCode">Here</a>
is the code base as I started the test.</p>
<h2>An Existence Test</h2>
<p>I almost always start out with an existence test. Existence tests
basically prove the proper files are included and the object can be
created. Normally I delete these after a few tests have been written.
But I left this one in for an example.</p>
<pre class="testcode">
def test_initial_conditions
q = F3DQueue.new
assert_not_nil q
end
</pre>
<p>Nothing really exciting here. Let’s move on …</p>
<h2>Proving <span class="caps">FIFO</span> Queue Order</h2>
<p>The first thing I want to prove is that items put into the queue are
removed in <span class="caps">FIFO</span> order. Since <ins>add_to_queue</ins> creates a AutoF3D object,
I mock out the <ins>new</ins> method on the class object and tell FlexMock to
expect <ins>new</ins> to be called twice. Once with :a, :b, and :c as
parameters, then again with :x, :y, :z paramters. Each invocation of
<ins>new</ins> will return a different symbol (:first and :second) so we can
easily test the items are pulled off the queue in <span class="caps">FIFO</span> order.</p>
<p>Notice that I pass in simple symbols for the arguments to
<ins>add_to_queue</ins>. Our code doesn’t interpret the values of the
arguments, they are merely passed directly to the AutoF3D constructor.
All we do is verify that the AutoF3D (mocked) constructor does indeed
receive the arguments we pass in.</p>
<p>Here’s the test:</p>
<pre class="testcode">
def test_adding_to_queue_is_removed_in_fifo_order
flexmock(AutoF3D).should_receive(:new).once.with(:a, :b, :c).and_return(:first).ordered
flexmock(AutoF3D).should_receive(:new).once.with(:x, :y, :z).and_return(:second).ordered
q = F3DQueue.new
q.add_to_queue(:a, :b, :c)
q.add_to_queue(:x, :y, :z)
assert_equal :first, q.remove_from_queue
assert_equal :second, q.remove_from_queue
end
</pre>
<p>This test caused three changes. First, the <ins>add_to_queue</ins> method
needed lines uncommented:</p>
<pre class="rubycode">
def add_to_queue(modelLoc, params, gridFile)
autoF3D = AutoF3D.new(modelLoc, params, gridFile)
@queue.push autoF3D
# $log.info 'Request added to queue'
end
</pre>
<p>(Notice I didn’t uncomment the log. The logger is not needed to pass
the test, and doesn’t contribute to the actual functionality of the
method. I will not be testing the logger in the for the purposes of
this article.)</p>
<p>Also the <ins>remove_from_queue</ins> needed its body uncommented:</p>
<pre class="rubycode">
def remove_from_queue
@queue.pop
end
</pre>
<p>And finally, the initializer code needed to create the queue array:</p>
<pre class="rubycode">
def initialize
@queue = []
# Thread.new{ process }
end
</pre>
<p>Notice that the <ins>Thread.new</ins> line is left commented. We will deal
with that in a bit.</p>
<p>So now we run the test:</p>
<pre class="shell">
$ ruby test_f3dqueue.rb
Started
F.
Finished in 0.010184 seconds.
1) Failure:
test_adding_to_queue_is_removed_in_fifo_order(TestF3DQueue) [test_f3dqueue.rb:23]:
<:first> expected but was
<:second>.
2 tests, 2 assertions, 1 failures, 0 errors
</pre>
<p>Oops! This test uncovered the first bug. The code as written has
stack behavior (i.e. <span class="caps">LIFO</span>). The naming seems to indicate that we want <span class="caps">FIFO</span>.</p>
<p>No problem. That’s an easy fix.</p>
<pre class="rubycode">
def remove_from_queue
@queue.shift
end
</pre>
<p>Now the tests run clean:</p>
<pre class="shell">
$ ruby test_f3dqueue.rb
Started
..
Finished in 0.001925 seconds.
2 tests, 3 assertions, 0 failures, 0 errors
</pre>
<h2>Proving that Running a Job Works</h2>
<p>Now when I run a job, I need to show that the proper four methods are
called once each and in the proper order. This is very straight
forward using FlexMock.</p>
<pre class="testcode">
def test_running_a_job_will_call_the_right_stuff_in_the_right_order
job = flexmock("job")
job.should_receive(:generate_geometry_and_grid).once.ordered
job.should_receive(:partition_grid_and_initialize_flow).once.ordered
job.should_receive(:run_flow_solver).once.ordered
job.should_receive(:post_process_solution).once.ordered
q = F3DQueue.new
q.run(job)
end
</pre>
<p>Uncommenting the body of <ins>run</ins> is all that is needed here:</p>
<pre class="rubycode">
def run( job )
# $log.info 'Request being processed'
job.generate_geometry_and_grid
# $log.info 'Created Geometry'
job.partition_grid_and_initialize_flow
# $log.info 'Partitioned Grid'
job.run_flow_solver
# $log.info 'Flow Solver Completed'
job.post_process_solution
# $log.info 'Post process Completed'
# $log.info 'Request completed'
end
</pre>
<p>Test are now showing:</p>
<pre class="shell">
3 tests, 3 assertions, 0 failures, 0 errors
</pre>
<h2>Processing an Empty Queue</h2>
<p>Ok, now it gets interesting. I want to show that attempting to
process a job when the queue is empty will cause the process to sleep
for the check queue interval.</p>
<p>This is one spot where I changed the code to make it easier to test.
It is difficult to test endless loops in unit tests (it tends to make
the tests run a <em>bit</em> long), so I broke out the logic for a single
pass through the loop into a method called <ins>process_one_job</ins>. We can
then test this logic without dealing with the looping at the same
time.</p>
<p>Note: It is possible to test endless loops and an example will be
given below. But it is slightly tricky and this allows us to
concentrate on proving the logic.</p>
<p>If there are no jobs to be processed, then all the code should do is
sleep for a particular amount of time. We will locally mock out the
<ins>sleep</ins> method on the queue object and insist that it will be called
exactly once with the expected interval.</p>
<pre class="testcode">
def test_processing_with_no_jobs_will_sleep_the_check_interval
q = F3DQueue.new
flexmock(q).should_receive(:sleep).once.with(F3DQueue::CHECK_QUEUE_INTERVAL)
q.process_one_job
end
</pre>
<p>Here is <ins>process_one_job</ins> with just two lines uncommented so that the
test will pass.</p>
<pre class="rubycode">
def process_one_job
# execution_attempts = 0
job = remove_from_queue
# begin
# if job
# run job
# execution_attempts = 0
# sleep SERVER_RECOVERY_TIME
# else
sleep CHECK_QUEUE_INTERVAL
# end
# rescue
# $log.warn 'An error occurred during execution'
# $log.warn $ERROR_INFO
# $log.debug $ERROR_POSITION
# sleep SERVER_RECOVERY_TIME
# if execution_attempts > MAX_EXECUTION_ATTEMPTS
# $log.error 'Too many failed execution_attempts: aborting'
# raise
# else
# execution_attempts += 1
# retry
# end
# end
end
</pre>
<p>There’s a lot of code still left commented in that method. Now we
need a test to force us to uncomment more code.</p>
<h2>Handling a Single Job</h2>
<p>Ok, now what happens when a single job is in the queue. We will
assume the happy path (i.e. no exceptions) so we expect <ins>run</ins> to be
called with the queued object, and then a sleep with the recovery
interval.</p>
<p>A couple of things to note. First, we mock out AutoF3D again so that
when we request something added to the queue, we control what kind of
object is returned. We <em>could</em> return a mock object and then mock out
the four methods that <ins>run</ins> will be calling.</p>
<p>However, I chose a slightly different approach. AutoF3D is mocked so
that it returns a simple symbol. Then I mock out the <ins>run</ins> method to
do nothing (but it is expected to be called once). This is slightly
controversial because I am actually mocking a method on the object
under test. But the run method is fairly simple, and we know that
<ins>run</ins> works because of our previous test, so in the end we get clearer
and simpler code.</p>
<p>Also note that the <ins>run</ins> and <ins>sleep</ins> methods mocks are ordered. This
means <ins>run</ins> will be called first, then <ins>sleep</ins>.</p>
<pre class="testcode">
def test_processing_with_a_single_job_will_run_the_job_and_pause_for_recovery
q = F3DQueue.new
flexmock(AutoF3D).should_receive(:new).once.and_return(:job)
flexmock(q).should_receive(:run).once.with(:job).ordered
flexmock(q).should_receive(:sleep).once.with(F3DQueue::SERVER_RECOVERY_TIME).ordered
q.add_to_queue(:a, :b, :c)
q.process_one_job
end
</pre>
<p>Now we get to uncomment even more lines in <ins>process_one_job</ins>.</p>
<pre class="rubycode">
def process_one_job
# execution_attempts = 0
job = remove_from_queue
# begin
if job
run job
# execution_attempts = 0
sleep SERVER_RECOVERY_TIME
else
sleep CHECK_QUEUE_INTERVAL
end
# rescue
# $log.warn 'An error occurred during execution'
# $log.warn $ERROR_INFO
# $log.debug $ERROR_POSITION
# sleep SERVER_RECOVERY_TIME
# if execution_attempts > MAX_EXECUTION_ATTEMPTS
# $log.error 'Too many failed execution_attempts: aborting'
# raise
# else
# execution_attempts += 1
# retry
# end
# end
end
</pre>
<p>That just leaves the error handling code to be uncommented. So that will be next.</p>
<h2> Handling a Job With Errors</h2>
<p>Now we want to test the case where processing a job will return an
exception. This test exercise the exception recovery code in the
original code base. The technique is similar to the last test, but
this time we specify two mock calls for <ins>run</ins>. The first time <ins>run</ins>
will return an exception. The second time it is called, it will
complete normally.</p>
<p>Notice that we have ordered <ins>run</ins> and <ins>sleep</ins> so that they interleave
execution with each other.</p>
<pre class="testcode">
def test_if_a_job_fails_retry_after_recovery_time
q = F3DQueue.new
flexmock(AutoF3D).should_receive(:new).once.and_return(:job)
flexmock(q).should_receive(:run).once.with(:job).and_raise(RuntimeError).ordered
flexmock(q).should_receive(:sleep).once.with(F3DQueue::SERVER_RECOVERY_TIME).ordered
flexmock(q).should_receive(:run).once.with(:job).ordered
flexmock(q).should_receive(:sleep).once.with(F3DQueue::SERVER_RECOVERY_TIME).ordered
q.add_to_queue(:a, :b, :c)
q.process_one_job
end
</pre>
<p>I was showing this test code to one of my coworkers and they were a
little surprised that the second expectation on <ins>run</ins> didn’t override
the first expectation. FlexMock is explicitly designed to allow you
to stack expectations like this. When searching for an expectation
during mocking, FlexMock will use the first one matching one if finds.
When an expectation has been used its designated number of times (in
the above test, the <ins>once</ins> method designates that the expectation
should only be used once), FlexMock will begin to use matching
expectations that are defined later.</p>
<p>The upshot is this is that it is easy to define mock behavior for
multiple calls to the same method.</p>
<p>Here’s the latest <ins>process_one_job</ins> method with some more lines
uncommented. We are getting close to the end with this one.</p>
<pre class="rubycode">
def process_one_job
# execution_attempts = 0
job = remove_from_queue
begin
if job
run job
# execution_attempts = 0
sleep SERVER_RECOVERY_TIME
else
sleep CHECK_QUEUE_INTERVAL
end
rescue
# $log.warn 'An error occurred during execution'
# $log.warn $ERROR_INFO
# $log.debug $ERROR_POSITION
sleep SERVER_RECOVERY_TIME
# if execution_attempts > MAX_EXECUTION_ATTEMPTS
# $log.error 'Too many failed execution_attempts: aborting'
# raise
# else
# execution_attempts += 1
retry
# end
end
end
</pre>
<h2>Processing Jobs that Continually Fail</h2>
<p>Finally we test the case where the job will continually raise an
exception until the error recovery code gives up and passes the
exception on to the caller. I didn’t bother ordering the
run/sleep calls here, making it easy to just specify that each are
called four times. I believe that the previous test adequately
specified interleaving.</p>
<p>I used a RuntimeError for my testing. If you have a specific
error in mind, you might want to test explicitly for it.
Generally raising the most general error you intend to handle is a
good way of testing the boundry conditions on your rescue clause.</p>
<pre class="testcode">
def test_too_many_failures_will_pass_along_exception
q = F3DQueue.new
flexmock(AutoF3D).should_receive(:new).once.and_return(:job)
flexmock(q).should_receive(:run).with(:job).and_raise(RuntimeError.new("XYZZY")).times(4)
flexmock(q).should_receive(:sleep).with(F3DQueue::SERVER_RECOVERY_TIME).times(4)
q.add_to_queue(:a, :b, :c)
ex = assert_raise RuntimeError do
q.process_one_job
end
assert_equal "XYZZY", ex.message
end
</pre>
<p>Note that the exception needs to be raised four times. I suspect this
is a bug in the error handling logic. I left the logic as is and
just made sure the test will pass. The code base specifies a retry
count of “2”. This seems to imply that we try <ins>run</ins> twice, or perhaps
three times (if the initail attempt doesn’t count as a retry). In any
case, four times seems too much.</p>
<p>So, here is the code for <ins>process_one_job</ins> with most of its lines
uncommented.</p>
<pre class="rubycode">
def process_one_job
execution_attempts = 0
job = remove_from_queue
begin
if job
run job
# execution_attempts = 0
sleep SERVER_RECOVERY_TIME
else
sleep CHECK_QUEUE_INTERVAL
end
rescue
# $log.warn 'An error occurred during execution'
# $log.warn $ERROR_INFO
# $log.debug $ERROR_POSITION
sleep SERVER_RECOVERY_TIME
if execution_attempts > MAX_EXECUTION_ATTEMPTS
# $log.error 'Too many failed execution_attempts: aborting'
raise
else
execution_attempts += 1
retry
end
end
end
</pre>
<p>Again note that this test surfaced a (rather minor) bug. There is an
extra assignment that clears the execution attempt counter after a
successful run of <ins>job</ins>. Since a successful run will exit the loop,
clearing it has no effect (unless it is the sleep command that fails,
that would be an interesting test scenario).</p>
<p>Since we haven’t shown the test results for a while, here’s how we
stand at this point:</p>
<pre class="shell">
7 tests, 5 assertions, 0 failures, 0 errors
</pre>
<h2>Processing Multiple Jobs</h2>
<p>Now we know that we can handle a single job successfully. Now let’s
make sure that we can handle multiple jobs. Remember that we broke
<ins>process</ins> into two methods: <ins>process_one_job</ins> and a much shorter
<ins>process</ins> that will call <ins>process_one_job</ins> in a loop.</p>
<p>Here’s what the original <ins>process</ins> method is looking like at the
moment:</p>
<pre class="rubycode">
def process
# loop do
# end
end
</pre>
<p>We pulled out its guts and left the still commented loop there. We
haven’t even bothered to have it call <ins>process_one_job</ins> yet. So let’s
write a test that will force us to fix that.</p>
<p>We will just mock out process_one_job so that it must be called 10
times. On the eleventh call it throws a symbol that we catch in the
test. Throwing a symbol is the trick that breaks us out of the
infinite loop. By throwing a symbol (rather than raising an error),
we don’t interact with the error handling logic of the code under
test.</p>
<p>This is actually the trick refereced earlier. By breaking the body of
the loop into a separate method, we only have to use this trick once
rather than on each of the process job tests.</p>
<pre class="testcode">
def test_process_calls_process_one_job_in_a_loop
q = F3DQueue.new
flexmock(q).should_receive(:process_one_job).times(10)
flexmock(q).should_receive(:process_one_job).and_return { throw :done }
assert_throws(:done) do
q.process
end
end
</pre>
<p>To get this to pass, we implement the <ins>process</ins> method as follows:</p>
<pre class="rubycode">
def process
loop do
process_one_job
end
end
</pre>
<h2>Threading Issues</h2>
<p>Finally we need to make sure a thread is started. Here is another
place I changed the code to make testing easier. The original
code base started a thread in the initializer of the object. This
means that <strong>every</strong> F3DQueue object ran in its own thread. This
would means every test would have to deal with multithread issues.
Yuck!</p>
<p>I changed the code so that a thread is started only when
explicitly calling the start method. I like this better for real
object anyways. Although it is an extra step, it gives you more
control about when the threads are started. If you really want to
start a thread at object creation, you can just say:</p>
<pre><code>queue = F3DQueue.new.start</code></pre>
<p>Since I really don’t want to start a Thread in the test (I just
want to make sure that the Thread.new method is called), I mock
out Thread.new so that it must be called once and when called will
execute the given block.</p>
<p>I then mock out the process method to that it must be called once.
The combination of these two mocks will ensure that <ins>start</ins> will
start a new thread that calls <ins>process</ins>.</p>
<p>And finally, I ensure that the return value of <ins>start</ins> will be the
queue object. This makes sure that the F3DQueue.new.start idiom
works.</p>
<pre class="testcode">
def test_start_will_start_a_process_thread
q = F3DQueue.new
flexmock("thread", Thread).should_receive(:new).with(Proc).once.
and_return { |block| block.call }
flexmock(q).should_receive(:process).once
return_value = q.start
assert_equal q, return_value
end
</pre>
<p>And is is the little <ins>start</ins> method that needed to be written for the
test. The Thread.new line is moved from the <ins>initialize</ins> method to
here.</p>
<pre class="rubycode">
def start
Thread.new do process end
self
end
</pre>
<p>Here’s our final test run:</p>
<pre class="shell">
9 tests, 7 assertions, 0 failures, 0 errors
</pre>
<h2>Code Coverage</h2>
<p>We know that <span class="caps">TDD</span> gives pretty code code coverage stats out of the box.
How did our “Comment-out First” approach do with regards to code
coverage?</p>
<p>Here is the RCov report:</p>
<pre class="shell">
+----------------------------------------------------+-------+-------+--------+
| File | Lines | LOC | COV |
+----------------------------------------------------+-------+-------+--------+
|AutoF3D.rb | 5 | 2 | 100.0% |
|f3dqueue.rb | 82 | 53 | 100.0% |
|test_f3dqueue.rb | 100 | 76 | 100.0% |
+----------------------------------------------------+-------+-------+--------+
|Total | 187 | 131 | 100.0% |
+----------------------------------------------------+-------+-------+--------+
100.0% 3 file(s) 187 Lines 131 LOC
</pre>
<p>Wow! 100% on the first try.</p>
<h2>Final Code Samples</h2>
<p>You can find the final versions of the F3DQueue object and its tests here:</p>
<ul>
<li><a href="http://wikis.onestepback.org/OSB/page/show/FinalF3DQueueCode">F3DQueue Code</a></li>
<li><a href="http://wikis.onestepback.org/OSB/page/show/FinalF3DQueueTestCode">F3DQueue Test Code</a></li>
</ul>
<h2>Future Directions</h2>
<p>Now that the F3DQueue object is well testing, it is time to take a
step back and think about the overall design of the class. There are a couple of things
that stick out in my mind about this code.</p>
<h3>(1) First Item</h3>
<p>We did a lot of mocking on the F3DQueue object itself while it was
being testing. Although a valid technique, you must be careful so
that you don’t end up just testing your own mocks. What it <em>does</em>
indicate is that the object you are testing might be trying to do too
many things. Perhaps the class needs to be broken up into small
classes, or perhaps some functionality needs to move into other
classes.</p>
<p>With this in mind, the <ins>run</ins> method seems to know an awful lot about
the workings of an Auto3D job object. It seems a bit out of place.
Why don’t we move the <ins>run</ins> method to the job itself. Moving <ins>run</ins>
into the Auto3D job object would allow us to write the following code
fragment (in the <ins>process_one_job</ins> method):</p>
<pre class="rubycode">
...
job = remove_from_queue
begin
if job
job.run # was: run job
sleep SERVER_RECOVERY_TIME
...
</pre>
<p>Now, our queue class is one method shorter and is just concerned with
the scheduling of the jobs and not the details of running the job
itself. This is good …</p>
<p>Except for the following little piece of code, which leads us into the
second thing that bothered me:</p>
<pre class="rubycode">
def add_to_queue(modelLoc, params, gridFile)
autoF3D = AutoF3D.new(modelLoc, params, gridFile)
@queue.push autoF3D
end
</pre>
<h3>(2) Second Item</h3>
<p>Here we have direct knowledge of the AutoF3D class. If we remove the
reference to AutoF3D, then our queue will suddenly become much more
general, and usable in situations where we might want to process a
different kind of job.</p>
<p>I would recommend changing the above code to:</p>
<pre class="rubycode">
def add_to_queue(job)
@queue.push job
end
</pre>
<p>This does mean that adding a job to the queue would now have to create
the job object explicitly. So, instead of:</p>
<pre>
queue.add_to_queue(loc, param, grid)
</pre>
<p>you would have to write:</p>
<pre>
queue.add_to_queue(new AutoF3D.new(loc, param, grid))
</pre>
<p>If you don’t like to manually create an AutoF3D object all the time
(and I don’t), then the following solution is an easy fix to that:</p>
<pre class="rubycode">
queue = F3DQueue.new
def queue.add_job(loc, params, grid)
add_to_queue(AutoF3D.new(loc, params, grid))
end
</pre>
<p>The more traditionally minded of us might want to just subclass the
F3DQueue class and add the <ins>add_job</ins> method in the subclass rather
than in the singleton class. That works too. Either way, it is easy
to do.</p>
<h2>Recap</h2>
<p>I hope this was useful for you. Here is a recap of some of the
important ideas from this exercise:</p>
<ul>
<li>Comment-First is not a bad way to handle legacy code.</li>
</ul>
<ul>
<li>Test scenarios, not methods. Note that I didn’t just pick a method
in F3DQueue and write a single test for it. I choose scenarios that
would exercise different sections of the code base. Start with the
simple (e.g. a Job that Doesn’t Fail). Then pick increasing harder
scenarios (e.g. “a Job that Fails Once”, “a Job that Fails Multiple
Times”).</li>
</ul>
<ul>
<li>Don’t be afraid to refactor to make testing easier. Breaking out
<ins>process_one_job</ins> was a great idea that not only made testing much
easier, but made the code easier to read.</li>
</ul>
<ul>
<li>The “Use Symbols as Cheap Mocks” is an idea I stole from Stu
Halloway in his “Refactoring of the Week” presentation. If a method
takes arguments that you don’t want to deal with, try passing in
symbols. If the arguments aren’t used, the symbols work great. If
an argument is actually used, the error message will identify the
symbol at fault. At that point, just replace the symbol with the
appropriate mock. This technique save you lots of time and makes
the tests easier to read.</li>
</ul>
<ul>
<li>If you want to break out of an infinite loop in the code under test,
throw a symbol from your mocks and catch it in your test. This
generally doesn’t interfere with any exception handling code in your
code under test.</li>
</ul>
<ul>
<li>Always take a step back and look for ways of improving the code. A
well tested module is fairly easy to change with confidence. Don’t
be afraid to improve things.</li>
</ul>
<h2>More Samples</h2>
<p>Do you have a bit of code that you are having trouble testing? If so,
go ahead and send it to me. If your code is interesting enough, I’ll
take a look at it and post the results here (so don’t send anything
you aren’t willing to see published in this blog). I can’t look at
everything, but I’ll try to find some interesting examples.</p> Dependency Injection in One Sentence <p style="padding-left:3em;"><em>Condensing thoughts down to one sentence …</em></p>
<h2>In One Sentence …</h2>
<p>So I was asked this question in IM today:</p>
<p style="padding-left:3em;"><em>If you had one sentence to explain to a Java programmer why
Dependency Injection is rarely necessary in Ruby, what would it
be?</em></p>
<p>Wow, one sentence! After some thought, here’s what I sent back:</p>
<p style="padding-left:3em;"><em>Dependency injection provides vital flexibility in Java and
unneeded overhead in Ruby.</em></p>
<p>Anyone have other suggestions?</p> What Should flexmock(real_obj) Return? <p style="padding-left:3em;"><em>Bruce Williams asked this question at RailsConf, and I
am soliciting feedback.</em></p>
<h2>Background</h2>
<p>First, a little background. There are two possibilities when calling <tt>flexmock()</tt>. First, you are creating a full mock object:</p>
<pre>
# Example 1
mock = flexmock("description")
mock.should_receive(...)
</pre>
<p>A full mock fulfills two roles: (1) it is a target for
<tt>should_receive</tt> to define expectations, and (2) it is a target for
normal domain messages when testing.</p>
<p>The other possibility is that you are creating a partial mock (i.e. a
regular Ruby object with just a few mocked methods):</p>
<pre>
# Example 2
real_obj = RealObject.new
proxy_mock = flexmock(real_obj, "description")
proxy_mock.should_receive(...)
</pre>
<p>The object returned from the <tt>flexmock()</tt> method is actually a proxy
object that can accept <tt>should_receive()</tt> messages to define the
expectations, but does not handle normal domain messages. After all, we have a real object that that handles domain messages.</p>
<h2>Partial Mocks</h2>
<p>It is clear that when creating a partial mock using the non-block form of
flexmock(real_obj), we must return the proxy, else there would be no way to
add expectations. But the return value for the block form of flexmock is
not so clear.</p>
<p>Consider the following code:</p>
<pre>
# Example 3
real_obj = RealObject.new
result = flexmock(real_obj) do |mock|
mock.should_receive(...)
end
</pre>
<p>Here the proxy object is passed as the block argument. All the expectation
setup is done within the block. It is <em>very</em> tempting to write this code
as:</p>
<pre>
# Example 4
result = flexmock(RealObject.new) do |mock|
mock.should_receive(...)
end
</pre>
<p>But here is the problem: in example 4 we no longer have a reference to the
RealObject instance. The <tt>flexmock()</tt> method returns the proxy
object, not the real object; just as it does in the non-block form.</p>
<h2>Bruce’s Suggestions</h2>
<p>Bruce suggested changing the block version of flexmock() to go ahead and
return the real object. Since the proxy is used in the block, there is no
real need for it outside the function. And, I will admit, example 4 is
short and relatively clear, especially with those familiar with the
<tt>returning</tt> idiom used in Rails.</p>
<h2>The Dilemma</h2>
<p>So here is my dilemma. Changing FlexMock so that example 4 works properly
is attractive. And I suspect that the return value of flexmock(real_obj) is
not ever used in a significant way in existing code, so backwards
compatibility should be be only a minor concern. However, changing the
return object based on whether or not the method has a block just seems …
<em>wrong</em>.</p>
<p>There is precedent for this. In the standard Ruby libraries
<tt>open(fn)</tt> and <tt>open(fn) { ... }</tt> return different things (an
open file for the former and the value of the block for the latter). I’ve
never had problems with this behavior in open, so perhaps I am just being
over sensitive here.</p>
<p>I told Bruce I would blog the issue and consider the feedback received. So
let me know what you think. Should <tt>flexmock()</tt> be modified to
return the real_object when defining partial mocks using the block form?</p>
<p>You can email me (jim@weirichhouse.org) or add a comment using the comments
link below.</p> FlexMock 0.6.0 Released <em>FlexMock version 0.6.0 was just released over the weekend. You can read
the release announcement below for all the new features and
enhancements.</em>
<hr size="2"></hr><p>
FlexMock is a flexible mocking library for use in unit testing and behavior
specification in Ruby. Version 0.6.0 introduces a number of API
enhancements to make testing with mocks even easier than before.
</p>
<h2>New in 0.6.0</h2>
<ul>
<li>Better integration with Test::Unit (no need to explicitly include
FlexMock::TestCase).
</li>
<li>Integration with RSpec (version 0.9.0 or later of RSpec is required).
</li>
<li>The <tt>flexmock</tt> method will now create both regular mocks and partial
mocks.
<pre>
flexmock() # => a full mock
flexmock(person) # => a partial mock based on person
</pre>
<p>
(<tt>flexstub</tt> is still included for backwards compatibility).
</p>
</li>
<li>Quick and simple mocks my now be created using an expectation hash. For
example:
<pre>
flexmock(:foo => 10, :bar => "Hello")
</pre>
<p>
will create a mock with two methods, :foo and :bar,defined. :foo will
return 10 when invoked, and :bar will return "Hello".
</p>
</li>
<li>The <tt>should_receive</tt> method will now allow multiple methods (with
the same constraints) be defined in a single call. For example, the
following declares that both :read and :write need to be called at least
one time each on the mock object.
<pre>
flexmock.should_receive(:read, :write).at_least.once
</pre>
</li>
<li><tt>should_recieve</tt> now will allow expectation hashes as arguments.
This is similar to the list of methods, but allows each defined method to
have its own return value.
<pre>
flexmock.should_receive(:name => "John", :age => 32)
</pre>
</li>
<li>In addition to using a block for defining constrains, constraints may now
be applied directly to the return value of <tt>new_instances</tt>. Combined
with the expectation hashes supported by <tt>should_receive</tt>, simple
mocking scenarios have become much more succinct. For example:
<pre>
flexmock(Person).new_instances.should_receive(:name => "John", :age => 32)
</pre>
</li>
<li>Improved implementation, allowing for more flexible use and greater
consistency between full mock and partial mocks.
</li>
<li>Version 0.6.0 also includes a fix for an incompatibility with some older
versions of RCov. The FlexMock Rakefile now includes a RCov task (and we
have 100% code coverage).
</li>
</ul>
<h2>What is FlexMock?</h2>
<p>
FlexMock is a flexible framework for creating mock object for testing. When
running unit tests, it is often desirable to use isolate the objects being
tested from the "real world" by having them interact with
simplified test objects. Sometimes these test objects simply return values
when called, other times they verify that certain methods were called with
particular arguments in a particular order.
</p>
<p>
FlexMock makes creating these test objects easy.
</p>
<h3>Features</h3>
<ul>
<li>Easy integration with both Test::Unit and RSpec. Mocks created with the
flexmock method are automatically verified at the end of the test or
example.
</li>
<li>A fluent interface that allows mock behavior to be specified very easily.
</li>
<li>A "record mode" where an existing implementation can record its
interaction with a mock for later validation against a new implementation.
</li>
<li>Easy mocking of individual methods in existing, non-mock objects.
</li>
<li>The ability to cause classes to instantiate test instances (instead of real
instances) for the duration of a test.
</li>
</ul>
<h3>Example</h3>
<p>
Suppose you had a Dog object that wagged a tail when it was happy.
Something like this:
</p>
<pre>
class Dog
def initialize(a_tail)
@tail = a_tail
end
def happy
@tail.wag
end
end
</pre>
<p>
To test the <tt>Dog</tt> class without a real <tt>Tail</tt> object (perhaps
because real <tt>Tail</tt> objects activate servos in some robotic
equipment), you can do something like this:
</p>
<p>
require ‘test/unit’ require ‘flexmock/test_unit‘
</p>
<pre>
class TestDog < Test::Unit::TestCase
def test_dog_wags_tail_when_happy
tail = flexmock("tail")
tail.should_receive(:wag).once
dog = Dog.new(tail)
dog.happy
end
end
</pre>
<p>
FlexMock will automatically verify that the mocked tail object received the
message <tt>wag</tt> exactly one time. If it doesn’t, the test will
not pass.
</p>
<p>
See the FlexMock documentation at <a
href="http://flexmock.rubyforge.org">flexmock.rubyforge.org</a> for details
on specifying arguments and return values on mocked methods, as well as a
simple technique for mocking tail objects when the Dog class creates the
tail objects directly.
</p>
<h2>Availability</h2>
<p>
You can make sure you have the latest version with a quick RubyGems
command:
</p>
<pre>
gem install flexmock (you may need root/admin privileges)
</pre>
<p>
Otherwise, you can get it from the more traditional places:
</p>
<table>
<tr><td valign="top">Download:</td><td><a
href="http://rubyforge.org/project/showfiles.php?group_id=170">rubyforge.org/project/showfiles.php?group_id=170</a>
</td></tr>
</table>
<p>
You will find documentation at: <a
href="http://flexmock.rubyforge.org">flexmock.rubyforge.org</a>.
</p>
<p>
— Jim Weirich
</p>
Extended FlexMock Example Using Google4R <em> I recently helped a friend use FlexMock to do some testing on code
that was written ot use the Google4R checkout APIs. I thought it might be
interesting to share some of the details here. Note that this code uses the
recently released FlexMock version 0.6.0. </em>
<p>
Google4R is a simple Ruby wrapper around the Google APIs. In this extended
example, we will use FlexMock to test software that uses the Google APIs,
without every communicating with Google itself.
</p>
<h2>Purchase.rb</h2>
<p>
Here is the bit of code that we will be testing…
</p>
<pre>
require 'google4r/checkout'
require 'item'
class Purchase
def initialize(config)
@frontend = Frontend.new(config)
@frontend.tax_table_factory = TaxTableFactory.new
end
# Purchase the +quantity+ items identified by +item_id+. Return the
# confirmation page URL.
def purchase(item_id, quantity=1)
item = Item.find(item_id)
checkout = @frontend.create_checkout_command
checkout.cart.create_item do |cart_item|
cart_item.name = item.name
cart_item.description = item.description
cart_item.unit_price = item.unit_price
cart_item.quantity = quantity
end
response = checkout.send_to_google_checkout
response.redirect_url
end
end
</pre>
<p>
<tt>FrontEnd</tt> is a Google4R class that provides a lot of the front end
work for talking to the Google APIs. The config object given to the
Purchase initializer is simply a hash of values defining the merchant_id,
merchant_key and sandbox flag. To use the real Google checkout APIs, you
will need to obtains a merchant id and key from Google. Since we will be
mocking the Google interaction, we can use dummy values in our test.
</p>
<p>
The tax table factory is required by the Google4R software. We provide the
following simplified one. Read the Google API documents for more
information.
</p>
<pre>
class TestTaxTableFactory
def effective_tax_tables_at(time)
tax_free_table = TaxTable.new(false)
tax_free_table.name = "default table"
tax_free_table.create_rule do |rule|
rule.area = UsCountryArea.new(UsCountryArea::ALL)
rule.rate = 0.0
end
return [tax_free_table]
end
end
</pre>
<p>
<tt>Item</tt> is simply an ActiveRecord class that we are using to hold our
purchase item information. It should respond to the <tt>name</tt>,
<tt>description</tt> and <tt>unit_price</tt> messages.
</p>
<h2>Testing Without Using External Resources</h2>
<p>
Our first test attempt will be to run the <tt>purchase</tt> method without
talking to either the live Google web services, or hitting an actual
ActiveRecord database.
</p>
<h3>Mocking Active Record</h3>
<p>
The ActiveRecord part is easy to mock. The following will handle it:
</p>
<pre>
flexmock(Item).should_receive(:find).with(1).and_return(
flexmock("guitar",
:name => "Deschutes",
:description => "Deschutes model Guitar",
:unit_price => Money.new(2400.00)))
</pre>
<p>
We have mocked out the <tt>find</tt> method on <tt>Item</tt> so that
whenever we call find with an integer argument of 1, we will return a mock
item that will report its name, description and unit_price. This gives us
| |