1

I'm writing a system that has a number of objects with data in them. For example one object has a user name attribute, another has a date, another shopping cart item etc.

I'm making an object that generates a MD5 hash based on a concatenated string of these values. So for example md5(username + date + special_number + cart_id).

The way I was going to do this was pass the md5_generator object to each other the other objects in turn allowing them to call an add_x method (eg add_username) on the generator to add their specific piece of data. This avoids pulling the data out of each object, which I want to avoid.

I'm wondering if this is the best idea or if there is some simpler OO pattern I'm missing?

migrated from stackoverflow.com Oct 14 '13 at 16:04

This question came from our site for professional and enthusiast programmers.

  • 1
    If you're going to use all those pieces of data together, why not encapsulate them in an object? – George Stocker Oct 14 '13 at 15:46
  • They are already in other objects. So for example the username is inside a User object, the cart_id is in a Cart object. I would like to avoid duplicating the attributes. But I need to get them all together some how because the md5 object has to hash them together. – Cormac Mulhall Oct 14 '13 at 15:49
  • 1
    It does sound like fishy OOP, since there's no reason why a shopping cart object, for instance, should need to know about hashes for some separate purpose, but either you have to pull the data out of each object, or have each object push it out, there doesn't seem to be any magic way to avoid this. How do the values get into the individual objects in the first place? Could you have the managing process add them to another data structure at the same time it is creating those objects? Not ideal either, but if you're going to do it, you have to try some way. – Paul Griffiths Oct 14 '13 at 15:57
  • Yeah that was my first thought, split the data off at the creation phase. Was nervous that the data in the object could be changed without that be reflected in md5 object. The reason for this hash is that each object creates its own piece of a request to an external API (e.g the User object generates the parts of a POST string involving its data), but the final POST field is a md5 hash of a number of the difference values from the different objects. – Cormac Mulhall Oct 14 '13 at 16:01
  • The secret has to be last, not first. See en.wikipedia.org/wiki/Length_extension_attack to understand the bug that might give a malicious attacker access to someone else's cart. (I say might because there are ways to protect against it. But again we see the truth in the saying that what you don't know about security WILL hurt you.) – btilly Oct 14 '13 at 16:51
3

You could just have an add_data(key, data) on the hash generator object to generically allow any data to be added:

class HashGenerator(...):
    def __init__(self):
        self.data = []

    def add_data(self, key, data):
        self.data.append((key, data))

    def calc_hash(self):
        self.data.sort()
        return hashlib.md5("|".join(data for _key, data in self.data))

which in turn the data objects are passed and use:

class UserNameObject(...):
    def inject_data(self, hash_generator):
        hash_generator.add_data('username', self.username)

Or, if you'd prefer the data objects to be unaware of the hash generator you could do (which would technically be better):

class UserNameObject(...):
    def get_hash_tuple(self):
        return ('username', self.username)

Though, I would recommend using SHA1 as opposed to MD5 because it's more secure but depending on the purpose of the hash, the best algorithm could vary.

  • Yeah that is pretty much what I was thinking. I was wondering how sound an idea that is from an OO perspective. – Cormac Mulhall Oct 14 '13 at 15:50
  • Unfortunately MD5 is an external requirement :-( – Cormac Mulhall Oct 14 '13 at 15:55
  • From an OO perspective, having a generic add_data(key, data) is better than multiple add_username(), add_date(), etc. especially if they don't do anything special. Ultimately, either the hash generator object, each data object, or some third hash/data aggregator object will have to know about the existence of the others, and it really just depends on how abstract to want to make it. To me, I think this way is fine using OO. – cpburnz Oct 14 '13 at 16:01
0

You could use a reflection to find out which properties each object has and dynamically add those to the generator.

In pseudo code:

class HashGenerator {
   String generate(Object o) {
      String combined = "";
      for each( property in o ) {
          combined += o[property];
      }

      return md5(combined);
   }
}

Depending on the programming language there will be diffent ways of getting the property in o to work.

  • I would like to avoid pulling the data out, even using properties. "Tell, don't ask" and all that jazz. – Cormac Mulhall Oct 14 '13 at 16:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.