I tend to think of yak shaving as the annoying but _necessary_ activity of fixing things you need to fix to close your bug. Not frivolous refactors. More like adding decent logging to a complex system, cause otherwise, how will you know why your feature doesn’t work?
Me too. Where I work it's slogging through the process of doing just about anything. A simple task ends up being a to do list that's 10 items long. There's a 60 day use it or lose it policy on just about everything so you may find you need to completely rebuild the dev and testing environments which include automated as well as complicated manual processes before you can even begin to fix the bug.
Yes the example is wrong. It’s about making an apple pie, but figuring out you have no apples, so then you’re going to the supermarket etc etc.
It’s about “necessary” things to achieve a goal, without appropriately weighing costs vs benefits nor considering alternative solutions (perhaps making a chocolate pie instead).
Exactly, what is mocked as Yak Shaving is the important stuff. But try telling your non technical manager why you need to add that logging system, which requires its own testing and deployment.
In this scenario you are the one focused, the non-technical people that shuffle tasks around playing 'agile' are the handicap. It could take a couple of hours or a couple of days to get that logging done but explaining to the non technical manager (who refuses to learn) why this needs to be done is a task in itself that cannot be underestimated.
At the time of writing this, this "article" is #1 on HN default sort. It's an incredibly short, and fluffy post (self reported as a 3 minute read), with little more substance than an urban dictionary listing. I'm baffled.
On the topic of yak shaving though: I recently felt like I wanted to do more technical writing. The prerequisites of this idea involved building a static site generator and redesigning my website. While building the SSG, I of course imagined all the features that would be expected, a tagging system, JSON output in addition to markdown rendering, custom syntax highlighting for codeblocks etc etc. I had that idea at least 1-2 years ago, and I've only recently written my first post within the past 2 months. I think I enjoy tinkering with build systems much more than writing.
I think we are many who read hacker news for the comments.
The downside is, it’s not so much the article that becomes relevant, but the topic. HN felt like talking about yak shaving and all we needed to get started (you included!) was a headline.
Agreed - it's like watching the emergent complex behavior that an AI spits out after you give it something unique. You're curious - what on earth could the HN crowd have to say Yak Shaving? The input doesn't matter at that point to a degree, it's the unique/novel thing that was outputted.
You could search Algolia for the last time it was discussed, but it's much for fun to bring up the topic again. Who knows maybe the emergent behaviour is different than the last time it was discussed.
Do you get different emergent behaviour depending on the time of day/week?
Have demographics of the site altered such that the prevailing opinions are vastly different?
What is the mean time to only tangentially related items being discussed?
I have written comments on articles that were posted before. In many cases the discussions and participants are quite different. And they complement the comments of the original post.
HN completely random, yes there are patterns, but if you looked at 1000 articles that have been posted 5 or more times on HN you would see it’s completely random to if a topic get attention or not. Same with an emerging new story, multiple users will post it and frequently only after it’s posted a few times over hours or days does it get traction; and even then, there’s obviously a lot of posts that never get attention, but do elsewhere, but were within the scope of what’s on topic on HN.
It also creates a vicious cycle where people who do care about article quality are more likely to disengage with the site -- and these are most likely the people who write the highest value comments.
I don't think a culture of 'only reading the comments' is at all a good thing.
To me, more important issue is allowing users to read, but not comment. Obviously everyone doesn’t have something meaningful to add to every topic, but if someone has read 100 articles and did add anything meaningful, something is wrong with HN.
Sounds like the path reddit took. Doubt HN will turn into it in perpetuity but I could already see some of that* leaking in the last 2-3 years, although thankfully it is harshly reigned in by moderation and fellow posters alike.
*by that I refer to comment chains just making bland puns, joining in threads for no reason other than saying something, even if it adds nothing and at times is straight up incorrect, etc.
Agree, though HN also clearly has the “Ask/Tell HN” if someone feels like taking about something and they’re by default down weighted vote wise, which to me says the posts linking to content should have substance.
For the people that read HN but don’t comment, please load/scan a link before upvoting. Not doing so will have a net negative impact on HN if enough people are not checking the links.
Similar thought: I think you could stay there's a spectrum of yak shaving. I wouldn't as the article call 'going down the rabbit hole' yak shaving as rabbit holes feel more intentional.
My feeling of things related to yak shaving:
Rabbit holes - intentionally following some thread of associations looking for some insight or unexpected solution
Yak shaving - While working on something important you iteratively find something more important that you feel you need to deal with first. Supposedly but not necessarily it's something you have to deal with to be able to solve the original problem.
I agree that the articles example of yak shaving is a special case of yak shaving where it isn't very clear that the shaver feels that the distraction is more important. But I suppose such feeling is always a bit implied in the word distraction.
> Yak shaving - While working on something important you iteratively find something more important that you feel you need to deal with first.
No; yak shaving is something you must deal with to continue working on your original "something important". It is solving blockers, not following distractions.
Yes, been there, done that: tinkering (or yak shaving) makes it easy to forget about KISS. And sometimes results in too many open tabs in one's browsers ;-0
But even the best of us are prone to fall for it, and sometimes they even produce excellent results, cf. Donald Knuth and the TeX / Metafont ecosystem:
Between 1977 and 1979 computer scientist Donald E. Knuth of Stanford University created the TeX page-formatting language and the Metafont character shape specification language, originally as a way of improving the typography of his own publications. [...] -- https://historyofinformation.com/detail.php?id=3339
My experience is that programmers always try to make things as simple as possible, and when they fail at that, it's because they don't know how, or don't have enough time, or maybe the "simple" solution isn't persuasive enough that it covers all the cases, so a "more complex" version is preferred, or something like that; not because they forgot "whoops" I was supposed to make things simple not complicated.
The only times I have heard "KISS" suggested in earnest have been from bad managers.
> But even the best of us are prone to fall for it, and sometimes they even produce excellent results, cf. Donald Knuth and the TeX / Metafont ecosystem:
I don't see how this has anything to do with failing to keeping things simple, yak shaving for sure, but this yak (if it's a yak) did need the shave: there weren't any typesetting systems comparable to TeX at the time (and by some opinions there still aren't). What else can you do? Have someone spend hours typesetting and resetting a thousand page book every time there's an error, or turn the job over to a computer and automatically typeset it?
This is just solving problems. Solving problems you have is good, and where people go wrong, it's when they are solving problems they don't have (but perhaps think they might), or perhaps they underestimate how much of their problem the computer could actually solve.
> I had that idea at least 1-2 years ago, and I've only recently written my first post within the past 2 months. I think I enjoy tinkering with build systems much more than writing.
This is very much an easy trap to fall into! What helped me was not sweating over the small stuff and setting up an instance of Grav, though I think that most of the turnkey blogging solutions out there would work (e.g. Ghost/Bolt as well, maybe not self-hosted Wordpress as a first option due to large surface area): https://getgrav.org/
What I really like about that solution in particular is that it is flat-file based and also has an admin web dashboard that's a separate plugin that can be enabled/disabled (some might prefer writing text files directly, with front matter and all) and has separate URL path that can be put behind basicauth (in addition to built in auth), client certificate auth or anything else.
It's not perfect, of course, and has given me the occasional headaches, but it's also good enough for my blog: https://blog.kronis.dev/
That said, I still struggle with my homepage - instead of going back through 5+ years of projects and describing all of the noteworthy ones, putting up a few galleries of screenshots, listing technologies, ordering them by relevance and also making sure that it doesn't contain too much data... it's just sitting there, on my TODO list. It's been that way for a while now.
> The prerequisites of this idea involved building a static site generator and redesigning my website
To clarify: that is not yak shaving, that is just plain old procrastination. Yak shaving includes tasks that you have to complete in order to do whatever your original intent was. For example:
* I want to add new feature to my code.
* The feature requires a database migration.
* To apply the migration to test environment I need to set up AWS credentials.
* To set up credentials I need to log in to AWS console.
* My password hasn't been rotated in a while so I need to update it.
* etc
> Yak shaving includes tasks that you have to complete in order to do whatever your original intent was.
The example (and definition) in the actual article disagree with you:
"You want to bake an apple pie, so you head to the kitchen.
In the hallway, you notice some paint chipping on the wall.
So you walk to the hardware store for some paint."
You obviously don't need to deal with the paint chipping before baking an apple pie.
Wikitionary gives both definitions: a blocking task or a procrastination detour
If you want to write and for it to be a habit you can reduce the friction of writing.
Create a GitHub repository and create a journal repository and create a markdown heading for each entry. It works.
I'm on 4 pages of 100+ journal entries each. See my profile, I journal computer ideas, algorithms in the open.
Using WordPress or using complicated software shall take time away from writing regularly. And you need to open a document and write, not abandon your blog due to forgetting how to post
The HN new queue is interesting because you often have a sea of articles with absolutely no votes, and then one or two articles with dozens of votes. While votes are probably power law or exponentially distributed, that skew seems a bit too extreme.
When quasi-blogspam articles like this rise to the top so quickly, one has to wonder whether it’s the result of vote manipulation.
Emergence at work. There is much to be learned from just the behavior externals of HN.
Uniqueness, mystery, narratives and humor/silliness are probably big drivers of attention on forums and news sites. Like the other commenter suggested, the gold is typically in the comments. I don’t have data to back up this assertion, but it would make for a good study/article.
>At the time of writing this, this "article" is #1 on HN default sort. It's an incredibly short, and fluffy post (self reported as a 3 minute read), with little more substance than an urban dictionary listing. I'm baffled.
> Never fix a bug and refactor in the same pull request.
We’re kinda going the opposite way: If you find something that should be fixed, then fix it.
This is, of course, meant for small things, like renaming or rewriting expressions to make them more readable. But we have had to make this change, because our experience is this is necessary to avoid code rot.
I think that the two ideas are separate. You should fix problems that you see, but you should do this in separate commits (and ideally PRs).
There are a few benefits
If your refactor is large, you can get a bug fix in ASAP in a small PR, and get the large PR reviewed later. Sometimes I’ve done a refactor with a stubborn CI integration test or two that might take a few days to fix due to long feedback cycles.
Aside from that it lets your reviewer enter a different mindset for each change. The bug fix is more easily understood, and the reviewer expects a change in behavior. For a refactor the reviewer can usually review in a more relaxed manner because they know the behavior can/should be the same, and good unit tests should identify any differences in behavior
The frustrating thing isn't the small problems, in chasing these small problems one might find a big one that isn't as easy to fix: https://www.youtube.com/watch?v=AbSehcT19u0
The other side I see to this is that if I don’t refactor this code, who will?
I guess that opens the debate to does the code actually need to be refactored? Sometimes not, but I have a very hard time leaving a 2000 line function alone, or a class with many levels of unnecessary inheritance.
What I’ve started to think is that there are people who get things done, and people who refactor.
People who get things done ship code fast. The good ones know when to make trade offs of purity vs practicality. The bad ones write unmaintainable code. They tend to view programming as a job, and code quality as a burden. They may refactor and make unrelated improvements, but it’s uncommon.
People who refactor still get things done, but most of their work have rabbit holes tacked on. They delivered a bug fix, but they also greatly improved the test suite and tooling. They tend to value purity, best practices, and might view programming as a craft/art. The good refactorers make the high value changes that are a net benefit to the team; they might care about cleaning up important parts of the code, improving developer experience, or adding test coverage to critical functions. The bad refactorers rewrite a bunch of code because it wasn’t pure, and the team, customers, and business have no observable effect from it.
I think teams need both kinds of people on it. Too many doers will lead to fast progress at first, but eventually grind to a haunt. I felt this was a HUGE problem at my team in AWS, and a major factor of why I left.
Too many refactorers is equally problematic. Your code will be of great quality, but velocity will be unacceptable for the business.
I personally am a refactorer. probably more of a bad refactorer than good, but it’s something I’m working on.
Maybe this is a rationalization for my behavior so that I believe it’s important, but my time at AWS shipping 3 features a year with a team of 16 says that code quality really does matter.
What you're saying and what the article is saying are two different things. The whole point of the article is not "Don't refactor code"; it's "Never fix a bug and refactor in the same pull request".
The obvious question in any organisation with a layer of project managers is how to explain that you've delivered the fix and you haven't moved on to fixing the next most important thing or adding some other new functionality.
Yes, that's probably a sign of poor project management or organisational brokenness. But it's also probably the reality for most people.
I just mentioned it in this comment[0] but I disagree with this premise too since sometimes it's more work to fix the bug without the refactor:
> It also misses the point that sometimes refactoring makes it _easier_ to fix the bug, and that a large part of fixing a bug is understanding exactly what's happening with the code, which refactoring can also make easier.
I have had this conversation yesterday, and the refactorer asked this very question. Here's my answer:
The question is improperly formulated. With your behavioral patterns of immediate refactoring, the question seems to be: "if I don't refactor this code NOW, who will?".
I'd say that if you don't refactor the code now, someone else, maybe future you, may refactor it later.
Most sane companies will protect engineering from impulsive feature requests and will add them to the backlog for future consideration.
I'm trying to instill the same protective mindset in my teams, and help them not do refactorings immediately but rather consider them as potential work as dedicated items in the sprints or so.
Doing so, prioritizing becomes a natural part of the refactoring/tech debt/tech risks agenda, because we have an overview of the work to do globally.
In my experience (three years, two companies, so not much) refactors are beyond last place for prioritization. Even my current company which does a great job of handling tech debt doesn’t track refactoring well. How would you even do it? Imagine how many tickets you would have about the things that need to be improved.
I guess this is delving into queue theory and how the work queue is growing to infinity because there aren’t enough workers.
Personably I just allocate X% of my time to this kind of work and spend it on the most productive improvements. You don’t have to die on every hill you see. And if most people do this it results in a constant shift to something better while still achieving business goals.
Building on this, I see a lot of areas of code that are effectively untouchable because of how much energy would need to be invested to understand the code and its context before making a change. So if a change has to be made to fix a bug or add a required feature, it's done in the most low-impact way, which only makes the code that much harder to understand in the future.
Meanwhile, I can't get refactor-only commits through because nobody wants the code to be touched unless absolutely necessary.
We're in the middle of migrating a massive PHP codebase to Java. The code I'm talking about is newer Java code. In a few years, people will be wondering why the Java code is as much as a mess as the PHP code and, if I happen to still be around, my response will effectively be "I told you so" (in kinder, more productive terms).
I've basically determined that my only option to ensure continued or improving code quality is to combine refactoring and bug fixes in the same merge request, while still keeping them in separate commits. That way whenever I touch a part of code for bug fixing or whatever else, I leave it behind in much better state than it was before.
> I've basically determined that my only option to ensure continued or improving code quality is to combine refactoring and bug fixes in the same merge request, while still keeping them in separate commits. That way whenever I touch a part of code for bug fixing or whatever else, I leave it behind in much better state than it was before.
I agree, in practice I think this is the best option, with some kind of timebox for the improvements made.
One thing I'd like to add is setting up some kinds of tests. If nothing else is available, E2E tests for the critical paths of the business are a good start. For (micro)services, getting API contract tests to work is also invaluable.
Refactoring while bug fixing can be good. But depending on your metrics, it might be underappreciated and seen as time wasting.
The guy the goes around blasting bugs like there's no tomorrow looks good to the boss. When he leaves someone will have to refactor his mess and that's wasting time again.
In the particular case of refactoring, I don't think this is a good idea. I can understand that multi-file system reorganization refactorings shouldn't be done with simple changes, but small enough refactorings can easily happen when working on a piece of code.
That is because-
- You have the best mental model about a piece of code and its system the best when you are working on it, not when you read a ticket description of what should happen. This leads to overall better efficiency and less context switching.
- I think that the principles of "leave things better than you first found them" and "with every not-so-minor change, one should think about how would you architect the system the best way possible at this current time" great principles.
- I find that "Refactoring sprints" never really work great. They tend to be inefficient and rarely prioritized tasks by the management. As developers we have responsibility over code and make sure that its in the best state possible as an implicit description of our profession.
Even though it pays to be focused, I think there is merit in the exploration of code-base as it helps figure out new ideas and avenues of improvement.
I've often been in the situation that someone left me some code and I have to fix a bug in it or add a feature but in order to even understand it I have to refactor it so it fits into my head.
I guess it's an article for programmers who too often have tasks/issues called “Refactor component N” or “Pay a technical debt in module G”. Majority of the programmers rarely have dedicated paid time to do just refactoring.
Small refactorings and cleaning alongside bugfix are fine. Big refactoring should happen independently, of course.
Refactoring is also a process for the developer to build an understanding of what the code is supposed to do. This in turn helps figuring out bugs as well.
What the author describes isn't really the kind of yak shaving I find myself doing as a programmer. Yes, fixing a bug in a single dedicated pull request is one technique that can be helpful in a very specific situation. But it's as if in the apple pie situation, the author said that the way to avoid yak shaving is to always have prebaked apple pies in your fridge. One quickly discovers how bad yak shaving can get when they go to store the apple pies in their fridge and find out that the fridge is full. Or when they go to open a pull request and realize that the CI tests aren't running because their credit card has expired and they can't update the card info because the person with access to that information is on PTO, and they spend the day trying to resolve the billing issue instead of just making a simple pull request to fix the bug.
Personally it relates to the scope of the change/bugfix. Sometimes a nice refactor merge drags forever because the understanding of the fix/task you're working keeps changing until solidification, if it is an extensive refactor then it's more work to keep up with updates and conflicts.
I thought that I have ADHD, but apparently I just need to stop shaving the yak..
distractions are real, at some point I pomodoro technique helps, however when I get interested/distracted with something else at the code then it's pointless
I find that one or two hour timers help. I force myself to have a tea break or a snack. It lets you zoom out for a minute, and remember what you set to work on that day.
This brings me to my next point: know what you're supposed to be working on. I like to write it down at the start of the day while I have breakfast, before I touch a computer.
Yak shaving. It is weird, because sometimes a serious refactor is virtually indistinguishable from jack shaving, it looks the same from the outside and it feels the same from the inside. The only difference is that the yak shaver often labours under the illusion that what they are doing is indeed important, while the refactorer knows what they do is important.
I think in programming it is easy to get lost in scale. We all know these videos where you scale in from the universe into a single atom. In programming tou operate at similar dieseperate scales. You need to have the high level perspective ("I want to get to this mountaintop!"), the mid level perspective ("I chose to scale the mountain via that route") and the detail level perspective ("I put that finger into that nook of the rock to my left and shift my weight slightly to the right..") and of course there is also a tooling perspective ("What kind of gear do I need to scale that mountain?").
When you operate just at the detail level it can happen that you end up on the wrong mountain, branch off into the wrong route etc.
To make things worse you can also have a meta-perspective ("How will this help me beyond the mountain I am currently on?").
From their example I think what the author means by "Never fix a bug and refactor in the same pull request" is actually "Never fix a bug and do unrelated refactorings in the same pull request." Many times it is much easier to fix a bug or implement a feature if some refactoring is done first. In order to increase clarity in the following code review I recommend using short, descriptive commit messages following some type of standard. Two that I know of are Conventional Commits[1] and Arlo's Commit Notation[2].
That’s not the definition of yak shaving I’ve ever used. I’ve always thought of it more like:
- I find a bug
- I track it down to a library I’m using. The fix is in a later release.
- I go to upgrade the library, but that brings in some transitive dependency upgrades that accidentally broke an API used elsewhere.
So now instead of fixing my bug I’m rewriting API call sites across my project.
I think my understanding of yak-shaving was more, can't get to the thing you were trying to do because of cascading blockers. Less distraction, and more unknown scope and complexity.
I quite like the Malcolm in the Middle[0] example of yak-shaving, though it's a combination of both blockers and distraction.
My understanding of yak shaving is that if you need to create a system for selling ads then you'll start by developing a graph layout algorithm that produces a set of optimal layouts for routing power in a data center (because you don't want to be called out if your system doesn't scale.)
> yak shaving - Any seemingly pointless activity which is actually necessary to solve a problem which solves a problem which, several levels of recursion later, solves the real problem you're working on.
That's a much more correct example than the one in the article. The "real-world example" in the article describes doing something completely different than intended, not out of necessity but by distraction.
I have the opposite problem of yak shaving. If I see something that should be fixed I do everything in my power to rationalize procrastinating it. My main strat is simply "I'll pretend I didn't see that", even when it's something that could have catastrophic consequences if not fixed. If it's something that is required for the task in hand I use all my creativity to find an ugly hack to bypass it.
If you follow the authors advice to its logical conclusion then all changes to the code base are narrowly focussed tweaks - where does the longer term thinking come into this?
If I’m implementing a new feature, should I also disregard the need for refactoring?
A more nuanced approach is needed. You need to learn when to make changes additively and when to reshape the code to fit your new use case (and how much reshaping is required).
As an aside: I think tech debt sprints (if needed regularly) are often a sign that you aren’t developing software sustainably day to day.
I disagree, if you realize: "we need to refactor this file/module/class/etc." then it becomes a new task. Or more general, "we need to refactor the organically grown architecture": it's a new task. Working on a task should not prohibit your thinking about additional tasks, just add them to the backlog.
I find the 'never fix a bug and refactor in the same commit' advice somewhat questionable.
If the code is a mess and I'm going to refactor it anyway should I spend a lot of time trying to fix the bug in the old code only to refactor it afterwards? Or should I refactor and deliberately leave the bug in there only to fix it afterwards?
To me doing them together often makes sense and I don't remember code reviewers ever complaining. But maybe I'm missing something?
it's about atomic commits. every commit should be a smallest possible self contained change. but tbh I also often do it at the same time, and if one is hard to untangle from the other during the commit, I just commit them together. to me, that's the lesser evil than not doing the refactor.
I think a much more thorough and measured discussion of this was done by Gwern in his piece about socks https://www.gwern.net/Socks in which he describes yak shaving as a failure cascade and talks about ways to avoid it.
I find it slightly insidious how the entire concept of yak shaving is framed in the article as a lack of attention span or directed focus on the part of the developer, instead of a consequence of being required to work in a suboptimal environment. In my experience the majority of yak shaving is spent removing direct impediments to solving the task at hand. Distraction is always an issue, but I feel that falls under the bracket of "doing the wrong task" rather than "the path to complete the task is indirect and convoluted".
With this kind of framing we can look at the cause of yak shaving as a failing of an individual, rather than a lack of an accurate and holistic view of what the task entails given the current state of the system.
https://projects.csail.mit.edu/gsb/old-archive/gsb-archive/g... The OG only specifies that it's "related" to the task, and makes it pretty clear that one could come up with a significantly cleaner path to the original goal - Yak Shaving overlaps heavily with "flimsy rationalization"
> If you truly need to make all of these other enhancements, do them in separate pull requests. Never fix a bug and refactor in the same pull request.
Somehow, in practice, I've seen the fixing plus enhancements work better in getting the code in a better shape.
Also, why are we not good with doing both at the same time? If its because it makes things harder to review, I've found that pairing on the review and adding clarifying comments to the PR is a much better way. If its for the commit history, is it always more important to have a squeaky clean commit history than to have easier to read (I'm presuming this is the intent of the refactor) code? Is there some point after which the code is bad enough to sacrifice some commit history clarity to get better code?
> You may even decide that these enhancements are distracting you from your immediate goal of shipping a feature. In this case, there is nothing wrong with addressing them in a tech debt sprint.
Has anyone actually seen this work? In my experience, once the original bug is out of the way there is no motivation or vision on how or why to make the cleanup and the tech debt tasks are left to rot forever, while the code slowly turns into mud. Does anyone know how to avoid this?
IMO the thing that works best is to do the yak shaving first before the bugfix. But also, timebox the effort for yak shaving - you're only allowed to do a certain amount.
Maybe do a PR with the refactor first, and another PR on top of it with the bug fix. That way you can test that the refactored code doesn't change any behavior, and then you can do the bug fix (hopefully more easily once the refactoring is done). An that way the refactoring doesn't get dropped as not important, since it's literally a dependency to getting the bug fix merged.
I would have loved this more if the plot twist was that the author first decided to recode their perfectly fine static site generator from Perl to the new hotness and along the way wrote a script that automatically rebuilds and deploys the site every time the executive toilet at American Express flushes.
112 comments
[ 4.9 ms ] story [ 212 ms ] threadIt’s about “necessary” things to achieve a goal, without appropriately weighing costs vs benefits nor considering alternative solutions (perhaps making a chocolate pie instead).
In this scenario you are the one focused, the non-technical people that shuffle tasks around playing 'agile' are the handicap. It could take a couple of hours or a couple of days to get that logging done but explaining to the non technical manager (who refuses to learn) why this needs to be done is a task in itself that cannot be underestimated.
On the topic of yak shaving though: I recently felt like I wanted to do more technical writing. The prerequisites of this idea involved building a static site generator and redesigning my website. While building the SSG, I of course imagined all the features that would be expected, a tagging system, JSON output in addition to markdown rendering, custom syntax highlighting for codeblocks etc etc. I had that idea at least 1-2 years ago, and I've only recently written my first post within the past 2 months. I think I enjoy tinkering with build systems much more than writing.
The downside is, it’s not so much the article that becomes relevant, but the topic. HN felt like talking about yak shaving and all we needed to get started (you included!) was a headline.
Do you get different emergent behaviour depending on the time of day/week? Have demographics of the site altered such that the prevailing opinions are vastly different? What is the mean time to only tangentially related items being discussed?
I don't think a culture of 'only reading the comments' is at all a good thing.
*by that I refer to comment chains just making bland puns, joining in threads for no reason other than saying something, even if it adds nothing and at times is straight up incorrect, etc.
For the people that read HN but don’t comment, please load/scan a link before upvoting. Not doing so will have a net negative impact on HN if enough people are not checking the links.
My feeling of things related to yak shaving:
Rabbit holes - intentionally following some thread of associations looking for some insight or unexpected solution
Yak shaving - While working on something important you iteratively find something more important that you feel you need to deal with first. Supposedly but not necessarily it's something you have to deal with to be able to solve the original problem.
I agree that the articles example of yak shaving is a special case of yak shaving where it isn't very clear that the shaver feels that the distraction is more important. But I suppose such feeling is always a bit implied in the word distraction.
No; yak shaving is something you must deal with to continue working on your original "something important". It is solving blockers, not following distractions.
I am at least 18 months into exactly the same hole. And it isn't the first time.
I've been using Obsidian[1] and a few plugins like Incremental Writing[2][3] to help me write. Focused less on publishing and more on writing for me.
[0]: https://www.goodreads.com/book/show/34507927-how-to-take-sma...
[1]: https://obsidian.md/
[2]: https://supermemo.guru/wiki/Incremental_writing
[3]: https://github.com/bjsi/incremental-writing
But even the best of us are prone to fall for it, and sometimes they even produce excellent results, cf. Donald Knuth and the TeX / Metafont ecosystem:
Between 1977 and 1979 computer scientist Donald E. Knuth of Stanford University created the TeX page-formatting language and the Metafont character shape specification language, originally as a way of improving the typography of his own publications. [...] -- https://historyofinformation.com/detail.php?id=3339
Does this really happen?
My experience is that programmers always try to make things as simple as possible, and when they fail at that, it's because they don't know how, or don't have enough time, or maybe the "simple" solution isn't persuasive enough that it covers all the cases, so a "more complex" version is preferred, or something like that; not because they forgot "whoops" I was supposed to make things simple not complicated.
The only times I have heard "KISS" suggested in earnest have been from bad managers.
> But even the best of us are prone to fall for it, and sometimes they even produce excellent results, cf. Donald Knuth and the TeX / Metafont ecosystem:
I don't see how this has anything to do with failing to keeping things simple, yak shaving for sure, but this yak (if it's a yak) did need the shave: there weren't any typesetting systems comparable to TeX at the time (and by some opinions there still aren't). What else can you do? Have someone spend hours typesetting and resetting a thousand page book every time there's an error, or turn the job over to a computer and automatically typeset it?
This is just solving problems. Solving problems you have is good, and where people go wrong, it's when they are solving problems they don't have (but perhaps think they might), or perhaps they underestimate how much of their problem the computer could actually solve.
This is very much an easy trap to fall into! What helped me was not sweating over the small stuff and setting up an instance of Grav, though I think that most of the turnkey blogging solutions out there would work (e.g. Ghost/Bolt as well, maybe not self-hosted Wordpress as a first option due to large surface area): https://getgrav.org/
What I really like about that solution in particular is that it is flat-file based and also has an admin web dashboard that's a separate plugin that can be enabled/disabled (some might prefer writing text files directly, with front matter and all) and has separate URL path that can be put behind basicauth (in addition to built in auth), client certificate auth or anything else.
It's not perfect, of course, and has given me the occasional headaches, but it's also good enough for my blog: https://blog.kronis.dev/
That said, I still struggle with my homepage - instead of going back through 5+ years of projects and describing all of the noteworthy ones, putting up a few galleries of screenshots, listing technologies, ordering them by relevance and also making sure that it doesn't contain too much data... it's just sitting there, on my TODO list. It's been that way for a while now.
I want it done. But I don't want to do it.
To clarify: that is not yak shaving, that is just plain old procrastination. Yak shaving includes tasks that you have to complete in order to do whatever your original intent was. For example:
That is yak shaving.The example (and definition) in the actual article disagree with you:
"You want to bake an apple pie, so you head to the kitchen. In the hallway, you notice some paint chipping on the wall. So you walk to the hardware store for some paint."
You obviously don't need to deal with the paint chipping before baking an apple pie.
Wikitionary gives both definitions: a blocking task or a procrastination detour
Create a GitHub repository and create a journal repository and create a markdown heading for each entry. It works.
I'm on 4 pages of 100+ journal entries each. See my profile, I journal computer ideas, algorithms in the open.
Using WordPress or using complicated software shall take time away from writing regularly. And you need to open a document and write, not abandon your blog due to forgetting how to post
When quasi-blogspam articles like this rise to the top so quickly, one has to wonder whether it’s the result of vote manipulation.
Uniqueness, mystery, narratives and humor/silliness are probably big drivers of attention on forums and news sites. Like the other commenter suggested, the gold is typically in the comments. I don’t have data to back up this assertion, but it would make for a good study/article.
The magic is in the Ren & Stimpy reference.
https://news.ycombinator.com/item?id=32746200
Oh well, back to yak having under the bike shed.
We’re kinda going the opposite way: If you find something that should be fixed, then fix it.
This is, of course, meant for small things, like renaming or rewriting expressions to make them more readable. But we have had to make this change, because our experience is this is necessary to avoid code rot.
There are a few benefits
If your refactor is large, you can get a bug fix in ASAP in a small PR, and get the large PR reviewed later. Sometimes I’ve done a refactor with a stubborn CI integration test or two that might take a few days to fix due to long feedback cycles.
Aside from that it lets your reviewer enter a different mindset for each change. The bug fix is more easily understood, and the reviewer expects a change in behavior. For a refactor the reviewer can usually review in a more relaxed manner because they know the behavior can/should be the same, and good unit tests should identify any differences in behavior
I guess that opens the debate to does the code actually need to be refactored? Sometimes not, but I have a very hard time leaving a 2000 line function alone, or a class with many levels of unnecessary inheritance.
What I’ve started to think is that there are people who get things done, and people who refactor.
People who get things done ship code fast. The good ones know when to make trade offs of purity vs practicality. The bad ones write unmaintainable code. They tend to view programming as a job, and code quality as a burden. They may refactor and make unrelated improvements, but it’s uncommon.
People who refactor still get things done, but most of their work have rabbit holes tacked on. They delivered a bug fix, but they also greatly improved the test suite and tooling. They tend to value purity, best practices, and might view programming as a craft/art. The good refactorers make the high value changes that are a net benefit to the team; they might care about cleaning up important parts of the code, improving developer experience, or adding test coverage to critical functions. The bad refactorers rewrite a bunch of code because it wasn’t pure, and the team, customers, and business have no observable effect from it.
I think teams need both kinds of people on it. Too many doers will lead to fast progress at first, but eventually grind to a haunt. I felt this was a HUGE problem at my team in AWS, and a major factor of why I left.
Too many refactorers is equally problematic. Your code will be of great quality, but velocity will be unacceptable for the business.
I personally am a refactorer. probably more of a bad refactorer than good, but it’s something I’m working on.
Maybe this is a rationalization for my behavior so that I believe it’s important, but my time at AWS shipping 3 features a year with a team of 16 says that code quality really does matter.
It's a matter of focus and intentionality.
'Phase 2 never happens'
Yes, that's probably a sign of poor project management or organisational brokenness. But it's also probably the reality for most people.
> It also misses the point that sometimes refactoring makes it _easier_ to fix the bug, and that a large part of fixing a bug is understanding exactly what's happening with the code, which refactoring can also make easier.
https://news.ycombinator.com/item?id=32749390
I clicked on this article because it applies to me (I constantly yak shave), but I’m a bit disappointed with how terse it was.
I have had this conversation yesterday, and the refactorer asked this very question. Here's my answer:
The question is improperly formulated. With your behavioral patterns of immediate refactoring, the question seems to be: "if I don't refactor this code NOW, who will?".
I'd say that if you don't refactor the code now, someone else, maybe future you, may refactor it later.
Most sane companies will protect engineering from impulsive feature requests and will add them to the backlog for future consideration.
I'm trying to instill the same protective mindset in my teams, and help them not do refactorings immediately but rather consider them as potential work as dedicated items in the sprints or so.
Doing so, prioritizing becomes a natural part of the refactoring/tech debt/tech risks agenda, because we have an overview of the work to do globally.
I guess this is delving into queue theory and how the work queue is growing to infinity because there aren’t enough workers.
I miss personal projects
I’m still trying to internalize this hah
Meanwhile, I can't get refactor-only commits through because nobody wants the code to be touched unless absolutely necessary.
We're in the middle of migrating a massive PHP codebase to Java. The code I'm talking about is newer Java code. In a few years, people will be wondering why the Java code is as much as a mess as the PHP code and, if I happen to still be around, my response will effectively be "I told you so" (in kinder, more productive terms).
I've basically determined that my only option to ensure continued or improving code quality is to combine refactoring and bug fixes in the same merge request, while still keeping them in separate commits. That way whenever I touch a part of code for bug fixing or whatever else, I leave it behind in much better state than it was before.
I agree, in practice I think this is the best option, with some kind of timebox for the improvements made.
One thing I'd like to add is setting up some kinds of tests. If nothing else is available, E2E tests for the critical paths of the business are a good start. For (micro)services, getting API contract tests to work is also invaluable.
The guy the goes around blasting bugs like there's no tomorrow looks good to the boss. When he leaves someone will have to refactor his mess and that's wasting time again.
- You have the best mental model about a piece of code and its system the best when you are working on it, not when you read a ticket description of what should happen. This leads to overall better efficiency and less context switching.
- I think that the principles of "leave things better than you first found them" and "with every not-so-minor change, one should think about how would you architect the system the best way possible at this current time" great principles.
- I find that "Refactoring sprints" never really work great. They tend to be inefficient and rarely prioritized tasks by the management. As developers we have responsibility over code and make sure that its in the best state possible as an implicit description of our profession.
Even though it pays to be focused, I think there is merit in the exploration of code-base as it helps figure out new ideas and avenues of improvement.
Small refactorings and cleaning alongside bugfix are fine. Big refactoring should happen independently, of course.
- You can deliver the two individual parts quicker
distractions are real, at some point I pomodoro technique helps, however when I get interested/distracted with something else at the code then it's pointless
This brings me to my next point: know what you're supposed to be working on. I like to write it down at the start of the day while I have breakfast, before I touch a computer.
I think in programming it is easy to get lost in scale. We all know these videos where you scale in from the universe into a single atom. In programming tou operate at similar dieseperate scales. You need to have the high level perspective ("I want to get to this mountaintop!"), the mid level perspective ("I chose to scale the mountain via that route") and the detail level perspective ("I put that finger into that nook of the rock to my left and shift my weight slightly to the right..") and of course there is also a tooling perspective ("What kind of gear do I need to scale that mountain?").
When you operate just at the detail level it can happen that you end up on the wrong mountain, branch off into the wrong route etc.
To make things worse you can also have a meta-perspective ("How will this help me beyond the mountain I am currently on?").
[1] https://www.conventionalcommits.org/en/v1.0.0/ [2] https://github.com/RefactoringCombos/ArlosCommitNotation
So now instead of fixing my bug I’m rewriting API call sites across my project.
I quite like the Malcolm in the Middle[0] example of yak-shaving, though it's a combination of both blockers and distraction.
[0]: https://www.youtube.com/watch?v=8fnfeuoh4s8
> yak shaving - Any seemingly pointless activity which is actually necessary to solve a problem which solves a problem which, several levels of recursion later, solves the real problem you're working on.
If I’m implementing a new feature, should I also disregard the need for refactoring?
A more nuanced approach is needed. You need to learn when to make changes additively and when to reshape the code to fit your new use case (and how much reshaping is required).
As an aside: I think tech debt sprints (if needed regularly) are often a sign that you aren’t developing software sustainably day to day.
If the code is a mess and I'm going to refactor it anyway should I spend a lot of time trying to fix the bug in the old code only to refactor it afterwards? Or should I refactor and deliberately leave the bug in there only to fix it afterwards?
To me doing them together often makes sense and I don't remember code reviewers ever complaining. But maybe I'm missing something?
With this kind of framing we can look at the cause of yak shaving as a failing of an individual, rather than a lack of an accurate and holistic view of what the task entails given the current state of the system.
>In this case, there is nothing wrong with addressing them in a tech debt sprint.
Let me guess how often these happen... Maybe once a year to.. never?
Somehow, in practice, I've seen the fixing plus enhancements work better in getting the code in a better shape.
Also, why are we not good with doing both at the same time? If its because it makes things harder to review, I've found that pairing on the review and adding clarifying comments to the PR is a much better way. If its for the commit history, is it always more important to have a squeaky clean commit history than to have easier to read (I'm presuming this is the intent of the refactor) code? Is there some point after which the code is bad enough to sacrifice some commit history clarity to get better code?
> You may even decide that these enhancements are distracting you from your immediate goal of shipping a feature. In this case, there is nothing wrong with addressing them in a tech debt sprint.
Has anyone actually seen this work? In my experience, once the original bug is out of the way there is no motivation or vision on how or why to make the cleanup and the tech debt tasks are left to rot forever, while the code slowly turns into mud. Does anyone know how to avoid this?
IMO the thing that works best is to do the yak shaving first before the bugfix. But also, timebox the effort for yak shaving - you're only allowed to do a certain amount.