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

Applied 'Extract Method' to read() #3

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

david-sackstein
Copy link

This change extracts methods from basic_file_base::read(std::size_t size).
In my opinion this breaks down the logic into independent pieces that are easier to reason about.

  1. It explicitly deals with the case when size==0. The logic is different and should be separate.
  2. It explicitly deals with the case when size==0 and file.size() = 0. The logic is different.
  3. There is no code duplication (read_non_zero() calls read(byte_view).
  4. Encapsulated the logic of get_bigger_size(). Nit. Handled the case where curr_size < 4

True, the file is now longer by 28 lines.
Indeed, in my opinion, some of this logic should be extracted to other headers which should be included by this one.

Copy link
Owner

@eyalz800 eyalz800 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@david-sackstein This is an awesome work, I made some comments here and there but feel free to leave the fixing to me, I will make the necessary changes soon (because I just started to study for my University exam).

} else {
// Reserve the requested size.
data.resize(size);
if (size == 0) {
Copy link
Owner

@eyalz800 eyalz800 Jun 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am taking this idea and have two read overloads, one for reading the entire file and one for reading a specific size. (That is read() and read(std::size_t)).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good. But sometimes I think it is better to be explicit.
I propose read_all().
This is similar to the train of thought that encourages us to write explicit static factories instead of relying on overloaded constructors. Sometimes you can get away with it, but often the variety of argument types is not enough to describe what the method does.

// Nothing to read.
return {};
}
return read_nonzero(bytes_to_read);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not dealing the case where the file is growing along the way. Most likely it can't do any harm but the fact that it is not waiting for the real end of file is troubling me.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you be more explicit? What is the scenario and what should the method be doing in that case that it is not?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the file is growing larger while you read it, this would only read a fixed amount of bytes (the amount of bytes before the grow) and not read until the EOF.

return std::nullopt;
}
auto current_offset = tell();
if (tell() >= file_size) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling tell twice seems risky, in any case, can optimize the two tell calls into one.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course. My bad.

}

template <typename File>
std::size_t basic_file_base<File>::get_bigger_size(std::size_t curr_size) const
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say enlarge_bytes rather than get and then do it from the outside.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean - to replace:
data.resize(get_bigger_size(data.size())); (1)
with
enlarge_bytes(data); (2)
I agree. But personally I still prefer separating the logic of get_bigger_size() and data.resize().
So I might add a method called enlarge_bytes whose implementation is (1) rather than inline get_bigger_size into enlarge_bytes().
I am a SRP guy ; )

if (data.size() == (std::numeric_limits<std::size_t>::max)()) {
// Differentiate between reached the end and not.
std::byte one_byte;
if (1 == read({ &one_byte, 1 })) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would really like to avoid this other read call.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. But a comment might be in order.

@eyalz800
Copy link
Owner

@david-sackstein

  1. I added your change about read_zero and read_nonzero as separate overloads, then I realized there is no need to rename them, so both are named just "read", one is read(std::size_t) and the other is just read(). I wonder about the other changes:
  2. The fix to reading 4GB on a 32 bit platform requires another read which makes the code less pretty where we both know it is not going to work as the process address space is exactly 4GB.
  3. Given point 1 I think the code for read(std::size_t) is now ok, and the read() function remains a little long but handles less cases. In my opinion, separating the read() function further into private functions is going to hurt the readability. It will reduce the readability significantly because the functions will handle a niche logic that will have the reader jump between them to understand the flow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants