Live data from Hacker News

Writing Well-Documented Code – Learn from Examples

codecatalog.org

101–110 of 153 posts

Re: Writing Well-Documented Code – Learn from Examples

#101

For the first example with conditions, I much prefer rolling the "why" of the comments into boolean variable names where possible e.g. // We still have burst budget for *all* tokens requests. if self.one_time_burst >= tokens { ... } else { // We still have burst budget for *some* of the tokens requests. becomes something like (I'm missing context but you get the idea): enoughBudgetForAllTokenRequests = self.one_time_…

Long variable names mean you perceive your simple code as being too complicated. It's an if statement. I would refactor your long variable name to something more compact like enough_budget.

[deleted]

Re: Writing Well-Documented Code – Learn from Examples

#102
IMO, comments are needed when the code itself can't express something necessary to understand its overall function.

I've found that hence e.g. for rather complex statements where the code isn't lacking information, not commenting is the correct approach.

Whereas sometimes, when I'm forced to write exceptional code because of e.g. a workaround, a comment can nicely introduce my future self and other readers to the context.

Re: Writing Well-Documented Code – Learn from Examples

#103
I have a really similar motivation behind a project that aims to teach Jetpack Compose in the same fashion and funny enough, the name is also pretty similar to the title of this thread - Learn Jetpack Compose By Example. You can find it here - https://github.com/vinaygaba/Learn-Jetpack-Compose-By-Exampl...

There's a ton of comments in every example (even though they might be redundant across the examples) and the idea is that you should be able to learn this new framework by merely reading through the examples.

Re: Writing Well-Documented Code – Learn from Examples

#104
post #36

Personally I found most of those examples to be not great. I think they would be improved better names overall, more well named private methods and most importantly well structured companion test classes proving the behavior. I really dont want to read another developers comments on their mental state while I am feverishly debugging their code during a 3am page. The number of times I have been misled by an outdated c…

Yup, the rate limiter comments are unhelpful. A top level comment explaining the idea is fine (and very useful) but code should largely be self documenting.

Re: Writing Well-Documented Code – Learn from Examples

#105
More and more I feel these huge comment blocks with the following inline comments sprinkled everywhere should really be a separate documentation file with its own structure where anyone not familiar enough can get up to speed, and understand the core principles behind the code written here.

For instance in the firecracker example, they don’t write 3 pages of block comments to explain the token bucket algorithm (or do they?), as anyone could go read the wikipedia article instead.

Comments living with the code have their benefits, but here I can’t imagine these huge comment blocks or algorithm related warnings get revised anytime outside of project wide refactoring.

What we also miss by having these comments inlined is the higher perspective of how it works with the other classes or how it fits in their running context. Anything that spans multiple class and/or methods makes it difficult to decide where to put the info and what scope it should have. People usually end up explaining the same things at 3 or 4 places in sublty different ways, which makes no one happy.

An exemple of that, this struct description

> /// TokenBucket provides a lower level interface to rate limiting with a /// configurable capacity, refill-rate and initial burst.

This comment is hinting at a sequence where ‘TokenBucket’ needs to be a configurable lower level interface. But what is that sequence, what needs it to be lower level, is there higher level interfaces ? I’ll sure end up spelunking the rest of the doc to get answers to that.

Re: Writing Well-Documented Code – Learn from Examples

#107
post #36

Personally I found most of those examples to be not great. I think they would be improved better names overall, more well named private methods and most importantly well structured companion test classes proving the behavior. I really dont want to read another developers comments on their mental state while I am feverishly debugging their code during a 3am page. The number of times I have been misled by an outdated c…

That is how I feel about these comments. In a vacuum I like them and when I bump into a piece of 10 year old code commented like this it is great. There is one caveat however, they have to be meticulously maintained and always updated to reflect every change made to the code. It is a huge caveat because more often than not the comments are out dated and no longer reflect the actual code and at that point they are det…

That's why Knuth had the idea of creating literate programs where documentation and code was maintained in a single block. Unfortunately, this idea was never used in large scale.

Re: Writing Well-Documented Code – Learn from Examples

#108
I was not very impressed by the token bucket example. Firstly, it is totally ridiculous to need to write your own implementation of gcd and the comment is silly and unnecessary.

Secondly, the implementation for the token bucket seems to just be bad. A simpler implementation is as follows:

- Input number of tokens and refill time.

- Output the constant state describing the limiter: the max number of tokens and the time to get a single token (= refill time / size, ignoring rounding issues which shouldn’t generally matter if your times are in nanos)

- The only mutable state is a single time instant: the time when the limiter becomes full

- to attempt to take a token, compute max(0,full_time - now) / new_token_time and if this is less than or equal to the size of the bucket minus the number of tokens you want, you may withdraw and set full_time := max(full_time, now) + tokens_to_withdraw * new_token_time

If that division is concerning then you should either attempt to withdraw from the rate limiter less frequently or you should not be using one at all.

The rest of the code is about scheduling events to happen when there are free tokens in the ratelimiter. This is a different problem and also over-complicated. You should either poll and retry periodically with your most important event (rather than whatever event you thought was most important when the bucket became empty) though you then want to be careful about stale tasks never running, or you should just have a queue of pairs (Task, cost) where cost is an int. after withdrawing tokens from the ratelimiter or when the queue transitions from empty to non-empty, peek the top item and set a timer for rl.full_time - rl.new_token_time * (rl.size - cost) and when the timer fires (or immediately if the time was in the past) you can dequeue, withdraw cost tokens, and run that top task (then repeat.)

Re: Writing Well-Documented Code – Learn from Examples

#109

For the first example with conditions, I much prefer rolling the "why" of the comments into boolean variable names where possible e.g. // We still have burst budget for *all* tokens requests. if self.one_time_burst >= tokens { ... } else { // We still have burst budget for *some* of the tokens requests. becomes something like (I'm missing context but you get the idea): enoughBudgetForAllTokenRequests = self.one_time_…

I prefer this too, but sometimes poor type-narrowing support hinders it. For example, TypeScript only recently added support for aliased type-narrowing:

https://devblogs.microsoft.com/typescript/announcing-typescr...

Re: Writing Well-Documented Code – Learn from Examples

#110

I had a lot of trouble reading that code. I kept getting distracted by the comments and missed the code. The code seems pretty self-explanatory. I have some changes I would make, but they really depend on performance vs depth (modulo the burst vs budget bug). // Hit the bucket bottom, let's auto-replenish and try again. self.auto_replenish(); Is ugly. Why repeat in English exactly what the code says? I don't even kno…

If we change the code, getting rid of if statements, it's easier to see what happens by removing if's.

I've changed BucketReduction to be a pair, and fixed the strange behavior on error. Swapping "fromBurst" and "auto_replenish" would reduce the number of throttling events. This solution does have more branches than the original, hence readability vs performance. It's still not exception safe, auto_replenish could throw and leave the state undefined.

    BucketReduction reduce(long tokens) {
        long fromBurst = min(tokens, burst);
        burst -= fromBurst;
        tokens -= fromBurst;

        if (tokens > budget) {
            auto_replenish();
        }

        long fromBudget = min(tokens, budget);
        budget -= fromBudget;
        tokens -= fromBudget;

        long totalConsumed = fromBurst + fromBudget;
        if (tokens == 0) {
            return new BucketReduction(Success, totalConsumed);
        }

        if (totalConsumed + tokens > size) {
            return new BucketReduction(OverConsumption, totalConsumed);
        }

        return new BucketReduction(Failure, totalConsumed);
    }
Post reply on HN