A matter of style

All,

A little while ago I picked up a copy of the pickaxe book and got hooked
to
Ruby. Never had a `real’ project to work on though (that’s what you get
when
you don’t hack for a living I suppose :-). Either way, a few weeks back
I
needed an app that generates deals for the card game bridge. I made a
small
design and hacked up some unit tests. After a while no more tests
failed:

[email protected] { ~/bridgehands }$ ruby bridgeTests.rb
Loaded suite bridgeTests
Started
....
Finished in 0.003154 seconds.

After a bit more coding to format the output I got something that
outputs:

[email protected] { ~/bridgehands }$ ruby deal.rb
        AQJ652
        92
        T53
        Q5
973                 4
K87653              AQJ
8                   J742
JT4                 A9876
        KT8
        T4
        AKQ96
        K32

Not bad… Like I said, I’m not a full-time programmer. I would love
to
learn more about `proper’ ruby style though. Is there even such a thing?
I
mean, the book cover said something about pragmatic :slight_smile:

Could anyone have a look at:

http://www.van-gils.org/~bas/bridgehands/

and give me some suggestions on style / ruby idiom / other things?

Any help would be greatly appreciated,

yours

Bas


Bas van Gils [email protected], http://www.van-gils.org
[[[ Thank you for not distributing my E-mail address ]]]

Quod est inferius est sicut quod est superius, et quod est superius est
sicut
quod est inferius, ad perpetranda miracula rei unius.

On Tue, Jun 12, 2007 at 03:10:49AM +0900, Bas van Gils wrote:

All,

A little while ago I picked up a copy of the pickaxe book and got hooked to
Ruby. Never had a `real’ project to work on though (that’s what you get when
you don’t hack for a living I suppose :-). Either way, a few weeks back I
needed an app that generates deals for the card game bridge. I made a small
design and hacked up some unit tests. After a while no more tests failed:
[snip]
Any help would be greatly appreciated,
From what I’ve been led to understand, method names consisting of
multiple words should be named_with_underscores, not namedWithCamelcase.

puts' is the same asprint “something\n”’

Parens can be omitted if it doesn’t confuse the parser (or the reader)

As well, reserve the { } form of blocks to one-liners.

Taking these into account, instead of writing (from
http://www.van-gils.org/~bas/bridgehands/deal.rb):

bg.suits.each{ |suit|
    cards = bg.north.cardsOfSuit(suit)
    print "        #{bg.sortCards(cards)} \n"
}

write something like

bg.suits.each do |suit|
    cards = bg.north.cards_of_suit suit
    puts "        #{bg.sort_cards(cards)} "
end

Then again, these are highly subjective views, ones that I’ve absorbed
from reading other people’s ruby and getting into arguments with friends
:slight_smile: Take them with a grain of salt, as I’m not a Ruby expert and thus I
might be wrong.

On 6/11/07, Bas van Gils [email protected] wrote:

Loaded suite bridgeTests
        Q5
973                 4
K87653              AQJ
8                   J742
JT4                 A9876
        KT8
        T4
        AKQ96
        K32

Do not forget to unblock the Ten of Diamonds in your 4 Spades :wink:

Not bad… Like I said, I’m not a full-time programmer. I would love to
learn more about `proper’ ruby style though. Is there even such a thing? I
mean, the book cover said something about pragmatic :slight_smile:

Could anyone have a look at:

http://www.van-gils.org/~bas/bridgehands/

Some thaughts
() why do you define Player#setName! an attribute accessor to :name
seems appropriate
(
) Card = Struct.new( :suit, :face ) would be sufficent
(*) Ruby allows for much shorter code, look e.g at
def getCard
if @cards.size == 0
raise “No more cards in the deck”
end
return @cards.slice!(0)
end
which I would write as
def getCard;
@cards.shift or raise SomeNiceErrorClass, “No more cards in the
deck”
end
(+) An example where you are in harmony with ruby is:
def cardsOfSuit(sn)
return @cards.select{ |card| card.suit.name==sn }
end
The return however is superfluous, but it is a respectable style to
end all defs with return statements

(*) Personally I think it is nice to name CardSet#shuffle! with the
“!”. However more learned members of the community think that the
existance of X#member! implies
X#member and X#member is to be defined as

def member; x = dup; x.member!; x end

Just to let you know, I am with you but we are pretty alone :wink:

All at all pretty impressive for a beginner.

Cheers
Robert

Bas van Gils [email protected], http://www.van-gils.org
[[[ Thank you for not distributing my E-mail address ]]]

Robert

Hi all

Robert (and also Anthony), thanks for your comments!

On Tue, Jun 12, 2007 at 03:58:21AM +0900, Robert D. wrote:

(*) Card = Struct.new( :suit, :face ) would be sufficent

Right, I wasn’t aware of the Struct concept. So there’s a first lesson
:wink:

end
That’s definitely shorter and more readable… I guess I’ll learn to
code this
way once I get to know the API better.

(*) Personally I think it is nice to name CardSet#shuffle! with the
“!”. However more learned members of the community think that the
existance of X#member! implies
X#member and X#member is to be defined as

def member; x = dup; x.member!; x end

Just to let you know, I am with you but we are pretty alone :wink:

Well, it is easy to just add this method if that is to be common Ruby
style.

Yesterday I read part of Why’s poignant guide to Ruby. I noticed that
:symbol’s are used frequently… is that also typical Ruby? IË™e. write

@someHash = { :foo => “bar” }

rather than

@someHash = { “foo” => “bar” }

is so, is (memory)efficiency the main reason?

Cheers

Bas


Bas van Gils [email protected], http://www.van-gils.org
[[[ Thank you for not distributing my E-mail address ]]]

Quod est inferius est sicut quod est superius, et quod est superius est
sicut
quod est inferius, ad perpetranda miracula rei unius.

On Tue, Jun 12, 2007 at 03:39:47AM +0900, Anthony M. wrote:

