Details
Diff Detail
- Repository
- rCOMM Comm
- Lint
Lint Not Applicable - Unit
Tests Not Applicable
Event Timeline
Is it a good practice to create a new class every time a method is invoked? I would guess, we should declare classes outside, construct objects in methods and return the instances. What is the reason behind taking your approach?
I'm not sure about this. I looked around a bit and have not found any information about this. Basically, local classes can be used and I've not seen any big issues with it.
Even when this is a valid language construction, we need to check if it should be used in this context. And currently, it looks like there are no benefits of using this approach compared to an alternative approach.
Currently we have four template methods, with two type parameters and one argument. In each of these methods, we create a local class that uses template type parameters when determining its parent class. None of the classes use function parameter context. So at this point, each of inner classes could be moved outside the function and all the code would compile and work the same.
So at the moment, defining the classes locally has only one advantage: we don't allow anyone to instantiate them outside the function - if that was the intention, then we can consider keeping this approach.
Local classes can be extremely useful when their definition depends on function argument. Currently it's not the case, but maybe this is going to change. What is the plan for these? (even if the code depends on the argument, it could as well be passed to the constructor, though)
To summarize, could you explain why local classes were used in this case? There exist some valid reasons, but at this point this code could be simplified to use normal classes, so I'm wondering what is the plan here.
Yes, the fact that these classes cannot be used outside of these functions is one thing. Another is that we have the implementations in one place. For me, it's easier to read. Please note that these classes contain just one method with the logic, maybe some of them will have some simple state.
Honestly, I do not think this is very important, we can move these classes somewhere, I find them better where they are, it indicates explicitly that they're supposed to be used only in this one specific place, plus we have a code with the logic directly inside of these functions.
I prefer this as is. I assume you prefer the opposite. I guess the fastest option to move forward here is to get an opinion of someone else and proceed with the outcome.
I prefer this as is. I assume you prefer the opposite.
It's not that I have a strong preference for one solution or another. But I do have preference to use the default approach unless there are good reasons to use something different.
the fact that these classes cannot be used outside of these functions is one thing
Agree, this is a valid point
Another is that we have the implementations in one place
Also a good point. But if we created normal classes in this file, it would be also in one place.
For me, it's easier to read
This surprised me. For me it's a lot worse to read. We have a couple of levels of additional indentation - and our experience from CommCoreModule suggests that this is a real issue.
If a local class is short, then the readability would be ok, but here it looks like the opposite will be true.
Please note that these classes contain just one method with the logic, maybe some of them will have some simple state.
That makes sense. We can't use static members inside them but simple state would be ok.
I find them better where they are, it indicates explicitly that they're supposed to be used only in this one specific place, plus we have a code with the logic directly inside of these functions.
Why should they be used only here? Is there something which makes them unusable in other places?
I guess the fastest option to move forward here is to get an opinion of someone else and proceed with the outcome.
I'm not going to block you on this as it looks like you think your approach is better here. I only wanted to hear why is that.
Requesting changes to clarify core dumps issue
services/backup/docker-server/contents/server/src/BackupServiceImpl.cpp | ||
---|---|---|
49–51 ↗ | (On Diff #9834) | Could you describe when such core dumps are possible? How can making the response a member of a class help? |
Ok, thanks. I think we can leave it as is and in a case, the classes grow too much we can move them outside of functions(or for any other reason later on).
Why should they be used only here? Is there something which makes them unusable in other places?
Every one of these classes is created specifically for one grpc call. I don't see any other use cases for them honestly but I may be wrong.
services/backup/docker-server/contents/server/src/BackupServiceImpl.cpp | ||
---|---|---|
49–51 ↗ | (On Diff #9834) | authResponse is a local variable and we're passing it as a ref. Since it's allocated on the stack, once it goes out of scope it will get deallocated. I just wanted the code to compile, didn't test the runtime anyway, but we should address this issue when we'll be implementing and testing the code, that's why I added this comment. |
services/backup/docker-server/contents/server/src/BackupServiceImpl.cpp | ||
---|---|---|
49–51 ↗ | (On Diff #9834) | The code that compiles but fails in runtime is risky - we might forget about it by mistake. I would prefer deleting or commenting this code out. The issue with this approach is that, when a new diff is created, it will somehow modify this code and we would still need to review the code from this diff because currently we know that this doesn't work. It's a lot better when we can clearly differentiate between code that is correct and that isn't. So in this case, we would save ourselves a lot of time, if all the invalid code was replaced by TODO. My guess is that this is only this line and the checks from above can safely stay. |
services/backup/docker-server/contents/server/src/BackupServiceImpl.cpp | ||
---|---|---|
49–51 ↗ | (On Diff #9834) | ok im gonna delete whats below, the point here is to show how more or less the auth manager is supposed to be used. |
Approving because this looks right to me, but I don't have much context on the backup service nor do I have much experience with templates in C++... so keep that in mind
I know @palys-swm already approved, but maybe he can take a final look before landing?
services/backup/docker-server/contents/server/src/BackupServiceImpl.cpp | ||
---|---|---|
50–51 ↗ | (On Diff #10021) | I think this comment was supposed to be deleted? From above: "ok im gonna delete whats below, the point here is to show how more or less the auth manager is supposed to be used." |
services/backup/docker-server/contents/server/src/BackupServiceImpl.cpp | ||
---|---|---|
50–51 ↗ | (On Diff #10021) | Yes, basically protobuf takes care of deleting the object so it's okay to allocate memory for it dynamically and pass a pointer to a set_allocated_ method. I refactored the code so we create pointers. |