Skip to main content
clarify title
Source Link

Working with "external" object IDsidentifiers


 

One alternativeapproach would be to have the associative container keep references to the ID field as keys. But I don't know how to do that, at least in a language like C++.

For example, in C++, consider the class

class MyClass {
public:
    std::string name;
    MyClass(string name) : name(name) {}
}

Then the straightforward approach would be to store a std::map<std::string, MyClass>. I tried to make use of std::reference_wrapper to store references to the IDs, but then the order of the map doesn't work since operator< isn't defined on reference_wrappers:

int main() {
    std::map<reference_wrapper<std::string>, MyClass> myInstances; // error
    MyClass obj("Bob");
    myInstances.insert({obj.name, obj});
}

In Python, I believe this

class MyClass:
    def __init__(self, ID: str):
        self.ID = ID


myInstances = {}
obj = MyClass("Bob")
myInstances[obj.ID] = obj

would work, since both the myInstances[obj.ID] identifier (as in Python object identifier) and the self.ID identifier would point to the same string (so no extra memory would be needed).

Edit: this wouldn't work in fact, as strings are immutable (like any other key for a dict).

Working with "external" object IDs


 

One alternative would be to have the associative container keep references to the ID field as keys. But I don't know how to do that, at least in a language like C++.

For example, in C++, consider the class

class MyClass {
public:
    std::string name;
    MyClass(string name) : name(name) {}
}

Then the straightforward approach would be to store a std::map<std::string, MyClass>. I tried to make use of std::reference_wrapper to store references to the IDs, but then the order of the map doesn't work since operator< isn't defined on reference_wrappers:

int main() {
    std::map<reference_wrapper<std::string>, MyClass> myInstances; // error
    MyClass obj("Bob");
    myInstances.insert({obj.name, obj});
}

In Python, I believe this

class MyClass:
    def __init__(self, ID: str):
        self.ID = ID


myInstances = {}
obj = MyClass("Bob")
myInstances[obj.ID] = obj

would work, since both the myInstances[obj.ID] identifier (as in Python object identifier) and the self.ID identifier would point to the same string (so no extra memory would be needed).

Edit: this wouldn't work in fact, as strings are immutable (like any other key for a dict).

Working with "external" object identifiers

One approach would be to have the associative container keep references to the ID field as keys. But I don't know how to do that, at least in a language like C++.

clarify intent
Source Link

Note: I wrote this question in a way that made it seem I'm mainly concerned with the memory usage and ways to optimise this. Rather, my original intention (and my current intention, upon revisiting this question) is to ask for solutions to the maintainability problem: the fact that one has to make sure that a corresponding pair of key (in the associative container) and field (in the object itself) for the name/ID of the object stay in sync.

I have often encountered a situation in which users of a program (not necessarily human, just an external agent) need to be able to reference objects of a class with a certain "external" identifier or name, in order to create, access, modify andor delete them. A couple of examples:

  • a command-line application where end-users refer to specific instances by name, e.g. a calculator that deals with geometrical objects
  • a GUI with a dynamically created drop-down list where each item corresponds to an instance

This identifier could be an integer, for example, or a string. We'll suppose it's a string for the sake of the argument.

Let me clarify. In order for the program to "link" a certain identifier to the corresponding actual object, it needs to have some sort of associative container with IDs as keys and their corresponding objects as values, providing thus logarithmic access time.

Now, suppose some method of this class needs access to the identifieridentifier; e.g. a prettyPrint method that also prints the object's name. In this case, should the identifier be a field of the class? This seems like the obvious solution. But the problem is that now the identifiers are duplicated: as keys in the associative container, and as fields in each instance. That would imply double the storage necessities and duplicate "management tasks" (iduplicate "management tasks"—i.e., when adding a new object to the associative container, one would need to specify the identifier as both key and field). It would also entail slightly more memory usage, but this is the least significant of the two problems.

Is there a general way to overcome this problem?Is there a general approach to this problem? (Or am I fussing over nothing?) 


One alternative would be to have the associative container keep references to the ID field as keys. But I don't know how to do that, at least in a language like C++.

class MyClass {
public:
    std::string ID;
    MyClass(string id) : ID(id) {}
}
class MyClass {
public:
    std::string name;
    MyClass(string name) : name(name) {}
}

Then the straightforward approach would be to store a std::map<std::string, MyClass>. I tried to make use of std::reference_wrapper to store references to the IDs, but then the order of the map doesn't work since operator< isn't defined on reference_wrappers:

int main() {
    std::map<reference_wrapper<std::string>, MyClass> myInstances; // error
    MyClass obj("Bob");
    myInstances.insert({obj.ID, obj});
}

