Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enforce const correctness #38

Open
valentjn opened this issue Mar 11, 2019 · 9 comments
Open

Enforce const correctness #38

valentjn opened this issue Mar 11, 2019 · 9 comments
Labels
discussion General problem for which possible solutions need to be discussed

Comments

@valentjn
Copy link
Member

In GitLab by @lettrich on Nov 17, 2016, 14:28

It is generally considered good practice to use the constwhenever possible. All guidelines on C++ programming agree on that. Not only does it help to identify input and output parameters, it also helps to ensure that certain side effects do not occur which can be very hard to find. And the compiler enforces it automatically during compilation with zero runtime overhead. As Most interfaces insgpp::base have already stabilized and we know which parameters are input and output parameters and which member functions actually change the state of of the object I would see it as a good measure to improve overall code quality without breaking any of the code which builds on top of it. What are the thoughts on that ?

PS: I'd gladly help implement the necessary changes!

@valentjn valentjn added the discussion General problem for which possible solutions need to be discussed label Mar 11, 2019
@valentjn
Copy link
Member Author

In GitLab by @valentjn on Nov 17, 2016, 15:00

My two cents:

  1. I wouldn't say any part of sgpp::base has stabilized. I'm only involved for 2.5 years, but as far as I can tell, quite a lot of restructuring and refactoring was done, not only since SG++'s beginnings in 2008, but also in those two years. Ok, there is indeed some code which hasn't been touched in years, but not the core things. And the future's no one's to see 😄
  2. I generally agree that const correctness is a good thing. In fact, all of my code (i.e., sgpp::optimization) uses it whenever possible, and I already did some efforts to introduce some const correctness in sgpp::base (search the log, examples include sgpp::base::Grid).
  3. In an ideal world, you would be completely right. But unfortunately, I think const correctness cannot be enforced all the way in all situations, at least not in a non-intrusive way. Just one example is GridStorage::getSequenceNumber. The GridPoint& index argument cannot be made const in the current implementation: GridStorage::grid_map::find needs a const reference to a GridPoint*, and if we made the index argument constant, the given &index would be a const GridPoint*, which of course is incompatible. I suppose that one would need some serious work to fix that.
  4. Besides, const correctness isn't that important in the sense that all non-const-correct code is necessarily bad. My stance is that I use consts whenever I can, but when I can't, due to whatever reason, then I don't.

Are there any specific code areas you thought about for adding const correctness?

@valentjn
Copy link
Member Author

In GitLab by @valentjn on Nov 17, 2016, 15:14

Oh yeah, and w.r.t. the "improve overall code quality without breaking any of the code which builds on top of it": That's only true if you're talking about adding consts to variable declarations in function bodies. If you mean adding consts to argument or return types, it will indeed likely break code building on top of it. Where return types are usually no problem, but argument types are.

That's just the thing about const correctness: If you use it for some code, then you have to use it for all the code which depends on that code. That's why I spent quite some time coding when I was adding some consts in the core of sgpp::base.

@valentjn
Copy link
Member Author

In GitLab by @lettrich on Nov 18, 2016, 18:08

Thank you for you for sharing your experiences and your opinion. I agree with the points you made - especially 4. I opened this "issue" more as a discussion/survey to see how much it matters to the main contributors and how much I should car as ultimately my goal is to write good code and help the project (especially parts of sgpp::datadriven) to improve in features , quality and usability.

As far as adding const correctness, I have not seen too many places in sgpp::base(at least the classes I work with) where I would want to add const but on the other hand many more member functions in sgpp::datadriven that could be revised.

@valentjn
Copy link
Member Author

In GitLab by @MLocs on Dec 14, 2016, 13:44

I think, to move this discussion forward, we need to consider individual parts. And I just happen to have a good example 😉 : the evaluation of the basis functions is symantically stateless and hence should not change the grid structure. I started to add const modifier to the function and then noticed that BsplineClenshawCurtisBasis evaluation actually does. @valentjn: I may be working on the outdated version of the code, is it something that you are using? Is the evaluation is logically const and the user does not see the changes?

@valentjn
Copy link
Member Author

In GitLab by @lettrich on Dec 22, 2016, 14:30

@MLocs I am not entirely sure which member functions you are talking about but the concept sounds logical. Maybe my observation is related to this. I have noticed this for sgpp::base::operationMultipleEval. The eval member function takes the surpluses vector and writes into a result vector. As surpluses should not be changed by the evaluation process, I think the argument should be const. I also think that the eval member function from a conceptual perspective should not change the state of the operationMultipleEval object und thus be a const member function.

@valentjn
Copy link
Member Author

In GitLab by @valentjn on Dec 22, 2016, 14:42

Oops, sorry @MLocs, that one slipped through my attention (blame the many MR mails). No, it's not an outdated version of the code. I agree with both of you, the evaluation should logically be a const method (i.e., user doesn't see the state's changes), but BsplineClenshawCurtisBasis stores some temporary vectors as member variables in the object. Otherwise, for each eval call these objects would've be allocated and de-allocated on the stack, which should be much slower. Downsides of that approach are that you can't use const and that you get issues when trying to parallelize with only one basis object. I guess it's the old discussion "fast/efficient code" vs. "good code" ("good" from a software engineering point of view). I'm not sure if there's an alternative solution that's both fast and good.

@valentjn
Copy link
Member Author

In GitLab by @MLocs on Dec 23, 2016, 13:22

Yes, I addressed both of your concerns (I think) in my current branch as a side note to what I was currently doing 😉
@valentjn The solution was to declare your cache member variables as mutable. This way I tell compiler that those are not seen outside of the class and the methods modifying the cache can still be logically constant.

@valentjn
Copy link
Member Author

In GitLab by @valentjn on Dec 23, 2016, 13:33

Ah--lo and behold! The endless depths of the many mysteries of C++ provide a solution for this very problem (usually the depths introduce even more mysteries). I did not know the mutable keyword. Guess it's never too late to learn new things 😄

Thanks and Merry Christmas Valeriy (I just saw I forgot it in the e-mail).

@valentjn
Copy link
Member Author

In GitLab by @MLocs on Dec 23, 2016, 13:40

Merry Christmas to you too! 🎅 :mother_christmas: 🎄 🎁

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion General problem for which possible solutions need to be discussed
Development

No branches or pull requests

1 participant