Let's say I have a program which uses n big modules:
A) Network/Communication
B) I/O files
C) I/O database
D) GUI
E) ...
Of course, a list of modules could be bigger.
Let's say I want to have some global variable, but with a scope limited to a single module.
As an example, let's say that I/O database module will consist of 10 classes, each representing each table in a database, but it needs some global const state like Name of table A, Columns of table A etc. (as it is a relational database, in table D I may need to use table A).
It is also obvious, that I do not need to access these table names through Network/Communication module. Is there a way to make a variable "globally" accessible only for some part of classes?
Just for clarification - I know that "Global for some part" is a contradiction, but my idea is that I want to keep the accessibility(no need of pointer passing to each object), while limiting the place from where it can be called (for example, limit from global to module scope)
You don't need globals for that, I strongly advise you to learn about dependency injection. Basically you have one "factory" module. And each module has an interface on you can inject an interface that has getters to access the centralized data. (e.g. members of a n instance of a class). This also allows you to test the independent modules using mocks and stubs (e.g. a test class that returns other values). –
Related
We have a common variables in our infrastructure on AWS, planned to be used by several modules. For example subnet ids, vpc id and so on.
To avoid duplication those variable in each module in *.tfvars files. Is that possible make them available from any terraform modules? While modules itself can be isolated from each other.
I think about kind of core module, which can be imported where that common variables needs. But in doubts that module is a right way to do that, as modules intended to have only resources in them, but we need expose only variables. Is it right way to use modules to share variables? Or how you guys cope with this problem? Think it's common or it's bad approach in terraform?)
Thanks.
If you have a set of expressions (including hard-coded literal values) that you want to reuse then it is valid to write a module which only contains input variable declarations, local values, and output values as a way to model that.
The simplest form of this would be a module that only contains output blocks whose values are hard-coded literal values, like this:
output "example" {
value = "result"
}
The official module hashicorp/subnets/cidr is an example of that: it doesn't declare any resources of its own, and instead it just encapsulates some logic for calculating a set of subnets based on some input variables.
This is a special case of Data-only Modules where the data comes from inside the module itself, rather than from data sources. A nice thing about modelling shared data in this way is that if you later decide to calculate those results automatically based on data sources then you'll be able to do so, while keeping the details encapsulated. For example, if you define a module which takes an environment name as an input variable and returns derived settings about that environment, the module could contain local logic to calculate those results today but could later determine some of those settings by fetching them from a prescribed remote location, such as AWS SSM Parameter store, if the need arises.
I'm writing this, well, call it a library I guess. It offers a set of global variables of type MyType. Now, I want to write the source of each of these MyType's in its own .cpp and .h files, unaware of all the rest, without needing some central header file saying MyType* offerings = { &global1, &global2, /*... */ }.
Now, had these been different classes I want to be able to instantiate, I would want to use a factory pattern; but here they're all of the same type, and I don't need to instantiate anything. I would think each variable needs to be 'registered' into a global array (or unordered set) from somewhere in its sources.
So, what's the idiomatic way to do this?
You could take a look at the Registry Pattern and create a manager for your filesystem or folder that will manage these objects.
The Registry could have everything related to Filesystem Handling so you insert your object names and properties in a model in one config file or database. The registry could look up that and instantiate your objects on runtime.
Now you would need a mechanism to communicate this objects to the rest of the system. But if your objects are not going to change then just a registry with compile time objects would do.
The Registry is a pattern to handle global objects in a similar fashion to the singleton.
Developing a modular application, I want to inject some helper classes into each module. This should happen automated. Note that my helpers have state, so I can't just make them static and include them where needed.
I could store all helpers in a map with a string key and make it available to the abstract base class all modules inherit from.
std::unordered_map<std::string, void*> helpers;
RendererModule renderer = new RendererModule(helpers); // argument is passed to
// base class constructor
Then inside a module, I could access helpers like this.
std::string file = (FileHelper*)helpers["file"]->Read("C:/file.txt");
But instead, I would like to access the helpers like this.
std::string file = File->Read("C:/file.txt");
To do so, at the moment I separately define members for all helpers in the module base class, and set them for each specific module.
FileHelper file = new FileHelper(); // some helper instances are passed to
// multiple modules, while others are
// newly created for each one
RendererModule renderer = new RendererModule();
renderer->File = file;
Is there a way to automate this, so that I don't have to change to module code when adding a new helper to the application, while remaining with the second syntax? I an not that familiar with C macros, so I don't know if they are capable of that.
I think I see what your dilemma is, but I have no good solution for it. However, since there are no other answers, I will contribute my two cents.
I use the combination of a few strategies to help me with these kinds of problems:
If the helper instance is truly module-specific, I let the module itself create and manage it inside.
If I don't want the module to know about the creation or destruction of the helper(s), or if the lifetime of the helper instance is not tied to the module that is using it, or if I want to share a helper instance among several modules, I create it outside and pass the reference to the entry-point constructor of the module. Passing it to the constructor has the advantage of making the dependency explicit.
If the number of the helpers are high (say more than 2-3) I create an encompassing struct (or simple class) that just contains all the pointers and pass that struct into the constructor of the module or subsystem. For example:
struct Platform { // I sometimes call it "Environment", etc.
FileHelper * file;
LogHelper * log;
MemoryHelper * mem;
StatsHelper * stats;
};
Note: this is not a particularly nice or safe solution, but it's no worse than managing disparate pointers and it is straightforward.
All the above assumes that helpers have no dependency on modules (i.e. they are on a lower abstraction of dependency level and know nothing about modules.) If some helpers are closer to modules, that is, if you start to want to inject module-on-module dependencies into each other, the above strategies really break down.
In these cases (which obviously happen a lot) I have found that a centralized ModuleManager singleton (probably a global object) is the best. You explicitly register your modules into it, along with explicit order of initialization, and it constructs all the modules. The modules can ask this ModuleManager for a reference to other modules by name (kind of like a map of strings to module pointers,) but they do this once and store the pointers internally in any way they want for convenient and fast access.
However, to prevent messy lifetime and order-of-destruction issues, any time a module is constructed or destructed, the ModuleManager notifies all other modules via callbacks, so they have the chance to update their internal pointers to avoid dangling pointers and other problems.
That's it. By the way, you might want to investigate articles and implementations related to the "service locator" pattern.
I have a game that consists of few modules.
One of them is database module.
I want to make it something like that:
Database{
public:
save(&Object); //all my classes in the all modules inherit from Object
load(&Object);
};
What would be the best way to make that module independent from other modules (other modules will store data in Database using save and load functions)?
I consider few solutions:
All objects have something like serialize() method that is inherited from Object class (analogy to Java). Database use that method to get the string and save it. Obvious disadvantages are: all objects have to implement new method and it won't be optimum to save strings (not knowing about the classes' structure).
Make 'manifests' for all the classes (in e.g. text file that will be send to Database). That manifests will describe what the structure of class is (e.g. one string, two double, one rare use int). Disadvantage is flexibility - changing the classes in other modules will have affect on manifests.
All classes has own save and load methods and Database use them. I don't want it, because all classes would have to know about database type and save and load should be in Database class, not distributed in the whole code (it's a main point to make such a module).
Database knows about all other modules (and will know how to save all objects). Bad thing here is a lot of dependencies. Changes in any of modules will affect the Database.
Which way will be good? Or maybe there's a better option?
One solution I've come across is to have all Object subclasses implement a virtual void serialize(ISerializer& serializer) method.
ISerializer would have pure virtual methods like void onInt(int value), void onString(const char* string) etc to be called by the Object subclass inside its serialize()-method. Your Database module could implement ISerializer in two separate classes, DatabaseReader and DatabaseWriter. Later on you could add ObjectInspectionFileDumper, OnScreenObjectStateDebugger or NetworkWriter that also implement ISerializer, but in other modules. Each object only needs to implement the serialize()-method once to gain all those possibilities for extension.
Pros:
Reading and writing is pretty much guaranteed to match up as long as you don't read data for an old version of an object without some kind of versioning scheme on top.
This is an orthogonal design, where the number of Object types and Serializer types can grow independently of each other.
Cons:
Mainly some virtual function overhead, if that is an issue for your project. This isn't something you will typically be doing much during regular gameplay though.
Later, you might come across things you want to call Objects which you don't want to serialize, then it could make sense to separate that out into an ISerializable interface class, only containing the pure virtual serialize()-method. To accommodate serializers where it matters (like debug serializers), you might want to change to void onInt(const char* name, int value) etc instead.
HTH
I have a class, let's say Person, which is managed by another class/module, let's say PersonPool.
I have another module in my application, let's say module M, that wants to associate information with a person, in the most efficient way. I considered the following alternatives:
Add a data member to Person, which is accessed by the other part of the application. Advantage is that it is probably the fastest way. Disadvantage is that this is quite invasive. Person doesn't need to know anything about this extra data, and if I want to shield this data member from other modules, I need to make it private and make module M a friend, which I don't like.
Add a 'generic' property bag to Person, in which other modules can add additional properties. Advantage is that it's not invasive (besides having the property bag), and it's easy to add 'properties' by other modules as well. Disadvantage is that it is much slower than simply getting the value directly from Person.
Use a map/hashmap in module M, which maps the Person (pointer, id) to the value we want to store. This looks like the best solution in terms of separation of data, but again is much slower.
Give each person a unique number and make sure that no two persons ever get the same number during history (I don't even want to have these persons reuse a number, because then data of an old person may be mixed up with the data of a new person). Then the external module can simply use a vector to map the person's unique number to the specific data. Advantage is that we don't invade the Person class with data it doesn't need to know of (except his unique nubmer), and that we have a quick way of getting the data specifically for module M from the vector. Disadvantage is that the vector may become really big if lots of persons are deleted and created (because we don't want to reuse the unique number).
In the last alternative, the problem could be solved by using a sparse vector, but I don't know if there are very efficient implementations of a sparse vector (faster than a map/hashmap).
Are there other ways of getting this done?
Or is there an efficient sparse vector that might solve the memory problem of the last alternative?
I would time the solution with map/hashmap and go with it if it performs good enough. Otherwise you have no choice but add those properties to the class as this is the most efficient way.
Alternatively, you can create a subclass of Person, basically forward all the interface methods to the original class but add all the properties you want and just change original Person to your own modified one during some of the calls to M.
This way module M will see the subclass and all the properties it needs but all other modules would think of it as just an instance of Person class and will not be able to see your custom properties.
The first and third are reasonably common techniques. The second is how dynamic programming languages such as Python and Javascript implement member data for objects, so do not dismiss it out of hand as impossibly slow. The fourth is in the same ballpark as how relational databases work. It is possible, but difficult, to make relational databases run the like the clappers.
In short, you've described 4 widely used techniques. The only way to rule any of them out is with details specific to your problem (required performance, number of Persons, number of properties, number of modules in your code that will want to do this, etc), and corresponding measurements.
Another possibility is for module M to define a class which inherits from Person, and adds extra data members. The principle here is that M's idea of a person differs from Person's idea of a person, so describe M's idea as a class. Of course this only works if all other modules operating on the same Person objects are doing so via polymorphism, and furthermore if M can be made responsible for creating the objects (perhaps via dependency injection of a factory). That's quite a big "if". An even bigger one, if nothing other than M needs to do anything life-cycle-ish with the objects, then you may be able to use composition or private inheritance in preference to public inheritance. But none of it is any use if module N is going to create a collection of Persons, and then module M wants to attach extra data to them.