Is there a way to do this? Or is it unnecessarily complicated?


 
int main() {
    std::map<reference_wrapper<std::string>, MyClass> myInstances; // error
    MyClass obj("Bob");
    myInstances.insert({obj.name, obj});
}

would work, since both the myInstances[obj.ID] identifier (as in Python object identifier) and the self.ID identifier would point to the same string (so no extra memory would be needed).

Edit: this wouldn't work in fact, as strings are immutable (like any other key for a dict).

I have often encountered a situation in which users of a program (not necessarily human, just an external agent) need to be able to reference objects of a class with a certain "external" identifier, in order to create, modify and delete them. This identifier could be an integer, for example, or a string. We'll suppose it's a string for the sake of the argument.

Let me clarify. In order for the program to "link" a certain identifier to the corresponding actual object, it needs to have some sort of associative container with IDs as keys and their corresponding objects as values, providing thus logarithmic access time.

Now, suppose some method of this class needs access to the identifier. In this case, should the identifier be a field of the class? This seems like the obvious solution. But the problem is that now the identifiers are duplicated: as keys in the associative container, and as fields in each instance. That would imply double the storage necessities and duplicate "management tasks" (i.e., when adding a new object to the associative container, one would need to specify the identifier as both key and field).

Is there a general way to overcome this problem? (Or am I fussing over nothing?) One alternative would be to have the associative container keep references to the ID field as keys. But I don't know how to do that.

class MyClass {
public:
    std::string ID;
    MyClass(string id) : ID(id) {}
}

Then the straightforward approach would be to store a std::map<std::string, MyClass>. I tried to make use of std::reference_wrapper to store references to the IDs, but then the order of the map doesn't work since operator< isn't defined on reference_wrappers:

int main() {
    std::map<reference_wrapper<std::string>, MyClass> myInstances; // error
    MyClass obj("Bob");
    myInstances.insert({obj.ID, obj});
}

Is there a way to do this? Or is it unnecessarily complicated?


 

would work, since both the myInstances[obj.ID] identifier (as in Python object identifier) and the self.ID identifier would point to the same string (so no extra memory would be needed).

Note: I wrote this question in a way that made it seem I'm mainly concerned with the memory usage and ways to optimise this. Rather, my original intention (and my current intention, upon revisiting this question) is to ask for solutions to the maintainability problem: the fact that one has to make sure that a corresponding pair of key (in the associative container) and field (in the object itself) for the name/ID of the object stay in sync.

I have often encountered a situation in which users of a program (not necessarily human, just an external agent) need to be able to reference objects of a class with a certain "external" identifier or name, in order to create, access, modify or delete them. A couple of examples:

  • a command-line application where end-users refer to specific instances by name, e.g. a calculator that deals with geometrical objects
  • a GUI with a dynamically created drop-down list where each item corresponds to an instance

This identifier could be an integer, for example, or a string. We'll suppose it's a string for the sake of the argument.

Let me clarify. In order for the program to "link" a certain identifier to the corresponding actual object, it needs to have some sort of associative container with IDs as keys and their corresponding objects as values.

Now, suppose some method of this class needs access to the identifier; e.g. a prettyPrint method that also prints the object's name. In this case, should the identifier be a field of the class? This seems like the obvious solution. But the problem is that now the identifiers are duplicated: as keys in the associative container, and as fields in each instance. That would imply duplicate "management tasks"—i.e., when adding a new object to the associative container, one would need to specify the identifier as both key and field. It would also entail slightly more memory usage, but this is the least significant of the two problems.

Is there a general approach to this problem? (Or am I fussing over nothing?) 


One alternative would be to have the associative container keep references to the ID field as keys. But I don't know how to do that, at least in a language like C++.

class MyClass {
public:
    std::string name;
    MyClass(string name) : name(name) {}
}

Then the straightforward approach would be to store a std::map<std::string, MyClass>. I tried to make use of std::reference_wrapper to store references to the IDs, but then the order of the map doesn't work since operator< isn't defined on reference_wrappers:

int main() {
    std::map<reference_wrapper<std::string>, MyClass> myInstances; // error
    MyClass obj("Bob");
    myInstances.insert({obj.name, obj});
}

would work, since both the myInstances[obj.ID] identifier (as in Python object identifier) and the self.ID identifier would point to the same string (so no extra memory would be needed).

Edit: this wouldn't work in fact, as strings are immutable (like any other key for a dict).

Tweeted twitter.com/StackSoftEng/status/1104124778884009985
clarify title
Link

Working with human-readable"external" object IDs

added 37 characters in body
Source Link
Loading
Source Link
Loading