[LRUG] Comparable Null Objects

jc at panagile.com jc at panagile.com
Wed Jul 15 07:09:21 PDT 2015


| Some events don't have an expected date, so like a good little OO programmer i've created a Null object:




Yay! Good OO programmer.




| but when it comes to sorting the list




wait, wat? Less good OO programmer.




I can see three things going on here, pretty much simultaneously.




1) You want to sort a list of different types of things. Like when you try to sort a list of Silverback Gorillas and instances of the number 37 it’s hard because it doesn’t really make sense.




2) You don’t have a list. You have an Array object. Is this the best place to send the ‘sort’ message to? Should it own the behaviour of sorting these particular disparate types of things?




3) You switched from clean OO thinking (we need an object to encapsulate this state) to imperative thinking (we have a list and we need to sort it).





I blame Ruby for all of this. It makes you think you’re doing OO programming but throws in many non-OO ideas to trip you up.




It’s not clear that an OO approach is the best approach here, but if you want to follow it try to think less about objects and more about the messages between objects. E.g., instead of ‘I need to sort a list’ think ‘I need to send a message somewhere telling it to do something (in this case to… what? To sort some objects? But why do you care?)’.




Hope this helps or at least makes you think or at the very least persuades you to rage quit programming and go and live in a forest,

John








On Wednesday, Jul 15, 2015 at 1:03 pm, Duncan Stuart <dgmstuart at gmail.com>, wrote:
Hi LRUG - hopefully an interesting little problem:

I have an Event class which has an "expected_date" attribute.
Some events don't have an expected date, so like a good little OO programmer i've created a Null object:

class NoExpectedDate

  def to_s(format=:default)

    "Unknown"

  end

end




This works great for printing the values, but when it comes to sorting the list I of course get:










   ArgumentError: comparison of Date with NoExpectedDate failed 

If I include Comparable and define <=> then one comparison works, but the other doesn't :

class NoExpectedDate

  include Comparable

  def to_s(format=:default)

    "Unknown"

  end

  def <=>(other_date)

    1 # Treat it as after every other date

  end

end




















$ NoExpectedDate.new > Date.today
=> true



$ Date.today > NoExpectedDate.new
ArgumentError: comparison of Date with NoExpectedDate failed

I think this is because Date's <=> method expects it's argument to be a Date object or a number ("a numeric value as an astronomical Julian day number"). I've tried defining to_i and to_r on NoExpectedDate, but no dice.

Can I get NoExpectedDate to pretend to be a Date (like SimpleDelegator lies about it's class)? Is that evil?

I suppose I could always just define a method on Event to do this particular sort, but that seems nasty for all sorts of reasons:



def sort_by_expected_date sort do |a, b| 

    if b.class = NoExpectedDate 

      1

    else

      a <=> b

    end

  end

end
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lrug.org/pipermail/chat-lrug.org/attachments/20150715/115d85fd/attachment-0003.html>


More information about the Chat mailing list