1. 2

    Sounds like this new MacBook would make a beast of a Gentoo machine :D

    1. 5

      One area that seems missing in all this is something for user focused network diagnostics (think ifconfig / ping / traceroute). Is there anything that can show me at a glance multiple OSI levels why something is broken. Say I just know that I can’t see google.com. It would be nice to have 1 command that shows that this is because {cable_unplugged, dns_broken, no_packets_route_past_your_router, …}

      1. 1

        Like the useless “network diagnostics wizard” in Windows? :)

      1. 17

        First of all, this conventional wisdom assumes that there is a single universal definition of “better”; but there isn’t one. If you work on a project as a team–which is almost all of us–it’s really hard to get everyone to agree on something; be it the definition of clean code, or even the type of whitespace to be used for indentation.

        Having a really small team size (N) makes consensus easier. It amazes me how much process is compensation for having more than a couple of people (at most) work on something. The failure mode for a small team is bus factor. The failure mode for larger teams is silent accumulation of technical debt due to lack of consensus and coordination.

        I don’t think there’s a neat solution to this problem, but I do notice that many problems go away as N approaches 1.

        Two might be the sweet spot.

        1. 3

          Which is why high productivity is so incredibly important. Get the highest productivity people (see Brooks’s chief programmer teams) and do everything to help them be more productive.

          1. 2

            The failure mode for a small team is bus factor. The failure mode for larger teams is silent accumulation of technical debt due to lack of consensus and coordination.

            I’m not sure that this concept has ever been made as clear as this quote. While not particularly a new observation, the profundity of this quote is one of those that I feel will grow to be just as important over time as Knuth’s famous quote on optimization.

          1. 3

            Meh - this should be automated. License change is a breaking semantic change in a library. There are finite licenses and known incompatibilities like this that are able to be modeled.

            1. 4

              There are finite licenses

              Not really. Some people write their own n-clause BSD license or so. It’s often a matter of changing a few words.

              1. 11

                An automated tool should flag this for manual review and probably removal, because making your project depend on some jackass’s untested, non-peer-reviewed NIH legal code is usually a terrible idea.

                1. 3

                  I think without intending to, you just proved my point. For a project that writes their own n-clause BSD license, these will inherently be dissimilar enough when looked at through automated tooling to trigger a build / package fail. This is good.

                  1. 2

                    I agree. I mean I should actually do this. I don’t think I have already seen this thing automated in my life and it is a shame. Licence changes in dependencies are probably rather uncommon but the risk is high.

                  2. 2

                    There are finite licenses that we should consider using…. I’m not saying one shouldn’t use a n-clause BSD license, but that one should have a relatively small number of them and they should be rejected by default, and later accepted as a case by case exception.

                    1. 1

                      they can be grouped by effect

                    2. 4

                      As he mentions, license compatibility is part of what you look for, but definitely not all. Can’t automate that. And, as the sibling mentions, licensing terms are absolutely not finite.

                      1. 2

                        There are automated tools to aid license review when doing packaging for Debian but they don’t remove the need for a thorough visual inspection.

                        The licenses are then summarized in a standard format in the debian/copyright file.

                        Unfortunately upstream developers and other distributions often don’t care about providing such clear licensing information.

                      1. 8

                        The primary flaw: no tests for code that has explicit edge cases. Even the ‘prod quality version’ has no tests.

                        1. 1

                          Very likely you naively come to EAV (Entity Attribute Value). See https://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%93value_model#Alternatives for some pointers on how to avoid that anti-(debatable)-pattern.

                          1. 5

                            Very thoughtful review. The book is 15 years old now and it does show its age a bit, but I am proud of it.

                            I don’t know whether responding to the author here works, but the two big issues he mentions: (unit testing > integration testing) and database isolation are two things I still emphasize.

                            The thing about integration testing is that you lucky if you have seams that allow it. If you do, then it’s doable. The thing is, though, that writing tests at a high level to get coverage at a low level is like dropping a pebble down a hole in the the earth and trying to get it to land on on a particular ledge. Even with coverage tools it’s tough. Once you’ve done that, you have a test that works, covers a lot, and likely takes longer to run than a focused test. Since it takes longer to run, you bunch up your changes and don’t run it as often. When that test fails, you’re left wondering which particular change caused the failure and you have to spelunk to figure it out. That’s why I lean toward smaller focused (unit) tests.

                            Re databases, it’s the slow down and the distance of used values from expected values that bothers me. Rails in particular is rough this way. I once worked with a team that had tests that took three hours to run on 24 cores because of ActiveRecord. If they’d only dealt with computation, I suspect the tests would’ve run in minutes.

                            1. 1

                              One thing I have encountered from the article:

                              One of the purposes of testing is to make refactoring and subsequent behavior changes easier and safer, but if every jot and tittle of the internal code structure is encoded in the test suite via all the mocks and fakes, a simple half hour of work refactoring the code as part of adding new functionality turns into hours of tedious work restructuring the tests to match. The result is to paradoxically discourage refactoring because of the painful changes then required to the tests, defeating one of the purposes of having tests.

                              Now, I know testing is something of an art and perhaps this is solved by a more careful balance between integration tests and unit tests, but have you encountered this? And how do you avoid it?

                              1. 3

                                Often I’ve found that overspecification in tests comes from using the wrong mechanism for faking out parts. http://blog.ploeh.dk/2013/10/23/mocks-for-commands-stubs-for-queries/ is pretty helpful for getting your head straightened out. Read it today. Read it again sometime in the future. Share it with your juniors. Hide it from the seniors that you wish to overtake ;)

                            1. 4

                              Basically, this tool is a syntax sugar for what Git already provide, giving you a more human friendly syntax. You can use this tool to read code better, for example, run “gitq by Dan with useState” in facebook/react repo to see what he does for react hooks, or “gitq from 2019-02-15 to 2019-02-17” to see who break the build during the weekend,…

                              1. 5

                                Just a nit regarding presentation: in the gif screencasts, I found your prompt (?) confusing. It looks very unfamiliar to me (not your standard “$” kind of prompt), so I had trouble splitting/parsing it mentally. For a long while, I assumed this somehow requires emacs, and that this is probably some internal emacs prompt (I’m not an emacs user). Eventually, I started to understand that the “emacs” might just show the name of the current directory. But I’m still not 100% sure about it. Maybe you could consider running the screen capture with PS1='$ ' or something similar, to make it easier to understand?

                                1. 1

                                  Interesting point, I was using zsh and didn’t notice about this non-standard aspect. Thank you so much, I’ll update these screen captures.

                                  1. 3

                                    You might also consider slowing down the casts (half speed at least, possibly more). I’ve found that it’s too fast to make out what is going on easily. I have no idea what the first GIF is demonstrating.

                              1. 7

                                Question for the group. If you use Stylus (or used to use Stylish), what do you use it for?

                                I headed over the the userstyles.org site and most of the styles seem to be “dark themes” or other cosmetic changes like changing the background of a site. Are there more practical uses of the extension? Can it modify HTML or Javascript (where the real power would be), or is it CSS only?

                                1. 27

                                  other cosmetic changes like changing the background of a site

                                  You call it cosmetic changes, other people call it accessibility.

                                  1. 7

                                    I use it to tweak the layout of some of the sites I use, like moving a fixed top navbar to the side, and making it smaller. Or making narrow columns wider. Small stuff like that, which make the browsing experience much more bearable. I rarely use the social or sharing aspects of it. I haven’t found anything useful there, and I’m not sharing my tweaks either, because they’re very personal anyway.

                                    I rarely use it to hide things, my adblocker can do that more conveniently indeed.

                                    1. 6

                                      I apply a style of body { max-width: 800px; } on a few blogs that weren’t designed with wide browser windows in mind—they spill text across the entire width of the screen, which makes them really hard to read. (You could use your browser’s “reading mode” to fix this, too, but this CSS change usually does the job without breaking any layouts.)

                                      1. 4

                                        Now that I’ve started using Dark Reader, I use Stylus for well-made, site-specific dark themes. Previously I was using the Gruvbox Dark Everywhere userstyle, but its shotgun approach leaves much to be desired. Beware: Dark Reader has some major performance issues on Firefox.

                                        Edit: My installed themes (which I enable along with Dark Reader after sunset): https://ptpb.pw/nUrG.png

                                        Edit 2: Also I enable the Firefox and Tree Style Tabs dark themes. This really needs to get more streamlined.

                                        Edit 3: And then I get to enable dark/night mode on sites that support it natively, one-by-one as I visit them. Sigh.

                                        1. 2

                                          Man, Dark Reader is great. Thanks for bringing my attention to that.

                                          1. 1

                                            Funny that you mention this. I don’t often long for the days when I had a CSS styling addon installed, but exactly this Dark Reader page made me bob my head back 20cm. That page seems to be made for a mobile phone or tablet screen, not a 27” monitor. Wow.

                                          2. 3

                                            Fixing fonts on the most obnoxious websites.

                                            1. 3

                                              I used to use Stylish - and a predecessor the name of which has slipped my mind - to reduce the size of the UI in Firefox - smaller tabs, less wasted space -> more space for page content.

                                              1. 3

                                                I like to use it to remove ads in core apps I use. I’d like to share the styles I create with others who use those apps. I use the free version of toggl, and they have a persistent, animated thing in the bottom-right corner that tells me the benefits of “going pro”. I just made a stylish thing to display: none the element which matches that rule. It’s great.

                                                1. 1

                                                  Is there an advantage to that over the “block element” feature that exist in most ad blockers?

                                                  1. 1

                                                    I use brave and Firefox which have some built in blocking. I haven’t thought of that, but I’ll take a look!

                                                2. 2

                                                  i’m considering using it to shrink the gmail sidebar label font - they recently increased it from the same size as email body text to a size bigger, and it’s very annoying.

                                                  1. 1

                                                    I just started using this again after forgetting that it existed. Another forum I visit regularly now is ad free and doesn’t waste a bunch of whitespace where these were removed. I created an ironic one for hiding the ads for stylish for android on userstyles.org… :D Also, my day job involves using a console that has a lot of useless (to me) menu items - bye bye.

                                                    1. 1

                                                      I sometimes use it to tweak interfaces, like get rid of annoying panels or adding bold to certain elements

                                                      1. 1

                                                        Can it modify HTML or Javascript (where the real power would be), or is it CSS only?

                                                        Is it possible for extensions to request access only to modify CSS?

                                                        1. 4

                                                          CSS can still exfiltrate sensitive page content (albeit attacks are harder to write).

                                                          1. 1

                                                            If you write your own CSS this is no longer a problem :P.

                                                            1. 1

                                                              That’s good to know. I’m going to do some reading on this, but do you have anything you recommend?

                                                          2. 1

                                                            There are two sites I frequent that have awful stylesheets that I can’t stand so I have custom stylesheets that make them look better.

                                                          1. 2

                                                            Personally, I really like having a staging area by default. I like my commits to have higher granularity (i.e. do one thing in a commit). When editing code, I will often make several commits worth of modifications before finalizing on what I want to change. I also usually have some modifications (i.e. debug printfs or minor build file modifications) which I don’t want to commit, but I may need to commit other parts of those files. Having a staging area makes it easier to pick-and-choose what parts of what files go into each commit. It could be argued that what I really want is just git add -p, and that the staging area is irrelevant to that. However, I like the interactivity that a two-phase commit process affords (and the ability to easily undo changes). In the article, Szorc argues that this shouldn’t be a default feature, but this seems to be a very common use-case (especially once multiple people start working on a project and you want a clean commit-history).

                                                            1. 2

                                                              Initially, I too thought that this was the argument that he was making, but if you think it through, and understand the nature of the what happens when you git add -p, it’s exactly the same as what happens when you commit, without the commit message. Git creates a copy of the file in the objects folder, takes the hash and names it appropriately based on the hash. The commit is just putting a label to the stuff that you put into the index (/staging area). Conceptually, there’s no difference between writing a label on an envelope and then one or more things in it vs putting one or more things in it and then writing a label on it. I’m a decently experienced git user and can see how the simplification of removing the staging area would make understanding git easier.

                                                              One of the places that it might make things harder is in resets - i.e. I’ve committed and I want to reset --soft HEAD~1 to redo the commit. It would be difficult to keep the existing changes in my workdir and the reset files separate. Perhaps there’s an obvious way around this though?

                                                            1. 6

                                                              They sometimes are, and sometimes aren’t. It really strongly depends on the logic of the application in question. I don’t think this is a very well formulated argument, it’s just saying that you should have smaller functions. It could be true, but sometimes you cannot disentangle the logic of a function like that. For example if you have a dry_run flag, you’re saying run the function but do not actually make the request (or do whatever the function does). It would only be possible to make it into two functions if you duplicate the logic, something that would not be DRY at all.

                                                              1. 6

                                                                The author says it’s a code smell, not a code travesty. And in the example they provided, the code change was certainly a readability win. I often think about how I can clean up functions that have flag-guarded blocks interleaved together. Those get hairy fast.

                                                                1. 1

                                                                  Yea, it definitely can be, and I’ve definitely written functions which do this badly and had to clean them up before–or had to clean up someone else’s before. But I think the article is making a point that’s not necessarily universalizable. In many cases, as a comment on the article says, you’d just be moving the conditional somewhere else.

                                                                  I think the general Ruby obsession with functions that are very small is a bit silly. While I do prefer smaller functions, it’s not always a reasonable choice and can easily create unnecessary complication and indirection in applications.

                                                                2. 2

                                                                  It would only be possible to make it into two functions if you duplicate the logic, something that would not be DRY at all.

                                                                  Disagree. What’s the simplest way to achieve a dry run capability? I’d say split the code into:

                                                                  someAction(bool dryRun) {
                                                                    var state = prepare();
                                                                    if (!dryRun) {
                                                                      run(state);
                                                                    } else {
                                                                       dryrun(state);
                                                                    }
                                                                  }
                                                                  

                                                                  Don’t you find the following simpler:

                                                                  someAction() {
                                                                    var state = prepare();
                                                                    run(state);
                                                                  }
                                                                  
                                                                  someDryRun() {
                                                                    var state = prepare();
                                                                    dryRun(state);
                                                                  }
                                                                  

                                                                  Often the dry-run part is often as simple as return state, and the someDryRun method actually is the prepare method simplifying even further.

                                                                  1. 2

                                                                    You’re omitting the important part where dry run and run are basically the same, but ok

                                                                    1. 2

                                                                      You can use Free Monads to express this and then one would run it in different contexts.

                                                                      Another thing I often do is for anything with side effects toss that under an interface so the flow is always the same but it offloads side-effectful work to a value it gets as input. Then you can have the dry-run version of the interface and the real-version of the interface.

                                                                      1. 2

                                                                        So, how do I do this in C++ or Java or JS?

                                                                        EDIT: Talking about the free monads thing, not the interface thing.

                                                                        1. 1

                                                                          You can get pretty close with something like https://en.wikipedia.org/wiki/Interpreter_pattern

                                                                        2. 1

                                                                          That actually sounds kinda neat, I suppose that you could do something simple in C# like

                                                                          private void visitDeletableItems(List<Item> items, Action<Item> action)
                                                                          {
                                                                            foreach (var item in items) // matching criteria or whatever
                                                                            {
                                                                              action(item)
                                                                            }
                                                                          }
                                                                          public void deleteDryRun(List<item> items) { visitDeletableItems(items, item => {}); }
                                                                          public void delete(List<Item> items) { visitDeletableItems(items, item => { delete(item); }); }
                                                                          private void delete(Item item) { ... }
                                                                          
                                                                  1. 6

                                                                    Some more possible things that could be learnt from this event.

                                                                    • Don’t do things that can have a large scale effect without thinking about the worst that can happen. The for loop in that code is entirely to blame for the magnitude of the problem (17,000). You could have caught this by precomputing the list of emails to go out and failing if this exceeded the normal amount by a drastic amount.
                                                                    • Perhaps you could have spread the checks across 24 hours instead of at a specific point in time to avoid being dependent on an external call that might not be available during an outage.
                                                                    • External service calls that you rely on will fail. Consider using a retry strategies that has exponential backoff with jitter. https://www.awsarchitectureblog.com/2015/03/backoff.html
                                                                    1. 3

                                                                      The problem is these are all arguably over-defensive measures without the benefit of hindsight. In an “agile” setting, you won’t be able to justify writing code this defensively all the time. Even less so, since if you code like that, there won’t be any incidents to justify writing code like that :)

                                                                      An exception could be if you managed to capture these patterns in abstract, reusable libraries, toolchains etc., then the up-front cost could be justifiable.

                                                                      1. 6

                                                                        I wouldn’t put that on “agile”. I worked in quite a lot of agile organisations where safe and defensive practice was exercised around all mission-critical and safety-related data. They just didn’t bother too much if something was released with a button two pixels too far left (which is an issue to be fixed, I don’t want to downplay frontend, but it can easily be fixed with another deployment and has no lasting repercussions).

                                                                        “pressure” is the killer here.

                                                                        1. 2

                                                                          Or you just make all that irrelevent/impossible by picking append-only data structures?

                                                                      1. 17

                                                                        I’m not a big fan of Perens by any means, but being sued for stating an opinion on licensing seems a bit dubious to me – but I am of course, not a lawyer.

                                                                        1. 5

                                                                          I’m not a big fan of Perens by any means, but being sued for stating an opinion on licensing seems a bit dubious to me – but I am of course, not a lawyer.

                                                                          It depends on the jurisdiction, but given that this is filed in the US Federal system, it’s pretty dubious. They’d have to prove that not only what Perens said was false, but also that he acted with either negligence or actual malice (essentially, they’d have to show it was false, that he knew it to be false, and that he acted with reckless disregard to that knowledge).

                                                                          This is in practice monumentally hard to prove. Even if you set aside the fact that what he said is probably true, even if it were false, unless Bruce Perens left a paper trail of statements along the lines of “I know this is false but I want to screw these guys and destroy their business with my false statements!”, it’s enough of a defence that he says he believed it to be true, because it doesn’t follow that he made the claim to imply the existence of facts which could be easily verified to be false (the Milkovich ruling the complaint mentions).

                                                                          (IANAL either, but this is pretty clear-cut caselaw)

                                                                          1. 1

                                                                            Doesn’t GRC win (the ability to say they’re non-infringing) here if they prove the statements false, even if they don’t prove defamation.

                                                                            1. 4

                                                                              No, you’re allowed to express opinions that later turn out to be incorrect.

                                                                              What this hinges on is that reasonable people can reasonably disagree about the interpretation of the GPL (disagreeing about the meaning of contracts is, after all, what lawyers do) and they can certainly express their opinions about that interpretation.

                                                                              You’d need to sell the judge on the idea that both GRC’s interpretation was correct AND it was so manifestly and obviously correct that the only possible interpretation of Perens’ statement was that he was making it to defame GRC because the opinion was so trivially proven false.

                                                                              Prior to Milkovich, expressing any opinion at all was protected. Milkovich’s wrinkle was that you couldn’t do something like “In my opinion, based on evidence I’ve seen, he’s lying” (implying the existence of evidence that shows he’s lying) if none existed and you could trivially have verified that there was no such evidence.

                                                                              Perens wasn’t doing that. He made a cogent argument based on his understanding of the GPL. That it disagrees with GRC’s interpretation, even if GRC’s interpretation is upheld in a court of law in the future, doesn’t make it defamatory.

                                                                              1. 1

                                                                                Well, there’s law on what he said and copyright law itself. Anyone backing up the infringement claim can focus on the copyright angle in the next court.

                                                                            2. 5

                                                                              Especially given he seems to be pretty much on the money with the assertions made.

                                                                            1. 2

                                                                              TL;DR: use --jobs=4 to run the installation in parallel for a ~1.6x speedup.

                                                                              1. 6

                                                                                lol

                                                                                /* Just a safe strncpy(3) */
                                                                                static void
                                                                                xstrlcpy(char *dest, const char *src, size_t n)
                                                                                {
                                                                                	strncpy(dest, src, n - 1);
                                                                                	dest[n - 1] = '\0';
                                                                                }
                                                                                ...
                                                                                xstrlcpy(cmd + strlen(cmd), newpath, strlen(newpath) + 1);
                                                                                xstrlcpy(buf + strlen(buf), fpath, strlen(fpath) + 1);
                                                                                ...