Taking these into account, instead of writing (from
cards = bg.north.cards_of_suit suit
puts " #{bg.sort_cards(cards)} "
end

Then again, these are highly subjective views, ones that I’ve absorbed
from reading other people’s ruby and getting into arguments with friends
:slight_smile: Take them with a grain of salt, as I’m not a Ruby expert and thus I
might be wrong.

Your suggestions are pretty much canonical Ruby style, at first glance
at
least.

On Tue, Jun 12, 2007 at 03:33:32PM +0900, Bas van Gils wrote:

is so, is (memory)efficiency the main reason?
I believe it’s a combination of efficiency and readability. The
differing syntax for a symbol as opposed to a string helps to provide an
immediate visual cue to the fact that it’s a hash key, since that’s by
far the most common place for symbols to be used (from what I’ve seen
and
done). It’s also one fewer character and two fewer keystrokes to type,
though I sincerely doubt that factors into most considerations. There
may be other reasons that apply, but that’s what immediately occurs to
me.

On Jun 12, 2007, at 6:59 AM, [email protected] wrote:

do/end actually matters. There are also some interesting ideas on
RAILS ROUTING (new! http://safari.awprofessional.com/9780321509246)
RUBY FOR RAILS (http://www.manning.com/black)

Jim W. tends to be an advocate of that convention: use do-end
for blocks that are “just blocks” and {} for blocks where the value
of the block is to be used. If you ever see any of Jim’s code that
uses Builder, this convention is quite apparent. The problem of the
higher precedence of the braces can often be side-stepped by
parenthesizing the method arguments preceding the {block}. This is
one of the reasons that the do/end form is recommended for Rakefiles
so that the need for ()'s doesn’t distract from the DSL-ish feel of
the task method.

I tend to merge this idea with the one for one-liners and prefer {}
in irb where the code isn’t being saved anywhere and almost never use
{} in ERb templates where the opening and closing of the block are in
separate <% %>'s.

-Rob

Rob B. http://agileconsultingllc.com
[email protected]

Almost. puts adds “\n” unless it’s already there. So these are
equivalent:

print "hello\n"
puts "hello\n"

Right but do you remember when I stupidly changed your code from
puts a
to
puts a.join("\n")

So this is another difference between print and puts, puts prints the
content of an array seperated by newlines. print does no such thing of
course.

particular, please have mercy and don’t leave the parens out in method
signatures. Things like this:

def a b, c, d = 1

read very strangely, at least to my eyes.
I love it, I really read it better like this. But I guess the
community rather puts parens :frowning: and if you want to comply listen to
David.
Let us just have a look at the Ruby core as David suggests below

All methods
ruby -e ‘c=0;ARGF.each{|f|c+=1 if /^\sdef\s/===f};puts c’ $(ruby -e
'puts Dir["**/
.rb"]’)
18258

All methods with parens
ruby -e ‘c=0;ARGF.each{|f|c+=1 if /^\sdef.(/===f};puts c’ $(ruby
-e ‘puts Dir["**/*.rb"]’)
12271

All methods without parens and without parameters
ruby -e ‘c=0;ARGF.each{|f|c+=1 if /^\sdef\s\w+\s$/===f};puts c’
$(ruby -e ‘puts Dir["**/*.rb"]’)
5303 +

ruby -e ‘c=0;ARGF.each{|f|c+=1 if /^\sdef\s\w+\s#/===f};puts c’
$(ruby -e ‘puts Dir["**/*.rb"]’)
94 = 5397
— ====
Leaves
ruby -e ‘puts 18258 - 12271 - 5303 - 97’
587 methods corresponding to “our” style which makes
ruby -e ‘puts 58700/18258.0’
3.21502902837112%

Not enough to get into parliament I’d say.

As well, reserve the { } form of blocks to one-liners.

That’s going to depend partly on whether you run across the
(relatively rare) case where the precedence difference between {} and
do/end actually matters. There are also some interesting ideas on
record (see archives) involving blocks with side effects vs. blocks
that just calculate. But I can’t remember which is supposed to be
which :slight_smile:

I try to avoid do end inside { }
Beware of this too
some_method a, b {|x| puts x}
will not work use either parens or do…end.

Cheers
Robert

Hi –

On Wed, 13 Jun 2007, Robert D. wrote:

So this is another difference between print and puts, puts prints the
community rather puts parens :frowning: and if you want to comply listen to
David.
Let us just have a look at the Ruby core as David suggests below

Another little test:

$ ruby -e ‘puts
ARGF.select{|f| f =~ /^\sdef\s\w+\s+\w+/}.size’ $(ruby -e 'puts
Dir["**/
.rb"]’)
120

$ ruby -e 'puts
ARGF.select{|f| f =~ /^\sdef\s\w+\s+\w+/}.size’ $(ruby -e 'puts
Dir["**/
.rb"].reject {|fn| fn =~ /rexml/} ')
9

:slight_smile: I think Sean is skewing the graph :-

David

On 6/12/07, [email protected] [email protected] wrote:

puts a

def a b, c, d = 1
ARGF.select{|f| f =~ /^\sdef\s\w+\s+\w+/}.size’ $(ruby -e 'puts
Dir["**/
.rb"]’)
120

$ ruby -e 'puts
ARGF.select{|f| f =~ /^\sdef\s\w+\s+\w+/}.size’ $(ruby -e 'puts
Dir["**/
.rb"].reject {|fn| fn =~ /rexml/} ')
9

:slight_smile: I think Sean is skewing the graph :-
I love that guy… :wink:
Seriously it would be stupid to advice a newby into a personal style
that is way off mainstream and I did not.
But I will not put parens around my defs because I feel that if Ruby
gives me this possibility and I like it I should use it.

Now when it comes to working in teams the whole story changes again…
most important thing being a consistent style. By adopting a style
close to mainstream that can be achieved easier…

That is why I feel that this discussion is important.

David

Cheers
Robert

Books:
Wait a minute why is nobody publishing me :wink:
Are you reading this Tim?

Robert

Hi –

On Tue, 12 Jun 2007, Anthony M. wrote:

Not bad… Like I said, I’m not a full-time programmer. I would love to

From what I’ve been led to understand, method names consisting of
multiple words should be named_with_underscores, not namedWithCamelcase.

puts' is the same asprint “something\n”’

Almost. puts adds “\n” unless it’s already there. So these are
equivalent:

print "hello\n"
puts "hello\n"

Parens can be omitted if it doesn’t confuse the parser (or the reader)

Can be, but it’s best not to get too cutesy with it :slight_smile: In
particular, please have mercy and don’t leave the parens out in method
signatures. Things like this:

def a b, c, d = 1

read very strangely, at least to my eyes.

As well, reserve the { } form of blocks to one-liners.

That’s going to depend partly on whether you run across the
(relatively rare) case where the precedence difference between {} and
do/end actually matters. There are also some interesting ideas on
record (see archives) involving blocks with side effects vs. blocks
that just calculate. But I can’t remember which is supposed to be
which :slight_smile:

Then again, these are highly subjective views, ones that I’ve absorbed
from reading other people’s ruby and getting into arguments with friends
:slight_smile: Take them with a grain of salt, as I’m not a Ruby expert and thus I
might be wrong.

Reading Ruby code, in particular the Ruby source code itself, is a
great way to see the traditional style. I’ve never seen anyone
improve on that style. People get very excited about the fact that
Ruby lets you “do your own thing” in terms of style – like:

printf( “My name is %s\n”, thisPerson.name() );

and such… but if most Ruby were written like that I think I would
have put the Pickaxe back on the shelf at the bookstore :slight_smile:

David

On Jun 12, 2007, at 4:47 PM, Chad P. wrote:

that just calculate. But I can’t remember which is supposed to be
which :slight_smile:

I have yet to see a practical case where the precedence actually came
into play – and I suspect that, when I do finally see such a thing,
readability would benefit from a refactor so that it doesn’t come into
play after all.

assert_not_nil @enum.find do

… a few lines of search code here …

end

You need to switch block styles, add some parenthesis, or separate
the two calls.

James Edward G. II

On Tue, Jun 12, 2007 at 07:59:10PM +0900, [email protected] wrote:

read very strangely, at least to my eyes.

It reads a little like OCaml to me – which is pretty strange, in the
context of a Ruby program. I tend to like a syntax that remains
constant
across the language (which is one of the reasons I expect to find
IronRuby to be rather disconcerting in practice, once it’s finalized,
and
one of the reasons I tend to avoid .NET variants of languages in
general).

As well, reserve the { } form of blocks to one-liners.

That’s going to depend partly on whether you run across the
(relatively rare) case where the precedence difference between {} and
do/end actually matters. There are also some interesting ideas on
record (see archives) involving blocks with side effects vs. blocks
that just calculate. But I can’t remember which is supposed to be
which :slight_smile:

I have yet to see a practical case where the precedence actually came
into play – and I suspect that, when I do finally see such a thing,
readability would benefit from a refactor so that it doesn’t come into
play after all.

printf( “My name is %s\n”, thisPerson.name() );

and such… but if most Ruby were written like that I think I would
have put the Pickaxe back on the shelf at the bookstore :slight_smile:

I like the flexibility of the language. I also like the canonical
style.

In other words, I think I agree.

On Wed, Jun 13, 2007 at 04:49:01AM +0900, Robert D. wrote:
[…]

Seriously it would be stupid to advice a newby into a personal style
that is way off mainstream and I did not.
[…]
Now when it comes to working in teams the whole story changes again…
most important thing being a consistent style. By adopting a style
close to mainstream that can be achieved easier…

That is why I feel that this discussion is important.

I agree that the discussion is important. It’s a good thing that Ruby
supports
so many styles. I’ve programmed in several languages and I’m always
curious as
to what is considered to be `good style’ by which I mean stuff like:

  • do you use {} or begin/end for blocks
  • do you use symbols or strings as keys for hashes
  • guidelines for rdoc
  • a few big classes (i.e. java style) or many small classes
  • and so on

The advise to look at the core libs is a good one. There’s a lot of code
there
and even though I don’t understand all of it, it gives a good idea of
how
things work.

More experience and more knowledge of the Ruby API is what I personally
need
now :wink:

Just-my-five-cents’ly yours

Bas


Bas van Gils [email protected], http://www.van-gils.org
[[[ Thank you for not distributing my E-mail address ]]]

Quod est inferius est sicut quod est superius, et quod est superius est
sicut
quod est inferius, ad perpetranda miracula rei unius.

On Wed, Jun 13, 2007 at 06:51:54AM +0900, James Edward G. II wrote:

do/end actually matters. There are also some interesting ideas on

… a few lines of search code here …

end

You need to switch block styles, add some parenthesis, or separate
the two calls.

Parentheses sound perfectly reasonable to me.

Hi –

On Wed, 13 Jun 2007, Robert D. wrote:

into play – and I suspect that, when I do finally see such a thing,
sure is a nice feature for a DSL. That does not necessarily make it

recover( :from => :error ){ do_some_stuff }

I dislike parens, but I am pretty alone, so I gotto refrain from
repeating myself (still hoping for some support here, obviously :wink:

It’s not a contest – not even a debate. Ultimately people should do
what they want. I like to steer people, especially newcomers, to the
traditional style, in the hope that that’s what they will decide they
want to do, partly just because it is the traditional style, and
partly because on the whole it looks so great.

That’s all there is to it. You already know everything you need to
know, and you can decide what to do. It doesn’t matter who (including
me) says what (and we already have ways to determine what Matz does).

In other words, let’s not get into one of these interminable threads
where people try to “argue” and “convince” each other. It’s just not
that kind of situation. (And neither are 99.9999% of such threads :slight_smile:

David

On 6/12/07, Chad P. [email protected] wrote:

play after all.
Depends a lot of your style:
In my DSL I use at work I will write stuff like

client :name => “allow ssh to DB”, :server => “1.1.1.1” … do
end

If you leave the parens away the {} just will not work, so this for
sure is a nice feature for a DSL. That does not necessarily make it
the best “Programming Style”.
Personally and sorry for insisting just find hat

def recover parms = {}, &blk

recover :from => :error do some_stuff end

reads better (for me) than
def recover( params ={}, &blk)

recover( :from => :error ){ do_some_stuff }

I dislike parens, but I am pretty alone, so I gotto refrain from
repeating myself (still hoping for some support here, obviously :wink:

Cheers
Robert


CCD CopyWrite Chad P. [ http://ccd.apotheon.org ]
Ben Franklin: “As we enjoy great Advantages from the Inventions of others
we should be glad of an Opportunity to serve others by any Invention of
ours, and this we should do freely and generously.”
How right he was. – If he really said that

I have yet to see a practical case where the precedence actually came
into play – and I suspect that, when I do finally see such a thing,
readability would benefit from a refactor so that it doesn’t come into
play after all.

assert_not_nil @enum.find do

… a few lines of search code here …

end

I think Chad’s point stands. It seems whatever is encapsulated in the
enum’s find search code would be better off as a method on that
object. That would make the test cleaner and then there won’t be any
worry about block style precedence.

On 6/13/07, [email protected] [email protected] wrote:

Hi –

It’s not a contest –
100% agree
not even a debate.
100% surprised (maybe I do not grasp the semantics of debate, it means
discussion, right?)
Ultimately people should do
what they want. I like to steer people, especially newcomers, to the
traditional style, in the hope that that’s what they will decide they
want to do, partly just because it is the traditional style, and
partly because on the whole it looks so great.
Sorry for intervening with that, but I will just be clear again:
David’s the guy to follow when in doubt, if you prefer my style you
prefer it anyway but be warned neverheless :(.

David has probably read and written 100 times the Ruby Code I have
read and written (catching up though;). As he I do not think it is a
contest, maybe I was confusing the ML with a chat forum a little
bit…

That’s all there is to it. You already know everything you need to
know, and you can decide what to do. It doesn’t matter who (including
me) says what (and we already have ways to determine what Matz does).

In other words, let’s not get into one of these interminable threads
where people try to “argue” and “convince” each other. It’s just not
that kind of situation. (And neither are 99.9999% of such threads :slight_smile:
I was not trying to do this but you make me aware that I was talking
too much, point taken.

Over and out :wink:
Robert

On Jun 13, 2007, at 7:37 AM, Yossef M. wrote:

end

I think Chad’s point stands. It seems whatever is encapsulated in the
enum’s find search code would be better off as a method on that
object. That would make the test cleaner and then there won’t be any
worry about block style precedence.

As long as your custom method doesn’t take a block…

James Edward G. II

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs