Passing via instance variable or regular ()

def first
name = “sam”
last(name)
end

def last(first)
name = first + " " + “jam”
end

versus

def first
@name = “sam”
last
end

def last
name = @name + " " + “jam”
end

I am new to ruby and programming. I see that both of these ways work.
When I was first starting I tended toward the first way, but lately I
have
been tending toward the second way. Does it make much difference?

The reason I like using @ instead of the other sort of passing, is
because if I have a method with a variable that another method needs way
down the line, if I pass with () it seems like I need to keep passing
needless variables down the chain to get it from the first method to the
last method. With @ it sort of leap frogs the middle methods.

edit: saying brand n-3-w means my post contains spam? lol…okay first
starting then.

On Wed, May 9, 2012 at 9:37 PM, sam jam [email protected] wrote:

When I was first starting I tended toward the first way, but lately I
have
been tending toward the second way. Does it make much difference?

edit: saying brand n-3-w means my post contains spam? lol…okay first
starting then.

Hi, Sam, good question :slight_smile:

Unfortunately the answer is the ever-nebulous “it depends” :stuck_out_tongue:

Within an object, the second way is generally better, because objects
should generally be small and operate on a shared set of instance
variables.

Outside an object (e.g., in this case these methods are declared on main

which is technically an object, but its purpose isn’t to interact with
your
system so much as to give you an environment to wire your stuff together
and bootstrap your app in), the former is usually better.

I’d like to go further into this, but it’s a bit difficult as the names
of
the methods don’t accurately reflect what they do (these both return
full
names, last is just a helper that first calls in order to concatenate
the
names)

So pretty much instance variables to pass between methods in a class,
and () to pass between classes?

On Thu, May 10, 2012 at 8:18 AM, sam jam [email protected] wrote:

So pretty much instance variables to pass between methods in a class,
and () to pass between classes?

I definitively disagree. The purpose of instance variables is to
carry the state of an instance. In your example you are using state
only for the purpose of the method invocation. Using instance
variables has side effects: the instance is changed after the method
returns and they are not thread safe without additional measures. So
in your case you are introducing unnecessary disadvantages. So it’s
definitively

def first
last(“sam”)
end

def last(first)
first + " " + “jam”
end

Note the subtle changes I did: you set name in last but you do not do
anything with the value, so I left it out and simply returned the
result. Also, I left variable “name” out of method #first because the
value is used in one place only anyway.

Kind regards

robert

Hi,

I agree with Robert. Of course both ways work and the first may even be
a bit more efficient. But it’s definitely a kind of hack, because you’re
“misusing” the instance variables.

Also you will get an exception when you call “last” before having called
“first” before. Since you cannot even know this without looking at the
method definition, the whole code is rather obscure. You’re relying on
certain outer condiditions, which have nothing to do with the actual
task (returning a simple string).

I think it’s generally a good idea to avoid implicit values (global
variables etc.) as much as possible and try to encapsulate
functionalities.

Using @ does have advantages as well though. Using () to pass variables
internally within the class leads to less readable code I think. For one
you need to pass variables down the chain even if you are not using them
at each point down the chain. That makes for very ugly code versus using
@ to leap frog methods.

I do see the benefit you mention about needing to call first before you
call last. In the following case

def first
name = “sam”
last(name)
end

def last(first)
name = first + " " + “jam”
end

I could call last from some other class or method. But in some cases I
see no advantage here. Sometimes when I make classes they are for very
specific tasks, a bunch of methods that make up a larger system. The
steps for that system always need to be called in order. I suppose if I
wanted to reuse the steps in other places it would be best to use ().

I also noticed Robert mentioning that he would avoid using the name
variable as it is only used once. This brings me to a second question.
Sometimes I find that using variables in this way can improve code
readability as well. Perhaps I am writing a Feistel cipher and it makes
sense to name parts @l and @r during the encryption rounds. The
resulting cipher or plaintext is then @l + @r. I then need to remove the
padding from the resulting plaintext, so even though I pass @l and @r
only once to the remove padding method, it makes sense to say

ciphertext = @l + @r
remove_padding(ciphertext)

or is this needlessly cluttering my code with variables? I see a lot of
times in my code I use an = sign like this, to make it read more
clearly, but sometimes I also find myself doing it needlessly. How do
you feel about this?

I think that my use of instance variables for @l and @r helped me make
the following code look nicer and read better.


require 'openssl'
require 'narray'


