I couldn't review Capy+Corosio in time for the Boost review, so I only reviewed Capy. I'll leave the feedback for Corosio here instead. I know it's too late for the Boost review, but I still reviewed Corosio because I'm very excited about it and just wanted to learn about it sooner or later. I'll leave everything here in a single issue because most are too small to deserve an issue. It's a shame I couldn't review both libraries in time, because now the split between the two libraries makes much more sense to me (although I think the documentation still doesn't explain it well) and how I could use them separately. I also find this library much more exciting than the other one.
For whatever reason, I think the documentation for Corosio was better than the documentation for Capy. The documentation for Capy is a bit confusing, while the documentation for Corosio is much clearer and more focused, so I think that helped maintain its coherence. I also found the Corosio design less controversial than Capy, once the design patterns in Capy are taken for granted. I'm also very excited to use the library, and it's refreshing to see things like auto [ec] = co_await corosio::delay(500ms); where I don't have to construct a timer explicitly and keep track of it, and so many other patterns that look like this one.
Exposition links
The library is not using our own Antora extension for links to the reference. This makes it hard to navigate the documentation and get details on what library classes do. Also, very often the documentation describes the signature inline in the exposition, and it's not matching or drifting from the real signature. It's also repetitive. All of that could be fixed easily by just using the extension.
The documentation hierarchy
The documentation follows a hierarchy, with very similar content explained three times:
- Networking Tutorial (Without reference to the library)
- As tutorials
- Guide (with the concepts of the library finally being presented)
Despite what the titles suggest, the tutorials are more like examples and are not typically explained systematically. The guide is a tutorial anyway, and the networking tutorial covers the exact same concepts as the library, so the reader has to read the same content three times (or maybe 2.5 times because the tutorials, which are actually more like examples, don't cover everything).
For the first time in Networking Tutorial, the content doesn't reference the library at all, and the user has to go through hours of content before even hearing about the library. Then in the the tutorials feel like things are not being explained systematically. I would suggest that those three parent sections could be fused into a single section that covers all the concepts involved in networking. For each concept, we already present the abstractions in the library to work with that concept and manipulate and represent objects related to that concept. This way, the documentation would be much shorter.
In the networking tutorial, despite not discussing the library yet, many concepts are presented as curiosities that the reader will later will find out are not directly related to the library. That makes it hard for the reader to get into the actual content about the library. Some concepts are probably even in the scope of the library because they're much higher or lower level so they're relevant to discuss only in terms of how they could be considered when optimizing performance but there's no abstraction for them in the library to be discussed later. Even many levels of the networking protocol are not really related to the library, in the sense that they're already too abstract at the operating system level, so the user doesn't have to worry about it. They could be nice content for admonitions but the library doesn't have abstractions for them. Maybe they could just be omitted in many cases.
This hierarchy is also not the pattern we typically use in our libraries (meaning cppalliance libraries, like Boost.JSON, Boost.URL, etc), where the typical pattern is going through the library concepts interleaved with an explanation about the topic and a hierarchy that ensures it's goal-oriented and also presents the simpler concepts first.
Tutorials
The Echo Server tutorial defines workers, whereas the following HTTP client tutorial doesn't. Of course, you can infer from the context that you have one worker for each connection to a client. The reason the second example doesn't need a worker is that it's just a single connection from a single client. But if the person isn't used to how servers work, it's not very clear that a worker represents a client or client-related data, or why the client doesn't need any workers.
The TLS Context tutorial is not very goal-oriented or very instructive. It's very dense at times. Some subsections have almost no content (in which case, if intentional, could be replaced with just the complete example without any sections). They just show a lot of code without explaining what's happening or why that content is relevant rather than something else. The hierarchy doesn't make sense. Everything's flat rather than hierarchical, with each parent level explaining what the child concepts would be.
In the Hash Server tutorial, the table says run_async( ex )( task ) should be called from outside a coroutine, but an example right above it is calling it from a coroutine.
In general, I'm very excited about the tutorials, especially the "Reconnect with Exponential Backoff" tutorial. Implementing that with ASIO would be trivial but annoying.
Guide
The hierarchy here is very different from other Boost libraries, especially our own libraries. We have a networking tutorial, and then we have tutorials. In the guide, we were about to see the same content for the third time. The expectation here is that, although we would be discussing the same content for the third time, this time it would at least be presented in a way that shows the library concepts. That didn't happen. The very first page has almost no code showing Corosio at all. The other pages have a bit of code, but on many of them, most of the content isn't about the library yet. It should be, because this is the very last parent section that can be about the library. This "TCP/IP Networking" is also extremely similar to the first pages of the Networking Tutorial. Part of the solution is simply deleting the page "TCP/IP Networking," since I'm pretty sure all of this information is already in the Networking Tutorial.
The page on "Concurrent Programming" could have more examples using the library as well, or just be moved elsewhere. The content of the "Concurrent Programming" page is already discussed in depth in the Capy documentation and is not what this library is about (because of how the split was made, that kind of went into Capy). If there is any content here that is missing from the Capy documentation, it should probably be described there anyway. As long as concepts for which only Corosio is concerned, maybe this could be interleaved with the documentation about Corosio, and then the concepts would be introduced as an admonition or in passing, as Corosio needs those concepts to explain something else related to the library. The main point is that the content of all the library has to come in this parent section because it's the last section the documentation has for that.
Also, the "Resuming Through the Right Executor" section on this page makes assumptions about the reader's knowledge of io_context that are only explained on a later page, "I/O Context". I don't know the best way to fix that if there's a circular dependency between concepts being presented, but I don't think that's the case. This page also starts using the term "strands" without defining it first (even though it'll ultimately say strands aren't relevant in Corosio), which is odd given that the documentation explains everything in depth here. Many "simpler" concepts, like IP addresses, have many pages just to define what they are and how they work. Sections like "Work Tracking" could either include a motivating example, or at least a description of one, or simply be removed as functionality that doesn't need to be in the exposition.
At some point, the pages under "Guide" have the opposite problem of the initial pages there. While the initial pages replicate content already explained elsewhere and make little reference to the library, some later pages have the opposite problem: they reference the library too much and don't explain what's happening. Sometimes sections have almost no exposition, and they're not trying to explain any specific concept at all. They're just listing all library functionality as if it were some kind of reference.
In the section "Example: HTTP Response Reading" of the “Composed Operations" page, the example is quite weird because it says it's about HTTP response reading, but there's nothing particularly special about it that makes it related to HTTP.
On the "TLS Encryption" page, the "Plain and Encrypted Connections" example isn't very good. If they're really identical, at the very least, this should use a template (potentially constrained on Stream) that takes the Stream. Or maybe there should be some kind of any_stream in the library, but I suspect you considered the idea and already decided it wasn't worth it. The "Platform Support" would probably work better with a table.
The page on "Unix Domain Sockets" makes it seem like this feature is only available on Unix, but it then mentions, out of nowhere, how it behaves on Windows a few times. The abbreviation for I/O completion ports (IOCP) is also mentioned without being defined.
The "UDP Sockets" page is located at a weird position in the hierarchy. Other parent pages that discuss the protocols describe it much earlier, next to TCP. Typically, even before TCP.
Thank you for the library again. I've very excited about it.
I couldn't review Capy+Corosio in time for the Boost review, so I only reviewed Capy. I'll leave the feedback for Corosio here instead. I know it's too late for the Boost review, but I still reviewed Corosio because I'm very excited about it and just wanted to learn about it sooner or later. I'll leave everything here in a single issue because most are too small to deserve an issue. It's a shame I couldn't review both libraries in time, because now the split between the two libraries makes much more sense to me (although I think the documentation still doesn't explain it well) and how I could use them separately. I also find this library much more exciting than the other one.
For whatever reason, I think the documentation for Corosio was better than the documentation for Capy. The documentation for Capy is a bit confusing, while the documentation for Corosio is much clearer and more focused, so I think that helped maintain its coherence. I also found the Corosio design less controversial than Capy, once the design patterns in Capy are taken for granted. I'm also very excited to use the library, and it's refreshing to see things like
auto [ec] = co_await corosio::delay(500ms);where I don't have to construct a timer explicitly and keep track of it, and so many other patterns that look like this one.Exposition links
The library is not using our own Antora extension for links to the reference. This makes it hard to navigate the documentation and get details on what library classes do. Also, very often the documentation describes the signature inline in the exposition, and it's not matching or drifting from the real signature. It's also repetitive. All of that could be fixed easily by just using the extension.
The documentation hierarchy
The documentation follows a hierarchy, with very similar content explained three times:
Despite what the titles suggest, the tutorials are more like examples and are not typically explained systematically. The guide is a tutorial anyway, and the networking tutorial covers the exact same concepts as the library, so the reader has to read the same content three times (or maybe 2.5 times because the tutorials, which are actually more like examples, don't cover everything).
For the first time in Networking Tutorial, the content doesn't reference the library at all, and the user has to go through hours of content before even hearing about the library. Then in the the tutorials feel like things are not being explained systematically. I would suggest that those three parent sections could be fused into a single section that covers all the concepts involved in networking. For each concept, we already present the abstractions in the library to work with that concept and manipulate and represent objects related to that concept. This way, the documentation would be much shorter.
In the networking tutorial, despite not discussing the library yet, many concepts are presented as curiosities that the reader will later will find out are not directly related to the library. That makes it hard for the reader to get into the actual content about the library. Some concepts are probably even in the scope of the library because they're much higher or lower level so they're relevant to discuss only in terms of how they could be considered when optimizing performance but there's no abstraction for them in the library to be discussed later. Even many levels of the networking protocol are not really related to the library, in the sense that they're already too abstract at the operating system level, so the user doesn't have to worry about it. They could be nice content for admonitions but the library doesn't have abstractions for them. Maybe they could just be omitted in many cases.
This hierarchy is also not the pattern we typically use in our libraries (meaning cppalliance libraries, like Boost.JSON, Boost.URL, etc), where the typical pattern is going through the library concepts interleaved with an explanation about the topic and a hierarchy that ensures it's goal-oriented and also presents the simpler concepts first.
Tutorials
The Echo Server tutorial defines workers, whereas the following HTTP client tutorial doesn't. Of course, you can infer from the context that you have one worker for each connection to a client. The reason the second example doesn't need a worker is that it's just a single connection from a single client. But if the person isn't used to how servers work, it's not very clear that a worker represents a client or client-related data, or why the client doesn't need any workers.
The TLS Context tutorial is not very goal-oriented or very instructive. It's very dense at times. Some subsections have almost no content (in which case, if intentional, could be replaced with just the complete example without any sections). They just show a lot of code without explaining what's happening or why that content is relevant rather than something else. The hierarchy doesn't make sense. Everything's flat rather than hierarchical, with each parent level explaining what the child concepts would be.
In the Hash Server tutorial, the table says
run_async( ex )( task )should be called from outside a coroutine, but an example right above it is calling it from a coroutine.In general, I'm very excited about the tutorials, especially the "Reconnect with Exponential Backoff" tutorial. Implementing that with ASIO would be trivial but annoying.
Guide
The hierarchy here is very different from other Boost libraries, especially our own libraries. We have a networking tutorial, and then we have tutorials. In the guide, we were about to see the same content for the third time. The expectation here is that, although we would be discussing the same content for the third time, this time it would at least be presented in a way that shows the library concepts. That didn't happen. The very first page has almost no code showing Corosio at all. The other pages have a bit of code, but on many of them, most of the content isn't about the library yet. It should be, because this is the very last parent section that can be about the library. This "TCP/IP Networking" is also extremely similar to the first pages of the Networking Tutorial. Part of the solution is simply deleting the page "TCP/IP Networking," since I'm pretty sure all of this information is already in the Networking Tutorial.
The page on "Concurrent Programming" could have more examples using the library as well, or just be moved elsewhere. The content of the "Concurrent Programming" page is already discussed in depth in the Capy documentation and is not what this library is about (because of how the split was made, that kind of went into Capy). If there is any content here that is missing from the Capy documentation, it should probably be described there anyway. As long as concepts for which only Corosio is concerned, maybe this could be interleaved with the documentation about Corosio, and then the concepts would be introduced as an admonition or in passing, as Corosio needs those concepts to explain something else related to the library. The main point is that the content of all the library has to come in this parent section because it's the last section the documentation has for that.
Also, the "Resuming Through the Right Executor" section on this page makes assumptions about the reader's knowledge of io_context that are only explained on a later page, "I/O Context". I don't know the best way to fix that if there's a circular dependency between concepts being presented, but I don't think that's the case. This page also starts using the term "strands" without defining it first (even though it'll ultimately say strands aren't relevant in Corosio), which is odd given that the documentation explains everything in depth here. Many "simpler" concepts, like IP addresses, have many pages just to define what they are and how they work. Sections like "Work Tracking" could either include a motivating example, or at least a description of one, or simply be removed as functionality that doesn't need to be in the exposition.
At some point, the pages under "Guide" have the opposite problem of the initial pages there. While the initial pages replicate content already explained elsewhere and make little reference to the library, some later pages have the opposite problem: they reference the library too much and don't explain what's happening. Sometimes sections have almost no exposition, and they're not trying to explain any specific concept at all. They're just listing all library functionality as if it were some kind of reference.
In the section "Example: HTTP Response Reading" of the “Composed Operations" page, the example is quite weird because it says it's about HTTP response reading, but there's nothing particularly special about it that makes it related to HTTP.
On the "TLS Encryption" page, the "Plain and Encrypted Connections" example isn't very good. If they're really identical, at the very least, this should use a template (potentially constrained on Stream) that takes the Stream. Or maybe there should be some kind of any_stream in the library, but I suspect you considered the idea and already decided it wasn't worth it. The "Platform Support" would probably work better with a table.
The page on "Unix Domain Sockets" makes it seem like this feature is only available on Unix, but it then mentions, out of nowhere, how it behaves on Windows a few times. The abbreviation for I/O completion ports (IOCP) is also mentioned without being defined.
The "UDP Sockets" page is located at a weird position in the hierarchy. Other parent pages that discuss the protocols describe it much earlier, next to TCP. Typically, even before TCP.
Thank you for the library again. I've very excited about it.