I primarily use structs as:
- A data structure replacing any array and calls to array like things.
- As a value object.
- As an internal class wrapping some behavior until I get a better grasp on things.
Consider the following:
MAPPING = { note: ['user_id', 'practice_user_id'] }
def old_column
MAPPING[key].first
end
def new_column
MAPPING[key].last
end
Let's replace with a struct!
MAPPING = { note: Tuple.new('user_id', 'practice_user_id'] }
extend Forwardable
def_delegators :tuple, :old_column, :new_column
def tuple
@tuple ||= MAPPING[key]
end
private
Tuple = Struct.new(:old_column, :new_column)
I'll take the struct over full-blown class in that case any day. And I'll take it over the array.
So I don't really get this argument. If I don't pass in the appropriate code into my class, it will not behave as I expect it to?????!?!?!? WHAT IS THIS I DONT EVEN. No but seriously, my struct classes are roughly between 1 and 8 lines of code with 1-2 arguments passed in. I'm pretty sure I can manage to not entirely botch that.
Also, I'm doing this thing where I write expecations for how my code behaves before I write the code. Then I run the expectations to ensure that my code does what I want it to do. It's great at catching silly things like missing arguments. You guys should try it. I've never actually encountered this issue with years of writing Structs.
OK... cool. I've never actually seen production code that takes advantage of them, but if it gets you hot and bothered then feel free to not use the Stuct then :).
I'd like you to show me a Ruby object that is totally immutable. I can break encapsulation on anything and while reviewing internal value objects using struct a setter method would probably look just as bad as obj.send("@#{attr}=", blerg)
to me. Ruby is full of trust that developers aren't going to be stupid and this is an area I'm comfortable giving a pass. If you don't like the honor system in this case I can understand it.
So I think at worst, a Struct is a means to get you to a better class. It has the downside of being a mutable value object, but really everything in Rubyland is mutable. We just pretend they are not for giggles. I still believe it has use as a tool and in practice of actually using Structs, you rarely encounter any of the perceived weaknesses. When you do, you just refactor towards a full class.