class Lioness

  def initialize
    @block_size_in_kb = 100
    @hash_algorithm = OpenSSL::Digest::SHA256.new
  end

  def xor_strings(string1, string2)
    string1 = NArray.to_na(string1, "byte")
    string2 = NArray.to_na(string2, "byte")
    (string1 ^ string2).to_s
  end

  def generate_subkeys(key)

    @subkeys = Hash.new

    4.times do |i|
      @subkeys.store("key#{i}", @hash_algorithm.digest("#{i} #{key}"))
      @hash_algorithm.reset

    end
  end


  def pad_message(message)

    if message.bytesize == (@block_size_in_kb * 1000) then
    @padded_plaintext = message
    else
    bytes_to_pad = (@block_size_in_kb * 1000) - message.bytesize
    @padded_plaintext = message + 128.chr + ("\0" * (bytes_to_pad - 1))
    end
  end

  def remove_padding(message)
    if message.index("#{128.chr}") then
    padding_starts = message.index("#{128.chr}")
    @plaintext = message.byteslice(0...padding_starts)
    else
    @plaintext = message
    end
  end

  def encrypt(plaintext, key)

    if plaintext.bytesize > (@block_size_in_kb * 1000) then
    puts "Message size must be below #{@block_size_in_kb} kilobytes"
    end


    if plaintext.bytesize <= (@block_size_in_kb * 1000) then

    pad_message(plaintext)
    generate_subkeys(key)

    @l, @r = @padded_plaintext.byteslice(0..(@sha256.digest_length -
1)), @padded_plaintext.byteslice(@sha256.digest_length..-1)

    r_operation(@subkeys["key0"])
    l_operation(@subkeys["key1"])
    r_operation(@subkeys["key2"])
    l_operation(@subkeys["key3"])

    @ciphertext = @l + @r
    end
  end

  def decrypt(plaintext, key)

    generate_subkeys(key)
    @l, @r = plaintext.byteslice(0..(@hash_algorithm.digest_length -
1)), plaintext.byteslice(@hash_algorithm.digest_length..-1)

    l_operation(@subkeys["key3"])
    r_operation(@subkeys["key2"])
    l_operation(@subkeys["key1"])
    r_operation(@subkeys["key0"])

    padded_plaintext = @l + @r
    remove_padding(padded_plaintext)
  end

  def r_operation(subkey)
    cipher = OpenSSL::Cipher::Cipher.new 'AES-256-CTR'
    cipher.encrypt
    cipher.key = xor_strings(@l, subkey)
    ciphertext = cipher.update(@r)
    ciphertext << cipher.final
    @r = ciphertext
  end

  def l_operation(subkey)
    @l = xor_strings(@l, @hash_algorithm.digest(subkey + @r + subkey))
    @hash_algorithm.reset
  end

end

On Fri, May 11, 2012 at 9:20 AM, sam jam [email protected] wrote:

Using @ does have advantages as well though. Using () to pass variables
internally within the class leads to less readable code I think. For one
you need to pass variables down the chain even if you are not using them
at each point down the chain. That makes for very ugly code versus using
@ to leap frog methods.

First of all that code is explicit - that’s not necessarily “ugly”.
Using instance variables to avoid having to pass arguments to method
calls has another disadvantage apart from the ones I mentioned
earlier: it is not obvious what’s happening here because information
is not passed explicitly. If you notice you have to pass too many
variables down a call chain then this is an indication that you have
not chosen proper abstractions of your state. Could be that all these
variables can go into a single class (even if it’s just a one liner
Struct) and then you only need to pass an instance of this class.
Benefit of this is that you get another entity which you can attach
documentation to and it can be given a telling name. By passing state
“behind the scenes” readers of the code will have a harder time to
understand what’s going on and the code is less modular because for a
method there exists an additional precondition (i.e. that some
instance variables are set in a particular way). By using unobvious
ways to pass state you gain a bit laziness at the time of writing but
pay with increased effort during reading and understanding later.
This is especially important for maintenance. Compilers can deal with
arbitrary convoluted code, but it must be readable in order to be
maintainable.

I could call last from some other class or method. But in some cases I
see no advantage here. Sometimes when I make classes they are for very
specific tasks,

All classes should be for very specific tasks! That’s the whole
point of software engineering: you have a certain amount of
functionality that must be delivered by a program and it is our task
to distribute that functionality across program artifacts (methods,
classes, modules) in a way that the result fulfills some requirements

  • desired functionality must be guaranteed
  • a certain level of performance must be achieved
  • maintainability, which consists of
    • readability
    • modularity
    • test coverage

Not necessarily with priorities in this order.

a bunch of methods that make up a larger system. The
steps for that system always need to be called in order. I suppose if I
wanted to reuse the steps in other places it would be best to use ().

You would typically start out with a public method which calls private
methods in that defined order. If you find later that you could use
those private methods on their own you can still make them public.
Basically the rule of thumb here is: make as few things public as
possible and needed for the task and pay special attention to the
interface because that is set in stone (not really but the cost of
changing a public interface is usually extremely high). It’s must
easier to make something private public later than to change a public
interface!

remove_padding(ciphertext)

or is this needlessly cluttering my code with variables?

It depends. If you want to document then you can also do things like
these:

remove_padding(@l + @r) # ciphertext
remove_padding_from_ciphertext(@l + @r)

I see a lot of
times in my code I use an = sign like this, to make it read more
clearly, but sometimes I also find myself doing it needlessly. How do
you feel about this?

Your feeling is probably right. :slight_smile:

Also in my code I did this instead

@ciphertext = @l + @r
remove_padding(@ciphertext)

I find that using instance variables helped me make the following code
look nicer

Please don’t do that. It comes at a price (see my earlier statements).

Kind regards

robert

“for a
method there exists an additional precondition (i.e. that some
instance variables are set in a particular way).”

there is still a precondition in either case

precondition: an instance variable is set in a particular way

def first
@name = “sam”
last
end

def last
name = @name + " " + “jam”
end

precondition: something is passed to it (something set in a particular
way)

def first
name = “sam”
last(name)
end

def last(first)
name = first + " " + “jam”
end

A lot of what you said I see as great points, but not that one because
it is the same in either case.

On Fri, May 11, 2012 at 12:32 PM, sam jam [email protected] wrote:

@name = “sam”

A lot of what you said I see as great points, but not that one because
it is the same in either case.

But the precondition of having a method argument is automatically
enforced (if you do not use varargs) and you will immediately notice
something is missing. In a way it is more obvious. And then there
are still the other advantages

  • thread safety
  • no permanent side effects
  • no need to invoke additional methods before this method to set
    instance state properly
    etc.

Cheers

robert

By the way: This kind of value passing doesn’t even work in most other
languages, because it depends on Ruby’s feature of dynamicly created
instance variables. This isn’t necessarily an argument against it, but
it shows that the idea is rather odd.