[HN Gopher] Be Aware of the Makefile Effect
___________________________________________________________________
Be Aware of the Makefile Effect
Author : thunderbong
Score : 313 points
Date : 2025-01-11 04:13 UTC (18 hours ago)
(HTM) web link (blog.yossarian.net)
(TXT) w3m dump (blog.yossarian.net)
| kazinator wrote:
| At first I couldn't understand what this article is saying. Then,
| .SECONDEXPANSION: kicked in!
| rpcope1 wrote:
| I feel this way every time with webpack, npm and babel.
| Over2Chars wrote:
| A clever point, worth discussing
| travisgriggs wrote:
| It's like a variant of Pournelles Law.
| fargle wrote:
| i think you got the wrong eponymous law, pournelle's iron law
| of bureaucracy (which i see happening _all_ the time, btw.) has
| nothing to do with this issue.
| donatj wrote:
| If I had a nickel for every time I have seen a Makefile straight
| up copied from other projects and modified to "work" while
| leaving completely unrelated unnecessary build steps and targets
| in place.
|
| It's a major pet peeve of mine.
| bboygravity wrote:
| How do you know what is and isn't related if nothing is
| documented?
|
| Trial and error?
|
| Well have fun with that :p
| donatj wrote:
| Exactly. Bonus points if the person who started the project
| moved on and you have to be the one to build and maintain it.
| rmgk wrote:
| You find the first part in your stack that is documented
| (e.g., make is documented, even if your makefile is not) and
| use that documentation to understand the undocumented part.
| You then write down your findings for the next person.
|
| If you don't have enough time, write down whatever pieces you
| understood, and write down what parts "seem to work, but you
| don't understand" to help make progress towards better
| documentation.
|
| If you put the documentation as comments into the file, this
| can make copy&pasting working examples into a reasonably
| solid process.
| marcosdumay wrote:
| Hum...
|
| You know, a makefile _is_ documentation. That 's why you
| should probably never copy one (except for a single line here
| or there). There's space for commenting a few stuff, but your
| target names and variables should explain most of what is
| going there.
|
| Anyway, the article and most people here seem to be talking
| about those autotools generated files. Or hand-built ones
| that look the same way. But either way, it's a bad solution
| caused by forcing a problem to be solved by a tool that
| wasn't aimed at solving it. We have some older languages
| without the concept of a "project" that need a lot of hand-
| holding for compiling, but despite make being intentionally
| created for that hand-holding, it's clearly not the best tool
| for that one task.
| mcdeltat wrote:
| At my work I've noticed another contributing factor:
| tools/systems that devs need to interact with at some point, but
| otherwise provide little perceived value to learn day-to-day.
|
| Example is build system and CI configuration. We absolutely need
| these but devs don't think they should be expected to deal with
| them day to day. CI is perceived as a system that should be "set
| and forget", like yeah we need it but really I have to learn _all
| this_ just to build the app? Devs expect it to "just work" and
| if there are complexities then another team (AKA my role) deals
| with that. As a result, any time devs interact with the system,
| there's a high motivation to copy from the last working setup and
| move on with their day to the "real" work.
|
| The best solution I see is meet the devs halfway. Provide them
| with tooling that is appropriate simple/complex for the task,
| provide documentation, minimise belief in "magic". Tools like
| Make kinda fail here because they are too complex and black-box-
| like.
| exitb wrote:
| The office coffee machine is not ,,set and forget", but you
| wouldn't expect the entire responsibility for it's maintenance
| to be evenly distributed between all people that use it.
| Similarly, CI needs ownership and having it fall on the last
| developer that attempted to use it is not an efficient way of
| working.
| nicoburns wrote:
| For me the big problems with CI setups tend to be:
|
| - They're often slow
|
| - They're often proprietary
|
| - They're often dealing with secrets which limits who can work
| on them
|
| - You generally can't run them locally
|
| So the feedback cycle for working on them is incredibly long.
| And working on them is therefore a massive pain.
| sharkjacobs wrote:
| > You generally can't run them locally
|
| I recognize that this is such a disincentive for me taking
| the initiative to fiddle with and learn about anything like
| this
| vintermann wrote:
| Same goes for anything "enterprisey". Last time I set up a
| big project, I made a commitment that "we should be able to
| check out and build this whole thing, for as long as
| humanly possible".
| pipes wrote:
| The local part is my big problem too. I used azure Dev ops in
| work. I find clicking through the UI to be a miserable
| experience, Id love to have it running locally so I could
| view inputs and outputs on the file system. Also yaml is an
| awful choice, no one I know enjoys working with it. The white
| space issues just get worse and worse longer your files get.
| tempodox wrote:
| > You generally can't run them locally
|
| GitLab CI gives you local runners. You can completely self-
| host CI.
| Joker_vD wrote:
| Well, yes, but aren't those runners have different
| configuration than the runners that are actually deployed
| and used by your company's CI/CD?
| tempodox wrote:
| Wat? Our company's CI _is_ GitLab CI, self-hosted. What
| other runners would we need?
| Joker_vD wrote:
| The local ones, mentioned in the original comment that
| we've been discussing in this thread? The local runner,
| executing on the developer's machine.
| tempodox wrote:
| Of course it makes no difference whether that runner runs
| on our local CI host or on my dev machine.
| Izkata wrote:
| I think GP got confused, it's not running the runners
| locally, it's running the CI steps locally (see the other
| sibling replies).
|
| For example, running tests locally exactly the same way
| as in the runner - sometimes I have to open a debugger in
| the middle of a test to see what exactly went wrong. Our
| tests run in gitlab in a particular docker image, and
| I've been adding a "make test" that runs the same tests
| in the same image locally, with additional flags to have
| full interactivity so the debugger works if needed.
| Plasmoid wrote:
| It's not self hosting. It's can I run the build from my
| local command line and get the same results.
| tempodox wrote:
| How is running those runners on our own hosts (locally)
| not self-hosting?
| mdaniel wrote:
| Spoken like someone who has not tried what you are
| describing. There are two moving parts to your response:
| a locally _hosted_ runner awaits jobs from GitLab itself,
| which doesn 't help running _locally_, and the other part
| is that -- back when it existed! -- trying $(gitlab-
| runner exec) was not a full fledged implementation of the
| GitLab CI concepts, making it the uncanny valley of "run
| something locally."
|
| However, as of v16 there is no more exec
| https://gitlab.com/gitlab-org/gitlab/-/issues/385235
| which I guess is good and bad. Good in that it not longer
| sets improper expectations that it could have plausibly
| done anything, and bad in that now it joins GitHub
| Actions[1] in not having any _local_ test strategy aside
| from "boot up gitlab/gitlab-ce && echo good luck"
|
| 1: yes, I'm acutely aware of the 3(?)
| implementations/forks of nektos/act that claim to do GHA
| but, again, readme is not software and I can tell you
| with the utmost certainty they do not do as advertised
| Joker_vD wrote:
| Not to mention that the rest of the environment is
| missing: e.g. you probably can't push to e.g. the
| organization's Docker registry/Artifactory/whatever from
| you local dev machine (if it's even visible from your
| machine in the first place). And those are arguably the
| _most_ interesting parts that you want to test the
| integration with.
| internet_points wrote:
| Yeah, I think this is the real issue. Too many different tool
| types that need to interact, so you don't get a chance to get
| deep knowledge in any of them. If only every piece of
| software/CI/build/webapp/phone-app/OS was fully implemented in
| GNU make ;-) There's a tension between using the best tool for
| the job vs adding yet another tool/dependency.
| tempodox wrote:
| If you think `make` is "too complex and black-box-like" then
| you haven't seen `cmake`.
| vintermann wrote:
| If you think cmake is a good example of more complex than
| make, then you haven't seen automake/autoconf. The first
| thing I thought of. You can find tons of tons of configure
| scripts that check if you're running ancient versions of
| Unix, checks that a byte is 8 bits wide, and a ton of other
| pointless checks. They don't _do_ anything with all that
| information, don 't think for a moment that you can
| _actually_ build the app on Irix, but the checks for it have
| been passed along for decades likes junk DNA.
| tempodox wrote:
| Firstly, automake/autoconf is not `make`, but a different
| piece of software, and secondly, that you know all those
| details about it is because it is not black-box-like.
| vintermann wrote:
| I never said it was. It's a script to generate a script
| to generate a makefile, more or less.
|
| If it wasn't black box like, why do people keep blindly
| copying tests which check things which haven't been
| relevant for decades and in any case would require a ton
| of manual effort to actually use for something?
| pwdisswordfishz wrote:
| I have seen both, and I consider them roughly similar.
| john-tells-all wrote:
| Strong agree. The best workflow I've seen uses CICD as a _very
| thin_ wrapper around in-tree scripts or make files.
|
| If a Dev can run some/all of the "cicd" stuff locally, they can
| see, control, and understand it. It helps _tremendously_ to
| have a sense of ownership and calm, vs "cicd is something
| else, la la la".
|
| (This doesn't always work. We had a team of _two_ devs, who had
| thin-wrapper CICD, who pretended it was an alien process and
| refused to touch it. Weird.)
| peterldowns wrote:
| +1. The only CI tool that I've seen really organize around
| this principle is Buildkite, which I've used and enjoyed. I'm
| currently using Github Actions and it's fine but Buildkite is
| literally sooooo good for the reasons you've mentioned.
| IgorPartola wrote:
| Make is one of the simplest build tools out there. Compared to
| something like Grunt, Webpack, etc. it's a hammer compared to a
| mining drill.
|
| The solution is to not use tools used by large corporations
| because they are used by large corporations. My unpopular
| opinion is that CI/CD is not needed in most places where it's
| used. Figure out how to do your builds and deploys with the
| absolute fewest moving pieces even if it involves some extra
| steps. Then carefully consider the cost of streamlining any
| part of it. Buying into a large system just to do a simple
| thing is often times not worth it in the long run.
|
| If you really do need CI/CD you will know because you will have
| a pain point. If that system is causing your developers pain,
| it isn't the right fit.
| fithisux wrote:
| Alias, cmake effect.
| chikere232 wrote:
| Let's keep "cmake effect" for "trying your best to not have to
| touch the language and repeatedly looking for something else
| whenever you do"
|
| It's a very microsoft feeling pile of crap
| szarnyasg wrote:
| I have observed the Makefile effect many times for LaTeX
| documents. Most researchers I worked with had a LaTeX file full
| of macros that they have been carrying from project to project
| for years. These were often inherited from more senior
| researchers, and were hammered into heavily-modified forks of
| article templates used in their field or thesis templates used at
| their institution.
| wjholden wrote:
| This is a great example of an instance of this "Makefile
| effect" with a possible solution: use Markdown and Pandoc where
| possible. This won't work in every situation, but sometimes one
| can compose a basic Beamer presentation or LaTeX paper quickly
| using largely simple TeX and the same Markdown syntax you
| already know from GitHub and Reddit.
| kergonath wrote:
| > use Markdown and Pandoc where possible.
|
| That won't solve any problem that LaTeX macros solve.
| Boilerplate in LaTeX has 2 purposes.
|
| The first is to factor frequently-used complex notations. To
| do this in Markdown you'd need to bolt on a macro
| preprocessor on top of Markdown.
|
| The second one is to fine-tune typography and layout details
| (tables are a big offender). This is something that simply
| cannot be done in Markdown. A table is a table and if you
| don't like the style (which is most of the time inadequate)
| then there is no solution.
| gardenerik wrote:
| A much better solution would be to use Typst, but that still
| might not work in all situations.
| baobun wrote:
| Good points in general.
|
| On the other hand, there are cases where (beneficial/desired)
| verbosity prompts copy-paste and tweaking - not due to complexity
| but from some form of scale or size of the input.
|
| In many cases this is a sign of something that should be dynamic
| data (put it in a db instead of conf) but that's not always the
| case and worth the tradeoff in the moment.
| lazystar wrote:
| amazon's internal build tool experiences this same phenomena.
| engineers are hired based on their leetcode ability; which means
| the average engineer has gaps in their infrastructure and config
| tool knowledge/skillset. until the industrys hiring practices
| shift, this trend will continue.
| marxisttemp wrote:
| As an undergrad, I did group projects with people who quite
| literally could not compile and run any actual project on their
| system outside of a pre-packaged classwork assignment, who
| essentially could not code at all outside of data structure and
| algorithm problem sets, who got Google internships the next
| semester.
|
| But they were definitely brighter than I when it came to such
| problem sets. I suppose we need both sorts of engineer to make
| great things
| ruuda wrote:
| I think LaTeX is the poster child of this. Nobody writes a LaTeX
| preamble from scratch, you always copy your previous document and
| tweak it.
| __mharrison__ wrote:
| I use Typst now instead and wrote the "preamble" from scratch.
| (Because Typst is that much less annoying than LaTeX)
| sandbach wrote:
| Don't do that! If you're always using the same preamble, you
| should turn it into a .sty file. Then the preamble of new
| documents is just \usepackage{myessay}
| aragilar wrote:
| I did that, then I needed to tweak things so I added options,
| then I needed to use the package somewhere that needed to be
| self-contained, so I started copy-pasting ;). I've done
| similar things with makefiles, tox configs, linter settings
| (all of which started from an initial version I wrote from
| scratch).
|
| I suspect the _real_ reason this effect exists is because
| there 's copy-pasting is the best way to solve the problem,
| due to a varying mix of: there being no way of managing the
| dependencies, needing to avoid (unmanaged) dependencies (i.e.
| vendoring is the same, only we have a tool managing it), the
| file (or its contents) needing to exist there specifically
| (e.g. the various CI locations) and no real agreement on what
| template/templating tool to use (and a template is just as
| likely to include useless junk). Copy-pasting is viewed as a
| one-time cost, and the thing copy-pasted isn't expected to
| change all that much.
| ttyprintk wrote:
| Definitely true for linting. Nothing unlike a linter solves
| the problems we want the linter to solve.
| fph wrote:
| Then you make a change to myessay.sty and suddenly four of
| your old files stop compiling.
| BlueTemplar wrote:
| I guess that there's a very important difference between
| copying something that you understand (or at least the details
| of which, like syntax, you can easily remember - here comments
| become important),
|
| and copying something that not only you do not understand, but
| you were not the one that made it in the first place, and you
| never understood it !
| leoc wrote:
| Old IBM mainframe scripting in JCL
| https://en.wikipedia.org/wiki/Job_Control_Language (so "OS JCL"
| now, I suppose) used to have a terrible reputation for this, but
| I've never actually touched the stuff myself.
| malkia wrote:
| or ahem... CMake
| mattbillenstein wrote:
| I think Makefile is maybe the wrong analogy - the problem with
| most people and makefiles is they write so few of them, the
| general idea of what make does is at hand, but the muscle memory
| of how to do it from scratch is not.
|
| But, point taken - I've seen so much code copy-pasta'd from the
| web, there will be like a bunch of dead stuff in it that's
| actually not used. A good practice here is to keep deleting stuff
| until you break it, then put whatever that was back... And delete
| as much as possible - certainly everything you're not using at
| the moment.
| sumanthvepa wrote:
| This is exactly the problem I face with many tools, Makefiles,
| KVM setups, docker configurations, CI/CD pipelines. My solution
| so far has been to create a separate repository with all my
| notes, shell script example programs etc, for these tool,
| libraries or frameworks. Every time I have to use these tools,
| I refer to my notes to refresh my memory, and if I learn
| something new in the process, I update the notes. I can even
| point an LLM at it now and ask it questions.
|
| The repository is personal, and contains info on tools that are
| publicly available.
|
| I keep organisation specific knowledge in a similar but
| separate repo, which I discard when my tenure with a client or
| employer ends.
| parasti wrote:
| What if your client comes back?
|
| On a more practical note, what structure, formats and tools
| do you use that enable you to feed it to an LLM?
| sumanthvepa wrote:
| I'm usually contractually obligated to destroy all client
| IP that I may posses at the end of an engagement. My
| contracts usually specify that I will retain engagement
| specific information for a period of six months beyond the
| end of the contract. If they come back within that time,
| then I'll have prior context. Otherwise it's gone.
| Occasionally, a client does come back after a year or two,
| but most of the knowledge would have been obsolete and
| outdated anyway.
|
| As for LLMs. I have a couple of python scripts that
| concatenate files in the repo into a context that I pass to
| Google's Gemini API or Google AI studio, mostly the latter.
| It can get expensive in some situations. I don't usually
| load the whole repository. And I keep the chat context
| around so I can keep asking question around the same topic.
| teo_zero wrote:
| > the tool (or system) is too complicated (or annoying) to use
| from scratch.
|
| Or boring: some systems require boilerplate with no added value.
| It's normal to copy & paste from previous works.
|
| Makefiles are a good example. Every makefile author must write
| their own functionally identical "clean" target. Shouldn't there
| be an implicit default?
|
| C is not immune, either. How many bits of interesting information
| do you spot in the following excerpt? #include
| <stdio.h> int main(int argc, char **argv) {
| printf("Hello\n"); return 0; }
|
| The printf alone is the real payload, the rest conveys no
| information. (Suggestion for compiler authors: since the programs
| that include stdio.h outnumber those that don't, wouldn't it be
| saner for a compiler to automatically do it for us, and accept a
| flag to not do it in those rare cases where we want to deviate?)
| skirge wrote:
| more implicit behaviors more surprises, like security bugs
| because default functionality or conversions happen
| oguz-ismail wrote:
| > wouldn't it be saner for a compiler to automatically do it
| for us
|
| no
| lucianbr wrote:
| > since the programs that include stdio.h outnumber those that
| don't
|
| I don't think that is true. There is a lot of embedded systems
| C out there, plus there are a lot of files in most projects,
| and include is per file not per project. The project might use
| stdio in a few files, and not use it in many others.
| brabel wrote:
| > The printf alone is the real payload, the rest conveys no
| information.
|
| What are you talking about? Every line is important.
| #include <stdio.h>
|
| This means you need IO in your program. C is a general purpose
| language , it shouldn't include that unless asked for. You
| could claim it should include stuff by default, but that would
| go completely against what C stands for. Code shouldn't have to
| depend on knowing which flags you need to use to compile
| successfully (at least not in general like this).
| int main(int argc, char** argv)
|
| Every program requires a main function. Scripting languages
| pretend they don't, but they just wrap all top-level code in
| one. Having that be explicit, again, is important for a low
| level language like C. By the way, the C standard lets you
| declare it in a simplified manner: int
| main(void)
|
| Let's ignore the braces as you could just place them on the
| same line. printf("Hello\n");
|
| You could just use `puts` here, but apart from that, yeah
| that's the main payload, cool. return 0;
|
| The C standard actually makes this line optional. Funny but I
| guess it addresses your complaint that "common stuff" perhaps
| should not be spelled out all the time?
|
| So, here is the actual minimalist Hello world:
| #include <stdio.h> int main(void) {
| puts("Hello world\n"); }
| teo_zero wrote:
| Thank you, but this thread was not about writing good code,
| but rather how often one ends up acritically copying existing
| "legacy" parts without even attempting to understand it.
|
| I probably used the wrong words: "conveys no information" was
| meant as "is less meaningful than the printf". Just like
| switching on the PC every morning is essential, but if you
| ask me what my job's about, I wouldn't mention it.
|
| In the same vein, I'm convinced that the printf is the part
| that expresses the goal of the program. The rest, the
| #include, the main(), even with the optimizations that you
| suggested, is just boilerplate, the part that is usually
| copied and pasted, not because it's not useful and not
| because it's too difficult to get right, as the original
| article claims, but because it's boring.
| chikere232 wrote:
| > Makefiles are a good example. Every makefile author must
| write their own functionally identical "clean" target.
| Shouldn't there be an implicit default?
|
| At some point you have to give the system something to go on,
| and the part where it starts deleting files seems like a good
| one where not to guess.
|
| It's plenty implicit in other places. You can for example,
| without a Makefile even, just do `make foo` and it will do its
| best to figure out how to do that. If there's a foo.c you'll
| get a `foo` executable from that with the default settings.
| pantalaimon wrote:
| My main frustration with make has usually been with too much
| (surprising) implicit default behavior, not the lack thereof.
| dirkt wrote:
| Same with programming: You just copy some old code and modify it,
| if you have something lying around.
|
| Same with frameworks (Angular, Spring Boot, ...). The tools even
| come with templates to generate new boilerplate for people who
| don't have existing ones somewhere.
| Papirola wrote:
| I call it the yoghurt effect.
| fargle wrote:
| i'll bite. care to expand? is this a riff on copy-pasta or
| spaghetti code or what?
| __mharrison__ wrote:
| Setup.py, cron, makefile, bash scripts, GitHub actions, and
| devcontainers all had this effect... Until AI came around.
|
| Now AI does a great job of getting you 90-100% of the way there.
| mianos wrote:
| I have an alternate theory: about 10% of developers can actually
| start something from scratch because they truly understand how
| things work (not that they always do it, but they could if
| needed). Another 40% can get the daily job done by copying and
| pasting code from local sources, Stack Overflow, GitHub, or an
| LLM--while kinda knowing what's going on. That leaves 50% who
| don't really know much beyond a few LeetCode puzzles and have no
| real grasp of what they're copying and pasting.
|
| Given that distribution, I'd guess that well over 50% of
| Makefiles are just random chunks of copied and pasted code that
| kinda work. If they're lifted from something that already works,
| job done--next ticket.
|
| I'm not blaming the tools themselves. Makefiles are well-known
| and not too verbose for smaller projects. They can be a bad
| choice for a 10,000-file monster--though I've seen some cleanly
| written Makefiles even for huge projects. Personally, it wouldn't
| be my first choice. That said, I like Makefiles and have been
| using them on and off for at least 30 years.
| sebazzz wrote:
| > That leaves 50% who don't really know much beyond a few
| LeetCode puzzles and have no real grasp of what they're copying
| and pasting.
|
| Who likely wouldn't have a job if it weren't for LLMs.
| raziel2p wrote:
| pretty sure we've made this complaint about a subset of
| developers since way before chatgpt and the like.
| f1shy wrote:
| And that happens not only with developers, but in any
| profession, which gives me shivers when I go to the doctor!
| huijzer wrote:
| > That leaves 50% who don't really know much beyond a few
| LeetCode puzzles and have no real grasp of what they're copying
| and pasting.
|
| Small nuance: I think people often don't know because they
| don't have the time to figure it out. There are only so many
| battles you can fight during a day. For example if I'm a C++
| programmer working on a ticket, how many layers of the stack
| should I know? For example, should I know how the CPU registers
| are called? And what should an AI researcher working always in
| Jupyter know? I completely encourage anyone to learn as much
| about the tools and stack as possible, but there is only so
| much time.
| silver_silver wrote:
| We can't really call the field engineering if this is the
| standard. A fundamental understanding of what one's code
| actually makes the machine do is necessary to write quality
| code regardless of how high up the abstraction stack it is
| cudgy wrote:
| Sure if you are doing embedded programming in C. How does
| one do this in web development though where there are
| hundreds of dependencies that get updated monthly and still
| add functionality and keep their job?
| kragen wrote:
| Maybe switch to less frequently updated dependencies and
| rewrite the easy ones in-house?
| pdimitar wrote:
| Yes, and I should overrule half the business decisions of
| the company while I am at it. Oh, and I'll push back on
| "we need the next feature next week" and I'll calmly
| respond "we need to do excellent engineering practices in
| this company".
|
| And everybody will clap and will listen to me, and I will
| get promoted.
|
| ...Get real, dude. Your comments come across a bit tone-
| deaf. I am glad you are in a privileged position but you
| seem to have fell for the filter bubble effect and are
| unaware to how most programmers out there have to work if
| they want to pay the bills.
| ori_b wrote:
| Yes, sometimes things are unfixably broken, and it's
| impossible to build anything good.
|
| For everything else, there's MasterCard.
| pdimitar wrote:
| Any golden MasterCards with $50M one-time limit you could
| offer for free? I can think of a few things to fix with
| those.
|
| RE: unfixably broken, well, not necessarily in concept
| but de facto you are sadly correct. Most people resist
| even the provably good changes.
| klibertp wrote:
| > For everything else, there's...
|
| ...the very definition of brokenness :D Not much of a
| (good) choice there...
| kragen wrote:
| I know a lot of people have terrible jobs at profoundly
| dysfunctional companies. I've had those too. That
| situation doesn't improve unless you, as they say, have
| the serenity to accept the things you cannot change, the
| courage to change the things you can, and the wisdom to
| know the difference.
|
| Not everyone has a position where they have the autonomy
| to spend a lot of effort on paying down technical debt,
| but some people do, and almost every programmer has a
| little.
|
| I think it's important to keep in view both your personal
| incentive system (which your boss may be lying to you
| about) and the interests of the company.
| pdimitar wrote:
| The serenity in question boils down to "I'll never make
| enough money to live peacefully and being able to take a
| two years sabbatical so let's just accept I'll be on the
| hamster wheel for life and I can never do anything about
| it".
|
| No. I'll let my body wither and get spent before my
| spirit breaks. I refuse to just "accept" things. There's
| always something you can do.
|
| BTW is that not what HN usually preaches? "Change your
| job to a better one" and all that generic motivational
| drivel [that's severely disconnected from reality]? Not
| throwing shade at you here in particular, just being a
| bit snarky for a minute. :)
|
| RE: your final point, I lost the desire to keep view of
| both my personal and my company's incentive systems. Most
| "incentive systems" are basically "fall in line or GTFO".
|
| Before you ask, I am working super hard to change my
| bubble and get a bit closer to yours. To say it's not
| easy would be so understated so as to compare the
| description of a lightning hit on you and you enduring
| the said lightning hit. But as said above, I am never
| giving up.
|
| But... it's extremely difficult, man. Locality and your
| own marketing matter a lot, and when you have been
| focused on technical skills all your life and marketing
| is as foreign to you as are the musical notes of an alien
| civilization... it's difficult.
| kragen wrote:
| I can't recommend others follow my path. Some of the
| results have been pretty bad. Hopefully your path works
| out well. We all die in the end.
| silver_silver wrote:
| The current state of web development is unfortunately a
| perfect example of this quality crisis. The tangle of
| dependencies either directly causes or quickly multiplies
| the inefficiency and fragility we've all come to expect
| from the web. The solution is unrealistic because it
| involves design choices which are either not trendy
| enough or precluded by the platform
| kragen wrote:
| Steam engines predate the understanding of not just the
| crystalline structure of steel but even the basics of
| thermodynamics by quite a few decades.
| silver_silver wrote:
| Yes and they're far less efficient and require far more
| maintenance than an equivalent electric or even diesel
| engine, where equivalent power is even possible
| BlueTemplar wrote:
| Why do you assume that the same doesn't apply to electric
| and diesel engines ?
| kragen wrote:
| Steam engines currently power most of the world's
| electrical grid. The main reason for this is that,
| completely contrary to what you said, they are more
| efficient and more reliable than diesel engines.
| (Electric motors of course are not a heat engine at all
| and so are not comparable.)
|
| Steam engines used to be very inefficient, in part
| because the underlying thermodynamic principles were not
| understood, but also because learning to build safe ones
| (largely a question of metallurgy) took a long time. Does
| that mean that designing them before those principles
| were known was "not engineering"? That seems like obvious
| nonsense to me.
| foobarchu wrote:
| I don't consider that an equal comparison. Obviously an
| engineer can never be omniscient and know things nobody
| else knows either. They can, and should, have an
| understanding of what they work with based on available
| state of the art, though.
|
| If the steam engine was invented after those discoveries
| about steel, I would certainly hope it would be factored
| into the design (and perhaps used to make those early
| steam engines less prone to exploding).
| silveraxe93 wrote:
| This is the 40% that OP mentioned. But there's a proportion
| on people/engineers that are just clueless and are incapable
| of understanding code. I don't know the proportion so can't
| comment on the 50% number, but hey definitely exist.
|
| If you never worked with them, you should count yourself
| lucky.
| kragen wrote:
| If you spend 80% of your time (and mental energy) applying
| the knowledge you already have and 20% learning new things,
| you will very quickly be able to win more battles per day
| than someone who spends 1% of their time learning new things.
|
| Specifically for the examples at hand:
|
| - at 20%, you will be able to write a Makefile from scratch
| within the first day of picking up the manual, rather than
| two or three weeks if you only invest 1%.
|
| - if you don't know what the CPU registers are, the debugger
| won't be able to tell you why your C++ program dumped core,
| which will typically enable you to resolve the ticket in a
| few minutes (because most segfaults are stupid problems that
| are easy to fix when you see what the problem is, though the
| memorable ones are much hairier.) Without knowing how to use
| the disassembly in the debugger, you're often stuck debugging
| by printf or even binary search, incrementally tweaking the
| program until it stops crashing, incurring a dog-slow C++
| build after every tweak. As often as not, a fix thus
| empirically derived will merely conceal the symptom of the
| bug, so you end up fixing it two or three times, taking
| several hours each time.
|
| Sometimes the source-level debugger works well enough that
| you can just print out C++-level variable values, but often
| it doesn't, especially in release builds. And for performance
| regression tickets, reading disassembly is even more
| valuable.
|
| (In C#, managed C++, or Python, the story is of course
| different. Until the Python interpreter is segfaulting.)
|
| How long does it take to learn enough assembly to use the
| debugger effectively on C and C++ programs? Tens of hours, I
| think, not hundreds. At 20% you get there after a few dozen
| day-long debugging sessions, maybe a month or two. At 1% you
| may take years.
|
| What's disturbing is how many programmers never get there.
| What's wrong with them? I don't understand it.
| icameron wrote:
| That's an insightful comment, but there is a whole universe
| of programmers who never have to directly work in C/C++ and
| are productive in safe languages that can't segfault
| usually. Admittedly we are a little jealous of those elite
| bitcrashers who unlock the unbridled power of the computer
| with C++... but yeah a lot of day jobs pay the bills with
| C#, JavaScript, or Python and are considered programmers by
| the rest of the industry
| kragen wrote:
| Yeah, I write most things in Python or JavaScript because
| it's much more practical.
| remus wrote:
| You make it sound easy, but I think it's hard to know where
| to invest your learning time. For example, I could put some
| energy into getting better at shell scripting but
| realistically I don't write enough of it that it'll stick
| so for me I don't think it'd be a good use of time.
|
| Perhaps in learning more shell scripting I have a
| breakthrough and realise I can do lots of things I couldn't
| before and overnight can do 10% more, but again it's not
| obvious in advance that this will happen.
| kragen wrote:
| I agree. And there's no infallible algorithm. I think
| there are some good heuristics, though:
|
| - invest more of your time in learning more about the
| things you are currently finding useful than in things
| that sound like they could potentially be useful
|
| - invest more of your time in learning skills that have
| been useful for a long time (C, Make) than in skills of
| more recent vintage (MobX, Kubernetes), because of the
| Lindy Effect
|
| - invest more of your time in skills that are broadly
| applicable (algorithms, software design, Python,
| JavaScript) rather than narrowly applicable (PARI/GP,
| Interactive Brokers)
|
| - invest your time in learning to use free software
| (FreeCAD, Godot, Postgres) rather than proprietary
| software (SolidWorks, Unity, Oracle), because sooner or
| later you will lose access to the proprietary stuff.
|
| - be willing to try things that may not turn out to be
| useful, and give them up if they don't
|
| - spend some time every day thinking about what you've
| been doing. Pull up a level and put it in perspective
| BurningFrog wrote:
| One simple approach that the second, or at least third,
| time you deal with something, you invest time to learn it
| decently well. Then each time you come back to it, go a
| bit deeper.
|
| This algorithm makes you learn the things you'll need
| quite well without having to understand and/or predict
| the future.
| oweiler wrote:
| That's why suggestions like RTFM! are stupid. I just don't
| have time to read every reference documentation of every tool
| I use.
| kccqzy wrote:
| I feel like your working environment might be to blame:
| maybe your boss is too deadline-driven so that you have no
| time to learn; or maybe there is too much pressure to fix a
| certain number of tickets. I encourage you to find a better
| workplace that doesn't punish people who take the time to
| learn and improve themselves. This also keeps your skills
| up to date and is helpful in times of layoffs like right
| now.
| prerok wrote:
| Seriously? Yes, you should read the docs of every API you
| use and every tool you use.
|
| I mean, it's sort of ok if you read somewhere how to use it
| and you use it in the same way, but I, for one, always
| check the docs and more often even the implementation to
| see what I can expect.
| aulin wrote:
| you don't have the time because you spend it bruteforcing
| solutions by trial and error instead of reading the manual
| and doing them right the first time
| ajross wrote:
| > I completely encourage anyone to learn as much about the
| tools and stack as possible, but there is only so much time.
|
| That seems like a weird way to think about this. I mean,
| sure, there's no time _today_ to learn make to complete your
| C++ ticket or whatever. But yesterday? Last month? Last job?
|
| Basically, I think this matches the upthread contention
| perfectly. If you're a working C++ programmer who's failed to
| learn the Normal Stable of Related Tools (make, bash, python,
| yada yada) across a ~decade of education and experience, you
| probably never will. You're in that 50% of developers who
| can't start stuff from scratch. It's not a problem of time,
| but of curiosity.
| Joker_vD wrote:
| > I mean, sure, there's no time _today_ to learn make to
| complete your C++ ticket or whatever. But yesterday? Last
| month? Last job?
|
| That seems like a weird way to think about this. Of course
| there was no time in the past to learn this stuff, if you
| still haven't learned it by the present moment. And even if
| there were, trying to figure out whether there perhaps was
| some free time in the past is largely pointless, as opposed
| to trying to schedule things in the future: you can't
| change the past anyhow, but the future is somewhat more
| malleable.
| ajross wrote:
| To be clear: I'm not suggesting a time machine, and I'm
| not listing any particular set of skills everyone must
| have. I'm saying that excusing the lack of core job
| skills by citing immediate time pressure is a smell. It
| tells me that that someone probably won't ever learn
| weird stuff. And in software development, people who
| don't learn weird stuff end up in that 50% bucket posited
| upthread.
| n_ary wrote:
| > I'm saying that excusing the lack of core job skills by
| citing immediate time pressure is a smell. It tells me
| that that someone probably won't ever learn weird stuff.
| And in software development, people who don't learn weird
| stuff end up in that 50% bucket posited upthread.
|
| Or the whole chain of work culture is bad and people do
| not have adequate down time or brain juice to pursue
| these. Additionally, how many do you want to learn? I
| have dealt with Makefile, then recently someone decided
| to introduce taskfile and then someone else wanted to use
| build.please and someone tried to rewrite a lot of CI
| pipelines using python because shell scripting is too
| arcane, while someone decided that CI were super slow and
| must be hosted on premises using their favorite
| system(was it now drone or whatever I forgot).
| Eventually, things become so many and chaotic, your brain
| learns to copy-paste what works and hope for the best as
| the tool you have spent time learning will be replaced in
| few months.
| skydhash wrote:
| A lot of these technologies share a common base that can
| be pretty small. Once you learn about Make and concepts
| like target, recipe, dependencies,... It'd be easier to
| learn Ansible or Github actions even though they don't
| solve the same problem. It's the same when learning
| programming language and whatever tools of the week. But
| that requires to spend a bit of effort to goes under the
| hood and understand the common abstractions instead of
| memorizing patterns and words.
| ajross wrote:
| > Or the whole chain of work culture is bad and people do
| not have adequate down time or brain juice to pursue
| these.
|
| And... again, I have to say that that kind of statement
| is absolutely of a piece with the analysis upthread.
| Someone who demands a "work culture" that provides "down
| time" or "brain juice" to learn to write a makefile...
| just isn't going to learn to write a makefile.
|
| I mean, I didn't learn make during "downtime". I learned
| it by hacking on stuff for fun. And honed the skills
| later on after having written some really terrible build
| integration for my first/second/whatever job: a task I
| ended up doing _because I had already learned make_.
|
| It all feeds back. Skills are the components you use to
| make a career, it doesn't work if you expect to get the
| skills like compensation.
| Loic wrote:
| I like Makefiles, but just for me. Each time I create a new
| personal project, I add a Makefile at the root, even if the
| only target is the most basic of the corresponding language.
| This is because I can't remember all the variations of all the
| languages and frameworks build "sequences". But "$ make" is
| easy.
| choeger wrote:
| You're probably using the wrong tool and should consider a
| simple plain shell script (or a handful of them) for your
| tasks. test.sh, build.sh, etc.
| poincaredisk wrote:
| I disagree. Make is - at it's simplest form - exactly a
| "simple plain shell script" for your tasks, with some very
| nice bonus features like dependency resolution.
|
| Not the parent, bit I usually start with a two line
| makefile and add new commands/variables/rules when
| necessary.
| nrclark wrote:
| (not the parent)
|
| Make is - at its core - a tool for expressing and running
| short shell-scripts ("recipes", in Make parlance) with
| optional dependency relationships between each other.
|
| Why would I want to spread out my build logic across a
| bunch of shell scripts that I have to stitch together, when
| Make is a nicely integrated solution to this exact problem?
| dwaltrip wrote:
| Any modern attempts to do this better than make? I often
| write small "infra" bash scripts in my projects, maybe I
| could use a tool like that.
| TheTaytay wrote:
| I haven't used them yet, but I keep seeing people touting
| alternatives, and in particular "just":
| https://github.com/casey/just
|
| This is primarily aimed at a "task runner" replacement
| rather than a "compilation with automatic file timestamp
| comparison replacement"
|
| Others I stumbled across: Taskfile Mage XcFile
|
| None of them have tempted me enough to move away from a
| set of bash scripts or scripts written in the language of
| my repo (yet).
| 1aqp wrote:
| I'd say: you are absolutely using the right tool. :-)
| f1shy wrote:
| I would just change the percentages, but is about as true as it
| gets.
| mianos wrote:
| I'd be curious to hear your ratio. It really varies. In some
| small teams with talented people, there are hardly any "fake"
| developers. But in larger companies, they can make up a huge
| chunk.
|
| Where I am now, it's easily over 50%, and most of the real
| developers have already left.
|
| PS: The fakes aren't always juniors. Sometimes you have
| junior folks who are actually really good--they just haven't
| had time yet to discover what they don't know. It's often
| absolutely clear that certain juniors will be very good just
| from a small contribution.
| f1shy wrote:
| My personal experience: - 5% geniuses. This are people who
| are passionate about what they do, they are always up to
| date. Typically humble, not loud people. - 15% good, can do
| it properly. Not passionate, but at least have a strong
| sense of responsibility. Want to do "the right thing" or do
| it right. Sometimes average intelligence, but really
| committed. - 80% I would not hire. People who talk a lot,
| and know very little. Probably do the work just because
| they need the money.
|
| That applies for doctors, contractors, developers, taxi
| drivers, just about anything and everything. Those felt
| percentages had been consistent across 5 countries, 3
| continents and 1/2 a century of life
|
| PS: results are corrected for seniority. Even in the
| apprentice level I could tell who was in each category.
| mianos wrote:
| From my 40 years in the field, I see much the same trend.
| I wouldn't call 5% of developers "genius"--maybe 1% are
| true geniuses. Those folks can be an order of magnitude
| better at certain tasks--doing things no one else can--
| but only within a limited sphere. They also bring their
| own baggage, like unique personalities. Still, I believe
| there's always room for genius on a big team, even with
| all the complications.
|
| Typically, upper management wants smooth, steady output.
| But the better your people are, the bumpier that output
| gets--and those "one-percenters" can produce some pretty
| extreme spikes. If you think of it like a graph, the area
| under the curve (the total productivity) can be way
| bigger for a spiky output than for a flat, low-level one.
| So even if those spikes look messy, they often deliver a
| ton of long-term value.
| adrian_b wrote:
| Actually it is trivial to write a very simple Makefile for a
| 10,000 file project, despite the fact that almost all Makefiles
| that I have ever seen in open-source projects are ridiculously
| complicated, far more complicated than a good Makefile would
| be.
|
| In my opinion, it is a mistake almost always when you see in a
| Makefile an individual rule for making a single file.
|
| Normally, there should be only generic building rules that
| should be used for building any file of a given type.
|
| A Makefile should almost never contain lists of source files or
| of their dependencies. It should contain only a list with the
| directories where the source files are located.
|
| Make should search the source directories, find the source
| files, classify them by type, create their dependency lists and
| invoke appropriate building rules. At least with GNU make, this
| is very simple and described in its user manual.
|
| If you write a Makefile like this, it does not matter whether a
| project has 1 file or 10,000 files, the effort in creating or
| modifying the Makefile is equally negligible. Moreover, there
| is no need to update the Makefile whenever source files are
| created, renamed, moved or deleted.
| mianos wrote:
| If everything in your tree is similar, yes. I agree that's
| going to be a very small Makefile.
|
| While this is true, for much larger projects, that have lived
| for a long time, you will have many parts, all with slight
| differences. For example, over time the language flavour of
| the day comes and goes. Structure changes in new code. Often
| different subtrees are there for different platforms or
| environments.
|
| The Linux kernel is a good, maybe extreme, but clear example.
| There are hundreds of Makefiles.
| adrian_b wrote:
| Different platforms and environments are handled easily by
| Make "variables" (actually constants), which have platform-
| specific definitions, and which are sequestered into a
| platform-specific Makefile that contains only definitions.
|
| Then the Makefiles that build a target file, e.g.
| executable or library, include the appropriate platform-
| specific Makefile, to get all the platform-specific
| definitions.
|
| Most of my work is directed towards embedded computers with
| various architectures and operating systems, so multi-
| platform projects are the norm, not the exception.
|
| A Makefile contains 3 kinds of lines: definitions, rules
| and targets (typical targets may be "all", "release",
| "debug", "clean" and so on).
|
| I prefer to keep these in separate files. If you
| parametrize your rules and targets with enough Make
| variables to allow their customization for any environment
| and project, you must almost never touch the Makefiles with
| rules and targets. For each platform/environment, you write
| a file with appropriate definitions, like the names of the
| tools and their command-line options.
|
| The simplest way to build a complex project is to build it
| in a directory with a subdirectory for each file that must
| be created. In the parent directory you put a Makefile that
| is the same for all projects, which just invokes all the
| Makefiles from the subdirectories that it finds below,
| passing any CLI options.
|
| In the subdirectory for each generated file, you just put a
| minimal Makefile, with only a few lines, which includes the
| Makefiles with generic rules and targets and the Makefile
| with platform-specific definitions, adding the only
| information that is special for the generated file, i.e.
| what kind of file it is, e.g. executable, static library,
| dynamic library etc., a list of directories where to search
| for source files, the strings that should be passed to
| compilers for their include directory list and their
| preprocessor definition list, and optionally and
| infrequently you may override some Make definitions, e.g.
| for providing some special tool options, e.g. when you
| generate from a single source multiple object files.
| bluocms wrote:
| This only happens because people treat build code at a lower
| standard than app code. IMO you should treat all code with the
| same rigour. From build scripts to app code to test code.
|
| Why write hacks in build tools when you wouldn't do in your app
| code.
|
| We build tool code with the same quality as the app code. That's
| why most tooling we use are written in typescript: type safety,
| code reuse...
| ido wrote:
| I would argue the main reason is that Make is just bad. There
| are easier to use alternatives such as scons or rake that don't
| have this effect applied to them.
| nayuki wrote:
| I see this effect in Java Maven pom.xml files. It's hard to get a
| straightforward answer on why each build step is needed, what
| each attribute means, what parts are optional or mandatory, etc.
| There seems to be a culture of copying these XML files and
| tweaking a few things without truly understanding what the whole
| file means. I briefly looked at Ant and Gradle, and their
| ecosystems don't look any better. The build configuration files
| seem to have too much unexplainable magic in them.
| fiddlerwoaroof wrote:
| Imo, the only solution is to avoid boilerplate generators and
| the parent poms projects like spring boot use for things like
| pom files: you can look at the boilerplate to get ideas for
| what might be necessary, but, if you're starting a project,
| write the pom yourself. It's a pain the first couple times, but
| it gets easier to know what you need.
| rockwotj wrote:
| Honestly for Java I really like Bazel. You should give it a
| shot. I have a project with a self contained jvm and jars from
| maven central. Its more explicit than the other options but way
| less magical IMO.
| mongol wrote:
| Java would really benefit from a fresh take on the build story.
| Maven is definitely a tool that suffers from this phenomenon.
| imoverclocked wrote:
| > I briefly looked at ...Gradle... The build configuration
| files seem to have too much unexplainable magic in them.
|
| This is largely due to the use of groovy. When the Kotlin DSL
| is used instead, it can usually be introspected by (eg)
| IntelliJ. Otherwise, it's pretty opaque.
| brabel wrote:
| Bullshit. Groovy can be introspected just as well as Kotlin.
| And the magic in kts files is still there:
| configure<SourceSetContainer> { named("main") {
| java.srcDir("src/core/java") } }
|
| Unless you know this, there's zero way you will come up with
| this by typing `configure` and using just auto-completion.
| Might as well use Groovy and a String for the name of the
| thing you're configuring. Good tooling would be able to auto-
| complete from there whether it's Groovy or Kotlin (or Java
| etc).
| imoverclocked wrote:
| That wasn't my experience a few years ago with a large
| groovy-dsl project. Since groovy will take a look in
| several different namespaces to automatically resolve
| things in a script, editors I tried had no hope of telling
| me what anything was.
|
| Also, groovy allows modification of private instance
| variables which leads to ... un-fun situations. I converted
| tens of thousands of lines of groovy to Kotlin. A lot of
| those lines were automated. Too many were not automatable
| for myriad reasons.
|
| As far as the magic in Kotlin, I can easily click through
| all keywords and jump to the implementation in IJ. Groovy
| (at the time and in the project I was in) was utterly
| hopeless in this regard.
| brabel wrote:
| Groovy closure delegates' type can be declared, giving as
| much information as with Kotlin. The reason you couldn't
| follow the code was that the people who wrote those
| things either didn't declare types, or IntelliJ wasn't
| using the type declarations (I believe Groovy support in
| Gradle files is less good than in general Groovy files,
| where the IDE does support this). You're correct that
| some plugins will resolve things dynamically and those
| cannot be resolved by the IDE. But that's not the fault
| of the language, if you're going to rewrite in Kotlin
| with types, you could just as well add types to your
| Groovy declarations for the same result.
| smitty1e wrote:
| What is the counter-example?
|
| We recycle known good stuff to avoid getting bogged down and
| introducing fresh flaws.
|
| The admonition to know what we're doing and act deliberately
| applies to so much in life, but flies in the face of Milton
| Friedman's point in "I, Pencil" =>
| https://youtu.be/67tHtpac5ws?si=yhheE1Y5ELfjWXs-
| mongol wrote:
| Is not this a very generic phenomenon? I would argue it applies
| broadly. For example budgeting, you usually start from last
| year's budget and tweak that, rather than start from scratch. Or
| when you write an application letter, or a ServiceNow ticket, or
| whatever. Now I regret that I have brought in ServiceNow in the
| discussion, it kills the good mood....
| Over2Chars wrote:
| There's also "zero based budgeting" (ZBB) that starts from zero
| and says "justify everything".
| KineticLensman wrote:
| Which in my experience sometimes involves copying last years
| justifications
| Over2Chars wrote:
| It might!
|
| But as I understand it and I am not an accountant (IANAA?),
| for non-ZBB budgets last years budget is usually used as a
| _starting point_ and increases are justified.
|
| "Here's why I need more money to do the same things as last
| year, plus more money if you want me to do anything extra".
|
| I'd be curious what our man Le Cost Cutter Elon Musk does
| for budgeting?
| parasti wrote:
| I have made conscious effort in the past to never copy/paste the
| initial fleshing-out of a Makefile or a PHP class, or HTML
| boilerplate, or whatever. Like, for years I stuck to that. Then I
| stopped making that effort because there is no upside. Or rather,
| there is no downside to copy+paste+modify. It's faster and you
| save your brain power for things that actually matter.
| tpoacher wrote:
| There's a subtle difference between a nice template and a
| fully-working implementation that you then modify though.
|
| (e.g. in that they were designed with different goals in mind,
| so the former is likely to have stopped at the point where it
| was general enough, to save you time, but not too specific to
| create footguns).
|
| Bonus points if your template explicitly has fail patterns that
| prevent your code from silently failing.
| bitwize wrote:
| A better name for this might be the JCL effect, as even
| experienced mainframe sysprogs copypasta the JCL it takes to
| build their COBOL programs from a known-good example and then
| mutatis the mutandis, rather than attempt to build a mental model
| of how JCL works from the impenetrable documentation and write
| JCL _de novo_.
|
| It's no big deal to me to write a small Makefile from scratch. My
| editor (Emacs) even knows to always use tabs when I hit TAB in a
| Makefile, removing the confusion of whether I inserted tabs
| (correct) or spaces (horribly incorrect) on the lines with the
| commands to build a particular target.
| dgan wrote:
| Okey but to me, copying - pasting working code (even with sone
| extra unused bits) really looks no more different than inheriting
| a library - provided base class, and then extending it to one's
| needs.
|
| That's literally the basis of all software. There is no need to
| invent "a Makefile effect/syndrome"
|
| Yes that's an indication that a code sharing mechanism is needed
| but not implemented. Copying pasting solves that. You don't
| expect people to rewrite http client for every project which
| interacts with APIs, so you?
| worldsayshi wrote:
| I think this is a good point. As somewhat of a tangent I have
| vaguely been thinking of the difference between copy pasting
| and explicitly extending for a bit.
|
| It seems that in many cases, adapting copy pasted code has some
| benefits over importing and adjusting some library code.
| https://ui.shadcn.com/ is an example of going the copy paste
| direction. It seems to me this is preferable when tweaking the
| exact behaviour is more important than keeping up to date with
| upstream or adhering to an exact standard. If you customize the
| behaviour a lot the extra abstraction layer only gets in the
| way.
|
| This insight might be a bit mundane. But I remember myself
| bending over backwards a bit too much trying to reuse when copy
| pasting is fine.
| heisenbit wrote:
| Well, I expect people to understand http clients and if things
| don't work to be sufficiently knowledgeable to recognize when
| they have a performance problem and figure out why they have
| it. For that one needs language, library and networking skills
| which to a degree most developers have because they do it every
| day.
|
| At issue however are niche skills. We are dealing with the long
| tail of a distribution and heuristics which work most of the
| time might not - the author mentions e.g. security. The way I
| look at this is risk i.e. security, bus factor, disruptions due
| to software moving from state "works and is not understood" to
| "broken and is not understood" and last but not least ability
| to predict behavior of this niche technology when it is going
| to be pushed into an larger project.
| yuppiepuppie wrote:
| This is "Copy-Pasta Driven Development" [0] and it's not even
| related to makefiles. It's related to the entire industry copying
| code from here to there without even knowing what they are
| copying.
|
| TBH I think copilot has made this even worse, as we are blindly
| accepting chucks of code into our code bases.
|
| [0] https://andrew.grahamyooll.com/blog/copy-pasta-driven-
| develo...
| markfsharp wrote:
| Could not agree more!
| pdimitar wrote:
| Blame the business people. I tried becoming an expert in `make`
| probably at least 7 times in a row, was never given time to
| work with it daily until I fully memorized it.
|
| At one point I simply gave up; you can never build the muscle
| memory and it becomes a cryptic arcane knowledge you have to
| relearn from scratch every time you need it. So I moved to
| simpler tools.
|
| The loss of deep work is not the good programmers' fault. It's
| the fault of the business people.
| skydhash wrote:
| I wouldn't say so. Make is very simple and you can grasp the
| basis within an hour or so, if you're familiar with shell
| scripting (as it's basically a superset of shell scripts,
| with the dependency graph on top). Then all you have to do is
| just in time learning which is mostly searching for a simpler
| pattern that what you're currently doing.
| pdimitar wrote:
| Hm, I'm not sure that's the case. Some of make's weirdness
| comes from bash-isms, not shell scripting in particular.
| g7r wrote:
| We use Cargo Cult to refer to this phenomenon:
| https://en.wikipedia.org/wiki/Cargo_cult_programming
| torstenvl wrote:
| Copy+tweak happens IRL all the time. There's no reason everyone
| who bakes should have to reinvent biscuits from scratch. There's
| no reason chip manufacturers should have to reinvent N-type
| P-type sandwiches from scratch. The existence of adaptations of
| previous success does not suggest that baking, or physics, or
| Make, is overly complicated.
| Taniwha wrote:
| I think this is completely normal for tools that you program
| seldomly. I write makefiles a couple of times a year, I've been
| using make for more than 40 years now, I use it every day, but I
| seldomly program it, and when I want something more than simple
| dependancies I often clone something that already works.
| agnishom wrote:
| What is a counterexample?
|
| I cannot think of a single tool which is complex enough but does
| not show the makefile effect
| teddyh wrote:
| "Just modify someone else's Borgmon code and you're good to go."
|
| -- Broccoli Man <https://www.youtube.com/watch?v=3t6L-FlfeaI>
| dvh wrote:
| Most of my simple C projects have make.sh instead that has
| something like: clear gcc some options
| -o foo && ./foo
| chikere232 wrote:
| You might benefit from make, as you wouldn't need a full
| rebuild every time, or have to spell out every step.
| bigpingo wrote:
| For C and C++* projects under ~100k lines I wouldnt bother
| with incremental builds - I have a 70k C project with a
| single translation unit that builds in under 1s on my
| machine.
|
| * C++ requires some discipline to not explode build times,
| but it can be done if you dont go nuts with templates and
| standard headers.
| tpoacher wrote:
| > However, at the point of design, this suggests a tool design
| (or tool application) that is flawed: the tool (or system) is too
| complicated (or annoying) to use from scratch.
|
| As someone who teaches and sees college-level students ask
| chatgpt what's 1 + 1, I disagree that it has anything to do with
| complexity or annoyance.
|
| Humans be humans; that's mostly it.
| vandahm wrote:
| Honestly, my .zshrc file started out as a .kshrc file that was
| passed down to me by an older developer about 20 years ago, when
| I was still in university. I've added and removed a lot of things
| over the years, but there are still a few parts of it that I
| don't totally understand, simply because they work and I've never
| had a reason to think about them. The guy I got it from, in turn,
| got his from someone else.
|
| In the old days, I had a .fvwm2rc config file that I got from my
| boss in the university computing center. I had no idea how it
| worked! And neither did he -- he got it from a professor when
| _he_ was in university.
| choeger wrote:
| Makefiles have an even more interesting issue: They lost their
| main purpose. In many, many projects that I've seen, they only
| consist of phony targets. No dependency tracking is used
| whatsoever.
|
| How many Makefiles are there that just Wrap npm, pip, or some
| other tool like that? A Makefile is supposed to _be_ the build
| system, not trigger it.
| klysm wrote:
| Okay but make is a shitty build system. What it does have going
| for it is you can nearly universally expect it to be already
| installed or easy to install. That makes it a good way to name
| commands shorter in a portable way, with some dependencies
| maybe thrown in.
|
| It's used for the same reason we write shell scripts
| mdaniel wrote:
| > It's used for the same reason we write shell scripts
|
| Only _worse_ since it also uses $ for its variables leading
| to "thing:\n\t env FRED=$$HOME/thing some-command -p
| $$AWS_PROFILE $(OTHER_THING) -d $$(date +%s)" level of
| squinting
|
| So for those using it as a task runner from the 60s, without
| dependency tracking, now it's just laziness over a shell
| script that has "dependencies" in an imperative and
| shellcheck-able way
| shusaku wrote:
| I always write my makefiles from scratch. At some point in the
| process, I will google "make automatic variables", because
| they're a pain to memorize.
| kragen wrote:
| Yeah, I've always been mystified by the idea that writing a new
| _Makefile_ is some kind of wizardly mystery. Make has its
| design flaws, for sure, but how hard is it really to write
| this? CFLAGS = -std=gnu99 -Wall
| all: foo clean: $(RM) foo *.o
| foo: foo_main.o foolib.o $(CC) $(CFLAGS) $(LDFLAGS)
| $^ -o $@
|
| (Except with tabs, which HN doesn't allow.)
|
| I haven't tested what I just typed above, but I'm reasonably
| sure that if I biffed it in a way that makes it nonfunctional,
| it will be obvious how to correct the problem.
|
| I mean, not that you can't do better than that (I'm pretty sure
| anyone experienced can see some problems!), or that there
| aren't tricky and annoying tradeoffs, but it just doesn't seem
| like a big activation barrier the way people sometimes make it
| out to be?
|
| Maybe those people just need to spend an afternoon once in
| their life working through a basic _make_ tutorial? Maybe not
| the _first_ time they work on a project using _make_ , but,
| maybe, after the fifth or sixth project when they realize that
| this somewhat primitive inference engine is going to be
| something they interact with daily for years? At some point
| you're getting into "lead a horse to water" or "teach a man to
| fish" territory. There's a limit to how much you can empower
| someone who's sabotaging themself.
|
| There's a slightly less minimal example in
| https://www.gnu.org/software/make/manual/html_node/Simple-Ma...
| with a full explanation. You can read it in a few minutes, but
| of course you have to experiment to actually learn it. The
| whole GNU Make 4.4.1 manual in PDF form is only 229 pages, so
| you can read it after dinner one night, or on your commute on
| the train over the course of a few days. And then you'll know
| the complete rules of the game.
| pantalaimon wrote:
| Auto-generated Makefiles that CMake and Autotools produce
| really leave a bad impression on how complex Makefiles need
| to be.
| kragen wrote:
| Yeah, I guess trying to read the output of gcc -O -S would
| make assembly language seem pretty overwhelming, too.
| o11c wrote:
| Specifically, any generated makefile that refuses to take
| advantage of GNU make is necessarily going to be horrible.
|
| BSD make is ... viable I guess, but only really worth it if
| you're already in the ecosystem - and even then I can't
| guarantee you won't hit one of its silly limitations.
| mdaniel wrote:
| Good news, you can change the output then! And for as much
| as you might not like its generated Makefiles, I assert
| that $(cmake -G Ninja) is 100,000,000x more "wtf" than -G
| Makefiles
|
| I disagree about the autotools ones, I find them very sane
| although autotools itself can die in a rotting dumpster out
| back. And take m4 with it.
| kragen wrote:
| Yeah, m4 is powerful in its way, and has an extraordinary
| strength-to-weight ratio (check out the implementation in
| _Software Tools in Pascal_ ) but ultimately I think it
| turned out to be a mistake. Make, by contrast, turned out
| to be a good idea despite its flaws.
| spc476 wrote:
| You can drop the last line---make already knows the
| incantations to compile a C file.
| kragen wrote:
| I did drop the lines you're thinking of. The last line is
| to specify which .o files go into the executable.
| pantalaimon wrote:
| it always feels like those are from an era where teletypes
| would print out the computer output on paper and brevity was
| key to save ink and paper.
| elcapitan wrote:
| I guess this is an effect of declarative programming and layered
| abstractions. The declarative syntax and abstraction are an
| answer to code being repetitive and long and hard to follow, but
| this then creates its own issues by making it harder to reason
| (especially for beginners or occasional users) about what is
| actually going on. The price for learning how to get it right
| just becomes much higher with every layer of abstraction
| inbetween, because you always have to learn what's going on
| underneath the "cushions" anyway.
|
| For me typical examples are Terraform configurations with their
| abstracted configuration syntax, which just mimicks some other
| configuration (e.g. AWS) and executes it in an environment where
| I don't necessarily have access to. Of course I'm not going to
| run endless experiments by reading documentation, assembling my
| own config and running it in painful slow CI pipelines until it
| works. I'll rather copy it from another project where it works
| and then go back to work on things that are actually relevant and
| specific for the business.
| janalsncm wrote:
| > Does it need syntax of its own? As a corollary: can it reuse
| familiar syntax or idioms from other tools/CLIs?
|
| I'm with the author here 100%. Stop inventing new syntaxes and
| formats for things that don't need it. It's not clever, it's a
| PITA when it doesn't work as expected at 3:30 on a Friday.
| Havoc wrote:
| To me it seems fine that a tool that is both complexity and
| versatile needs a config file that is beyond memorization. So I
| think this line of reasoning has limitations.
|
| I could see it with say CLI tools though. Like if I need to
| reference my notes for a CLI command then that may well indicate
| a failure in tool design.
|
| >repeatedly copy a known-good solution and accrete changes over
| time.
|
| Alternative phrasing would be that it evolves. Arguably there is
| a positive trajectory there
| m463 wrote:
| There's another similar concept that sort of goes along with
| this.
|
| Sometimes it's better to duplicate code rather than make a
| special routine to do it.
|
| Sometimes it's not only easier to copy/paste, but it is better
| than adding a level of abstraction
| camgunz wrote:
| This is pretty thought provoking. I think the issue is "80% of
| the use of this complicated tool is for very simple ends". From
| there you get a lot of "I can't be bothered to learn
| git/make/sed/helm/jenkins, all I'm doing is X 15 minutes a year".
| My guess is SWEs hate ceilings, so we don't want to use tools
| that have them, even though they'd be far more fit for purpose.
| We also don't want to build tools with ceilings: why limit your
| potential userbase/market?
| PaulKeeble wrote:
| I end up doing the copy paste thing quite a lot with build tools,
| it was very common in Ant, Maven and then in Scala build tool.
| When your projects all have the same fundamental top level layout
| and you are doing the same actions over and over you solve the
| problem once then you copy and paste it and remove the bits that
| don't apply.
|
| These types of tools there isn't much you do differently they
| don't give you much in the way of abstractions its just a list of
| actions which are very similar between projects. Since you
| typically with them are working in declarations rather than the
| usual programming primitives it often fundamentally falls down to
| "does my project need this build feature or not?".
| davidguetta wrote:
| Is it not a problem which is basically COMPLETELY SOLVED by LLMs
| ?
|
| The reason this happens is because Makefiles (or CI/CD pipelines
| / linters config, bash scripts) are more or less "complete
| language" on their own, that are not worth learning when you can
| do ... exactly what the author says (copy/pasting/modifying until
| it works) 99% of the time.
|
| But LLMs in general know the language so if you ask "write a
| minimal Makefile that does this" or even "please simplify the
| Makefile that i copy/pasted/modified", my experience is that they
| do that very well actually.
| uludag wrote:
| Completely solved? I'd say exacerbated beyond recognition. We
| have tools to let us get by so much farther without
| understanding anything, so it probably becomes less of a
| problem in more cases. But it basically guarantees that all but
| the most curious will not understand how the system actually
| works. Everything becomes magical copy/pasting from the most
| advanced information retrieval system with LLMs.
| earnestinger wrote:
| > However, the occurrence of the Makefile effect in a simple
| application suggests that the tool is too complicated for that
| application.
|
| I interpret it in a bit of different way.
|
| Makefile is relatively simple and unopinionated like a brick.
| Also makefile defines/reflects project's structure.
|
| From simple blocks one can build any shape one want. Total
| freedom.
|
| Problem is, make doesn't impose best practice and doesn't steer
| you clear of common pitfalls of project structuring and building
| and publishing.
|
| One example for illustration: Out of source builds is rather good
| idea, but not imposed by make.
|
| So makefile is not enough, one needs all the life-lessons of
| using make, so inherited makefiles are better than written from
| scratch.
| o11c wrote:
| To expand the illustration:
|
| * using out-of-source builds is a good idea
|
| * using fully automatic dependencies is a good idea
|
| * never committing generated files is a good idea (avoid
| hysteresis)
|
| It is fundamentally _very difficult_ to get all three of these
| at once; automatic dependencies often require generating files
| ahead of time, but generating files often involves needing to
| know the dependencies or at _least_ their paths ahead of time.
|
| These days the trend seems to be to commit "generated-in-place"
| files, which avoids _some_ of the historical problems with the
| last (at the cost of introducing others). I don 't claim this
| is optimal.
| earnestinger wrote:
| One more shower thought. Those inherited makefiles are a
| solution in a search for a standard.
| jcarrano wrote:
| I wouldn't say this is necessarily a bad thing. I wrote my first
| version of a Makefile with automatic dependencies and out-of-tree
| builds 10+ years ago and I have been copying and improving it
| since. I do try to remove unneeded stuff when possible.
|
| The advantage is that one can go in and modify any aspect of
| build process easily, provided one takes care to remove cruft so
| that the Makefile does not become huge. This is very important
| for embedded projects. For me, the advantages have surpassed the
| drawbacks (which I admit are quite a few).
|
| You could, in theory, abstract much of this common functionality
| away in a library (whether for Make or any other software),
| however properly encapsulating the functionality is additional
| work, and Make does not have great built-in support for
| modularization.
|
| In this sense I would not say Make is overly complex but rather
| the opposite, too simple. Imagine how it would be if in C global
| variables were visible across translation units. So, in a way,
| the "Makefile effect" is in part due to the nature of the problem
| being solved and part due to limitations in Make.
| rini17 wrote:
| Can you imagine the makefile was made by someone else and you
| are now suddenly confronted with the result of 10 years of
| tuning.
| jcarrano wrote:
| I am that someone else because I seldom edit the makefiles
| and I forget things. That's why I try to trim unused targets
| and recipes and I try to keep it documented.
|
| In the end it is no different from any code that's suffered
| from 10 years of tuning and it can get ugly. Maybe Make is
| even somewhat worse in this respect, but then again it does
| not need to be changed often.
| keepamovin wrote:
| In other news I like the coherence of your online digital
| identity and websites.
|
| Reminds me of the early internet. Auras of class, cred,
| erudition, intelligence, mystery, imagination. Thank you.
| teeray wrote:
| I see this often on our codebase. It was mostly written by ex-C#
| developers who were new to writing Go, and there's many ham-
| handed C#-isms in there. At some point, someone took a guess at
| how something should be, then subsequent changes were done by
| copy-paste. Years down the road, another copy-paste job happens,
| and when I point out that the patterns within are not good (like,
| can actually be buggy), I get a confused response, because that
| is what was there.
|
| There is an implicit assumption that the code written espouses
| best-practices, but that is far from the truth.
| neonsunset wrote:
| I can imagine these developers being frustrated with highly
| verbose and often unsound semantics of Go.
| rednafi wrote:
| IDK I feel like Go suffers from this a lot. I have seen a lot
| of Gava, Guby, and G# over the last few years. It happens in
| Python a lot as well. Some people just love to write Java in
| Python and the new type hints make it even easier.
| nwallin wrote:
| Happens to us at my day job too. The codebase is primarily C++.
| My most recent horror story is that I was stepping through some
| code in an object that was statically initialized and a
| variable that was initialized as `static const double foo =
| nan;` had a value of 0 in it. This was very surprising to me.
|
| I look at how we defined nan and it turns out that nan is a
| singleton that was initialized in a DLL somewhere. My variable
| was being initialized before the singleton nan was initialized.
| I asked around, and someone with access to the previous version
| control system (we migrated to git in 2016) discovered that
| this was part of the original commit to that VCS back sometime
| in 2003-2006 or something. We think that was probably from
| before our C++ compiler was updated to support C++98 and
| `numeric_limits` was added.
|
| So of course I moved this over so that accessing our special
| nan singleton is just a static constexpr call to
| `std::numeric_limits<double>::quiet_NaN()`. But our special nan
| singleton is used all over the place in our codebase. So of
| course I have to check to see nobody's doing something weird
| with it.
|
| Of _course_ they are.
|
| There are about a hundred lines of code that boil down to `if
| (foo == special_nan_singleton) { /* ...handle nan _/ }` which
| of course...isn 't how nan works. This is a no-op and the
| compiler just straight up compiles it out of binary. This
| happens a _lot*. Including fundamental infrastructure, like the
| special JSON serializer somebody reinvented.
| Scubabear68 wrote:
| The best term for this is Cargo Cult Development. Cargo Cults
| arose in the Pacific during World War II, where native islanders
| would see miraculous planes bringing food, alcohol and goods to
| the islands and then vanishing into the blue. The islanders
| copied what they saw the soldiers doing, praying that their
| bamboo planes and coconut gadgets would impress the gods and
| restart the flow of cargo to the area.
|
| The issue of course is the islanders did not understand the
| science behind planes, Wallis talkies, guns, etc.
|
| Likewise, cargo cult devs see what is possible, but do not
| understand first principles, so they mimic what they see their
| high priests of technology doing, hoping they can copy their
| success.
|
| Hence the practice of copying, pasting, trying, fiddling,
| googling, tugging, pulling and tweaking hoping that this time it
| will be just right enough to kind of work. Badly, and only with
| certain data on a Tuesday evening.
| qwery wrote:
| The article does kind of mention this in footnote '1', for what
| it's worth:
|
| > The Makefile effect resembles other phenomena, like cargo
| culting, normalization of deviance, "write-only language," &c.
| I'll argue in this post that it's a little different from each
| of these, insofar as it's not inherently ineffective or bad and
| concerns the outcome of specific designs.
| lolinder wrote:
| I don't think of this as being cargo cult development. Cargo
| culting has more to do with mimicking practices that have
| worked before without understanding that they only worked
| within a broader context that is now missing. It's about going
| through motions or rituals that are actually ineffective on
| their own in the hopes that you'll get the results that other
| companies got who also happened to perform those same motions
| or rituals.
|
| What OP is describing isn't like this because the thing being
| copied--the code--actually is effectual in its own right. You
| can test it and decide whether it works or not.
|
| The distinction matters because the symptoms of what OP calls
| the Makefile effect are different than the symptoms of cargo
| culting, so treating them as the same thing will make diagnosis
| harder. With cargo culting you're wasting time doing things
| that actually don't work out of superstition. With the Makefile
| effect _things will work_ , provably so, but the code will
| become gradually harder and harder to maintain as vestigial
| bits get copied.
| themanmaran wrote:
| I would almost call this the "boilerplate effect".
|
| Where people copy the giant boilerplate projects for React,
| K8, Terraform, etc. and go from there. Those boilerplates are
| ideal for mid to large scale projects. And it's likely you'll
| need them someday. But in the early stages of development
| it's going to impart a lot of architecture decisions that
| really aren't necessary.
| peterldowns wrote:
| That's a great phrase. A perfect example of what you're
| talking about is actually built-in to the `helm` tool for
| creating re-usable kubernetes configs: `helm create myapp`
| creates the most convoluted junk I've ever seen in my life.
| As a new `helm` user I was extremely confused, as I had
| been expecting a minimal example that I could start from.
| Instead, I got a maximal example. Thankfully a more
| experienced engineer on the infra team confirmed that it
| was mostly unnecessary boilerplate and I could remove it.
|
| Something to consider for anyone else building tools --
| boilerplate has costs!
| NomDePlum wrote:
| Seeing this exact effect where I am currently working. Main
| available CI/CD tool is a customised and centrally managed
| Jenkins fleet. It's pretty much impossible to avoid using and
| seldom needs changed - until it does. Some attempts have been
| made at centralised libraries and patterns - but even that
| requires knowledge and study that most won't know is
| available or be given time to acquire.
|
| So when the inevitable tweak or change is made it's made in
| the easiest, cheapest way - which is usually copying an
| existing example, which itself was copied from somewhere
| else.
|
| I see exactly the same in other teams repositories. Easiest
| path taken to patch what already exists as the cost/benefit
| just isn't perceived to be there to worth prioritising.
| godelski wrote:
| > only worked within a broader context that is now missing
| > because the thing being copied--the code--actually is
| effectual in its own right.
|
| I don't understand how the second disproves the former.
|
| In fact, a cargo cult works because there's the appearance of
| a casual linkage. It appears things work. But as we know with
| code, just because it compiles and runs doesn't mean "it
| works". It's not a binary thing. Personal I find that belief
| is at the root of a lot of cargo cult development. Where many
| programmers glue things together say "it works" because they
| passed some test cases but in reality code shouldn't be a
| Lovecraftian monster made of spaghetti and duct tape. Just
| because your wooden plane glides doesn't mean it's AC an
| actual plane
| scubbo wrote:
| > a cargo cult works
|
| But...it doesn't? That's the whole definitional point of
| it. If action A _does_ lead to outcome B, then "if we do A,
| then B will happen" is not a cargo cult perspective, it's
| just fact.
| foobarchu wrote:
| For actual cargo cults, yes. Cargo Cult Development just
| used the name to invoke a comparison..when CCD is being
| practiced, devs are doing mystical steps because it's
| part of the incantation. They wouldn't keep doing them if
| the project then never worked.
|
| Your definition is extremely unlikely to ever be
| practiced, because those developers would be fired for
| never getting anything working, and so it's not really a
| helpful one imo.
| lolinder wrote:
| Concrete examples of what I think actually counts as
| cargo culting:
|
| * Incorporating TDD because it's a "best practice".
|
| * Using Kubernetes because Google does it.
|
| * Moving onto AWS because it's what all the cool
| companies are doing.
|
| The key thing that makes cargo cult development a cargo
| cult is that it's practices and rituals adopted without
| any concrete theory for _what_ a bit is supposed to do
| for you in your context. You 're just doing it because
| you've seen it done before.
|
| This is different than small scale copypasta where people
| know exactly what they're trying to accomplish but don't
| take the time in any given instance to slow down and re-
| analyze _why_ this bit of code looks the way that it
| does. They know that it works, and that 's enough in that
| moment.
|
| If we're going to go back to the original analogies that
| started it all, what you're describing as cargo cult
| would be more similar to islanders using machinery that
| was left behind without knowing how it works or how to
| maintain it. They don't strictly need to know that in
| order to gain actual concrete value from the machinery,
| but it would be better in the long term if they knew how
| to maintain it.
| godelski wrote:
| > For actual cargo cults, yes.
|
| I'd say it is true for both. There's evidence that the
| actions cause the events. They correlate. It's why people
| start doing the actions in the first place. The exact
| reasoning you use, if it didn't "work" (appear to work)
| then the cult dies off pretty fast (and they do).
| Rationally irrational. It's good to be aware of because
| with high complexity systems it is easy to fall into
| these types of issues. Where you are doing A and you
| _believe_ are causing B, but there is no real relation.
| godelski wrote:
| Sorry, the quotes around "work" were implicit. I thought
| there was enough context to make that clear. That just
| because some things actually work doesn't mean it works
| for the reason it actually works.
|
| This is what I meant by cargo cults working. Where there
| is a _belief_ in a causal connection where there is none.
| The Melanesia really did believe there was a causal
| connection between their actions would cause cargo to
| return. It's not just about appearance. It is about not
| understanding the actual causal chain and misinterpreting
| the causal variables.
|
| Measurement is HARD. It is very common that if you do A
| then B will happen YET A is not the cause of B. Here's a
| trivial example: a mouse presses a button and it gets
| fed. In reality, the mouse presses a button and a human
| feeds the mouse. It is not the button. It may even be
| impossible for the mouse to know this. But if the human
| leaves, the mouse can press the button all they want and
| they will not get fed. I hope you can see how this can
| happen in far more complex ways. As the chain of events
| gets longer and more complex you an probably see why it
| is actually a really common issue. Because you have
| literal evidence that your actions are causal while they
| are not.
| lolinder wrote:
| > Just because your wooden plane glides doesn't mean it's
| AC an actual plane
|
| But if your wooden plane can somehow make it to Europe,
| collect cargo, and bring it back to your island, what
| you're doing is _definitely not cargo culting_.
|
| It might not be actual engineering, maybe you don't
| understand aerodynamics or how the engine works, and maybe
| the plane falls apart when it hits the runway on the return
| flight, but if you got the cargo back you are doing
| something very different from cargo culting.
|
| That's why copypasta doesn't count as cargo culting. It
| accomplishes the same task once copied as it did before. It
| may do so less reliably and less legibly, but it does do
| what it used to do in its original context.
| godelski wrote:
| >> Just because your wooden plane glides doesn't mean
| it's AC an actual plane > But if your wooden
| plane can somehow make it to Europe, collect cargo, and
| bring it back to your island
|
| Sure, but these are categorically different and not
| related to my point. > That's why
| copypasta doesn't count as cargo culting.
|
| Let me quote wiki[0] The term cargo cult
| programmer may apply when anyone inexperienced with the
| problem at hand copies some program code from one place
| to another with little understanding of how it works or
| whether it is required. Cargo cult programming
| can also refer to the practice of applying a design
| pattern or coding style blindly without understanding the
| reasons behind that design principle. Some examples are
| adding unnecessary comments to self-explanatory code,
| overzealous adherence to the conventions of a programming
| paradigm, or adding deletion code for objects that
| garbage collection automatically collects.
|
| Even in the example it gives the code will "work." You
| can collect garbage when the language already does that,
| you'll get performance hits, but your code won't break.
|
| It "it doesn't _work_" disqualifies something from not
| being cargo cult programming, then there would be no
| cargo cult programming. Who is shipping code that doesn't
| compile or hits runtime errors with any form of
| execution? You couldn't do that for very long.
|
| Let's take an airplane example. Say you want to copy
| Boeing[1]. You notice that every 747 has a coffee maker
| on it. So you also make a coffee maker. After all, it is
| connected to the electrical system and the engines. Every
| time you take out the coffee maker the airplane fails. So
| you just put in a coffee maker.
|
| A cargo cult exists BECAUSE _something_ is "working".
| BECAUSE they have evidence. But it is about
| misunderstanding the causality. See also Feynman's "Cargo
| Cult Science"[2]. As dumb as people are, there's always a
| reason people do things. It is usually not a good reason
| and it is often a bad reason, but there is a reason. Even
| people will explain you "causal" explanations for things
| like astrology.
|
| [0] https://en.wikipedia.org/wiki/Cargo_cult_programming
|
| [1] Well in the past you might have wanted to lol
|
| [2]
| https://calteches.library.caltech.edu/51/2/CargoCult.pdf
| > not only what you think is right about it: other causes
| that could possibly explain your results
|
| His explanation explicitly acknowledges the experiment
| works. In fact, even the math to explain the experiment
| "works". But it is wrong. Related is Von Neuman's
| Elephant. Where Freeman Dyson had evidence that a theory
| explained an experiment, yet it was in fact wrong.
| Evidence isn't sufficient to determine causality.
| lolinder wrote:
| To quote the original source that Wiki cites and is
| derived from:
|
| > A style of (incompetent) programming dominated by
| ritual inclusion of code or program structures that serve
| no real purpose. A cargo cult programmer will usually
| explain the extra code as a way of working around some
| bug encountered in the past, but usually neither the bug
| nor the reason the code apparently avoided the bug was
| ever fully understood (compare {shotgun debugging},
| {voodoo programming}).
|
| This is categorically different than the kinds of
| copypasta that TFA is talking about, and it's different
| in that the copypasta in TFA _does serve a purpose_.
|
| There's a world of difference between copying something
| whose implementation you don't understand _but whose
| function you do understand_ versus copying something
| which you vaguely associate with a particular outcome.
|
| https://jargon-file.org/archive/jargon-2.9.6.dos.txt
| godelski wrote:
| > does serve a purpose.
|
| I think this is where we're butting heads, because I
| think this is an ambiguous term.
| cle wrote:
| For me, there are many cases where I copy-paste stuff I've
| written in the past b/c some tool is a pain-in-the-ass and I
| can't afford the mental context switch. I usually _do_
| understand what 's happening under the hood, but it's still
| cognitively heavy to switch into that "mode" so I avoid it when
| possible.
|
| Tools that fall into this category are usually ops-y things
| with enormous complexity but are not "core" to the problem I'm
| solving, like CI/CD, k8s, Docker, etc. For Make specifically, I
| usually just avoid it at this point b/c I find it hard to avoid
| the context switch.
|
| It has nothing to do with miraculous incantations--I know the
| tradeoff I'm making. But it still runs the risk of turning into
| the Makefile Effect.
| remus wrote:
| I agree, and I think the key distinction is in understanding.
| In a cargo cult there's a lack of understanding, whereas I'll
| often copy and paste code/config I understand to get
| something done. Usually this is for something I don't do very
| often (configuring nginx, writing some slightly complicated
| shell script etc.) I could spend an hour reading docs and
| writing the thing from scratch but that's likely gonna be
| wasted time because there's a good chance Im not going to
| look at that thing again for a few years.
| sgarland wrote:
| It's always hoped (but rarely shown to be true) that by
| making templates, teams will put thought into their K8s
| deployments etc. instead of just copy/pasting. Alas, no -
| even when the only things the devs have to do is add resource
| requests and limits, those are invariably copy/pasted. If the
| app gets OOMkilled, they bump up memory limit until it
| doesn't. If it's never OOMkilled, it's probably never
| touched, even if it's heavily over-provisioned (though that
| would only matter for the request, of course).
|
| This has spawned a cottage industry of right-sizing tooling,
| which does what a dev team could and should have done to
| begin with: profiling their code to see resource
| requirements.
|
| At this point, I feel like continuing to make things easier
| is detrimental. I certainly don't think devs need to know how
| to administer K8s, but I do firmly believe one should know
| how to profile one's code, and to make reasonable decisions
| based on that effort.
| raverbashing wrote:
| Pretty much this
|
| And of course every one of those tools has to have their own
| special language/syntax that makes sense nowhere else (think
| of all the tools beyond make, like autotools, etc)
|
| I don't care about make. I don't care learning about make
| beyond what's needed for my job
|
| Sure, it's a great tool, but I literally have 10 other things
| that deserve more of my attention than having my makefile
| work as needed
|
| So yeah I'll copy/paste and be done with it
| erosivesoul wrote:
| Honestly is this not how it should be done? There's always
| going to be a more elegant approach for sure. But in
| general, we don't want developers to keep rewriting the
| same code again and again. Avoiding that is part of entire
| design paradigms. I'd like to talk to the dev who doesn't
| copy-paste and writes everything from scratch.
| woodruffw wrote:
| (Author of the post.)
|
| This is mentioned in footnote 1. Concretely, I don't think this
| is exactly the same thing as cargo culting, because cargo
| culting implies a lack of understanding. It's possible to
| understand a system well and still largely subsist on copy-
| pasting, because that's what the system's innate complexity
| incentivizes. That was the underlying point of the post.
| gavindean90 wrote:
| No one tell them about Cobal
| svilen_dobrev wrote:
| Apart of not knowing / unable to start from scratch, this is
| about frequent, and infrequent use. The latter also means not-
| that-important-in-overall-landscape, and brings forgetting and
| perceiving it as less "ROI", so one (hopefuly) finds and copy-
| pastes that-last-working thing into.. whatever Frankenstein.
|
| https://utcc.utoronto.ca/~cks/space/blog/programming/Frequen...
| fargle wrote:
| calling this "Makefile" effect is a terrible disservice. one
| could as easily call it "PHP" effect, "YAML" effect, etc. pick
| whichever language you'd personally like to denigrate.
|
| there is nothing that makes makefiles inherently more or less
| susceptible to this. if it's more common, it's because people
| don't want to take the time doing more solid engineering and
| clean design for something like a ci/cd config or a makefile,
| being viewed as ancillary or less important. and so they often
| don't want to learn the language, so monkey-see-monkey-do.
|
| as sibling comments state, this is better called cargo cult or
| maybe copy-pasta. and i've seen it with any language c, c++,
| python, scripts, config files, anything. i even see it in chat
| gpt answers because it's regurgitating someone else copy pasta.
|
| if it's a problem, it's a problem of discipline.
| rednafi wrote:
| But it sure makes it more memorable. I would've called it
| GitHub Actions effect.
| cassepipe wrote:
| The reason why it seems to apply to makefiles in particular is
| because most people think life is too short to bother learning
| and understanding makefiles so it seems to happen there more
| than anywhere else.
|
| Also no matter how complicated and subtle you think your
| makefile is, true experts will tell you it's wrong and you
| instead copy their apparently over-engineered, hard to
| understand makefile
| earnestinger wrote:
| I think article addresses
|
| > if it's a problem, it's a problem of discipline.
|
| With this
|
| > Also note: the title is "be aware," not "beware." The
| Makefile effect is not inherently bad!
| getnormality wrote:
| Another factor is frequency of use. I use LaTeX to do big write-
| ups on the order of once per year or less. LaTeX at the level I
| use it is not a hard tool, but I generally start a new document
| by copy-pasting a previous document because there is a lot of
| detail about how to use it that I'm never going to remember given
| that I only use it for a few weeks once a year.
| Linux-Fan wrote:
| I usually try to avoid the "makefile effect" by learning the
| technolgoy I use reasonably frequently (like e.g. Makefiles,
| Shell Scripts, ...).
|
| However, despite the fact that I used to use LaTeX very much, I
| always copy-pasted from a template. It is even worse with
| beamer presentations and TikZ pictures where I would copy-paste
| from a previous presentation or picture rather than a template.
|
| For TikZ I am pretty sure that the tool is inherently complex
| and I just haven't spent enough time to learn it properly.
|
| For LaTeX I have certainly spent enough time on learning it so
| I wonder whether it might be something different.
|
| In my opinion it could very well be a matter of "(in)sane
| defaults". Good tools should come with good defaults. However,
| LaTeX is not a good tool wrt. this metric, because basically
| all my documents start something like
|
| ~~~ \documentclass[paper=a4, DIV9, 12pt, abstracton,
| headings=normal, captions=tableheading]{scrartcl}
| \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc}
| \usepackage[english,german,ngerman]{babel}
| \usepackage[english,german]{fancyref} % ...
| \usepackage{microtype} \usepackage{hyperref} ~~~
|
| Most of this is to get some basic non-ASCII support that is
| needed for my native tongue or enable some sane defaults (A4
| paper, microtype...) which in a modern tool like e.g.
| pandoc/markdown may not be needed...
|
| Hence the purpose of copy-pasing the stuff around is often to
| get good defaults which a better tool might give you right out
| of the box (then without copy/paste).
| kccqzy wrote:
| Copy-pasting itself is not bad per se. What's bad is copy-
| pasting without understanding the why and how.
|
| For LaTeX I also copy-paste a whole lot from older files, but
| I don't feel bad because (a) I wrote these files before, (b)
| I know exactly what each line is doing, (c) I understand why
| each line is needed in the new doc.
|
| I wrote a relatively large amount of TikZ code earlier in my
| life (basically used it as a substitute for Illustrator) and
| for this library in particular, I think it just has so much
| syntax to remember that I cannot keep it all in my brain for
| ever. So I gladly copy from my old TikZ code.
| fph wrote:
| \usepackage[utf8]{inputenc} now is the default, at least; you
| don't need to include it anymore. And diacritics work out of
| the box, no need to write weird incantations like G\"{o}del
| anymore.
| folmar wrote:
| I use it more often and also start with copy-paste header, that
| includes:
|
| * all packages needed for my language (fontenc, babel, local
| typography package) * typical
| graphicx/fancyhdr/hyperref/geometry packages that are almost
| always needed * a set of useful symbol and name definitions for
| my field
|
| If you are not writing math or pure text in English only LaTeX
| is batteries not included.
| rednafi wrote:
| This also happens with tools you have to use but don't get much
| payoff from--like internal tooling. At work, we have a shitty in-
| house feature flag service. It breaks all the time and is super
| finicky. Learning it properly doesn't really help me, so I mostly
| copy and paste my way through it.
|
| Another example is jq. I use it occasionally, and ChatGPT handles
| the syntax pretty well. For me, learning it properly just isn't
| worth the time or effort.
| linuxftw wrote:
| Makefile syntax is also well understood by ChatGPT. If you want
| to know a suitable way for doing some task, ChatGPT can do it.
| It can also explain what another Makefile is doing.
|
| Here's an example of a (similar) prompt I used recently: "Write
| me a makefile that executes a script inside a docker container.
| I want the script to be someprefix-<target-script> that calls
| /app/<target-script>.sh inside the container."
|
| I don't have to care about Makefile syntax anymore for the most
| part.
| rednafi wrote:
| Exactly. I used to go for Just and Go Task as Make
| alternatives, but not anymore. LLMs are great with Make
| syntax, and Make is everywhere.
| dave333 wrote:
| The traditional Unix man page or list of options output with
| --help is often a firehose of details that most devs will never
| use. Sometimes there are a few examples shown of common use cases
| which is a good place to start learning the tool.
| sgarland wrote:
| Sure, but IME even when the tool in question is incredibly
| well-documented (like Django, or some other popular library),
| and has plenty of examples, most _still_ don't read the docs.
|
| I don't know how to deal with that mentality. I don't mind
| showing someone how I came to an answer, but I also expect them
| to remember that for the next time, and do some searching of
| their own.
| dare944 wrote:
| > However, the occurrence of the Makefile effect in a simple
| application suggests that the tool is too complicated for that
| application.
|
| The author's overall point is fine (specifically, that one should
| consider developer cut-and-paste behavior as an indicator of
| unnecessary complexity in a tool). However, when discussing the
| designer's perspective, I think the author should have taken a
| broader view of complexity.
|
| Much of the complexity in Makefiles stems from their generality;
| essentially, the set of problems to which a Makefile can be a
| solution. Substantively reducing this complexity necessarily
| means eliminating some of those use cases. In the case of make,
| this is clearly possible. Make as a Unix tool has been around for
| a looong time, and one can look at the early versions for an idea
| of how simple it could be.
|
| But the rub is, simplifying make doesn't necessarily reduce
| complexity. Once armed with a simpler, but more limited make,
| developers are now tasked not only with knowing the easier
| Makefile syntax, but also knowing when make isn't an appropriate
| solution, and when and how to use whatever tool exists to fill
| the gap. Compounding this is the fact documentation and shared
| knowledge regarding which tool is appropriate for which problem
| is much harder to come by than documentation for the tool itself.
| This can easily lead to the tool choice equivalent of developer
| cut-and-paste behavior: "so-and-so uses build tool X so I must
| use it too", "if your doing (general description of problem) the
| only build tool you ever need is Y", "I used Z before, so I'm
| just going to make it work again".
|
| Essentially you can think of make as one "verb" in a sprawling
| and uncoordinated domain-specific language that targets building
| things. Developers need some level of proficiency across this
| language to succeed at their work. But trading complexity that
| must be mastered in one tool for complexity that must be mastered
| across tools can very easily increase overall complexity and
| promote its own kind of "Makefile Effect", just at a different
| level.
|
| EDIT: Some might prefer the term "Cargo Culting" rather than
| "Makefile Effect" here. I suggest they are the same behavior just
| in different contexts.
| matsemann wrote:
| Why do some tools have this problem, and others not?
|
| I think it's convention over configuration. Makefile can do
| anything, so every project is different and needs different
| configurations, and _everything_ must be configured. Which means
| that when I use a tool like that, it 's sooo many decisions to
| make, that I just copy something that I know works.
|
| If instead it was some sane defaults, it would be pretty apparent
| where it deviates. And instead of thinking of hundred things and
| which to choose, I either don't think about them, or think "do I
| have a reason to configure this instead of using defaults?"
| layer8 wrote:
| There are certainly a lot of tools that are more complicated than
| necessary, but _Make_ as a tool isn't a good example of that,
| IMO. With modern tooling, more often than not the complexity
| problem is compounded by insufficient documentation, the existing
| documentation being predominantly cookbook-style and not
| explaining the conceptual models needed to reason about how the
| tool works, nor providing a detailed and precise enough
| specification of the tool. That isn't the case for _Make_ , which
| is well-documented and not difficult to get a good grasp on, if
| one only takes the time to actually read the documentation.
|
| The cookbook orientation mentioned above in turn leads to a
| culture that underemphasizes the importance of learning and
| understanding the tools that one is using, and of having thorough
| documentation that facilitates that. Or maybe the direction of
| causation is the other way around. In any case, I see the problem
| more in too little time being spent in creating comprehensive and
| up-to-date documentation on tooling (and designing the tooling to
| be amenable to that in the first place), and in too little
| resources being allocated to teaching and learning the necessary
| tooling.
| knallfrosch wrote:
| Yeah I'm just not wasting my life (or professional time) learning
| Groovy, Maven, DotNET project files, DotNET 4.8, Gradle, Azure
| DevOps, Grafana, Prometheus, Docker, Docker compose, Kubernetes,
| Jenkins etc et all.
|
| I need those things once at project setup. I copy-paste and
| change a bit.
|
| Why copy-paste? It's a proven strategy with a high success rate
| despite little effort behind it.
|
| I also don't want to learn templating for every little DSL I need
| to write one file per project with.
|
| But if you love doing it "the right way", you're welcome to do
| that work for me.
| myhf wrote:
| "A complex system that works is invariably found to have evolved
| from a simple system that worked. A complex system designed from
| scratch never works and cannot be patched up to make it work. You
| have to start over with a working simple system."
|
| - John Gall (1975) Systemantics: How Systems Really Work and How
| They Fail
|
| https://en.wikipedia.org/wiki/John_Gall_(author)#Gall's_law
| jfengel wrote:
| It's why I'm always very skeptical of new languages and
| frameworks. They often look great on a PowerPoint slide, but
| it's not clear how they'll look on something complex and long-
| lasting.
|
| They usually pick up warts added for some special case, and
| that's a sign that there will be infinitely many more.
|
| There's a fine line between "applying experience" and
| "designing a whole new system around one pet peeve". But it's a
| crucial distinction.
| wellbehaved wrote:
| With that attitude how would the presently accepted
| languages/frameworks have come about?
| oblio wrote:
| Probably slower and with more respect for existing tech.
|
| But hey, now we have npm, so who cares anymore? :-)
| mrcsd wrote:
| Disrespect is part of progress, respectful humans are
| liable to blindness of flaws. Just as part of youthful
| creativity is disregard for what has come before.
| Learner100 wrote:
| A design philosophy called "Progressive Disclosure" tries to
| tackle this problem, where a tool is supposed to present a
| minimal set of functionality initially to allow a user to be
| productive without being an expert and progressively "reveal"
| more complex features as the user becomes more familiar with the
| tool and attempts to do more complex things.
|
| I've heard the programming language Swift followed this
| philosophy during development, though I've never written any
| Swift code to know how well it worked out.
|
| https://en.wikipedia.org/wiki/Progressive_disclosure
| bluedino wrote:
| This happens with Slurm/PBS job submission files. Always end up
| asking the user "where/who did you get this from?"
| earnestinger wrote:
| What is slurm?
| bluedino wrote:
| https://hpc-wiki.info/hpc/SLURM
| silasdavis wrote:
| Someone remind me, is it $@ or $< ?
| pwdisswordfishz wrote:
| For what?
| spc476 wrote:
| In a given rule: foo.o : foo.c
| $(CC) $(CFLAGS) -o $@ $<
|
| The "$@" is the output (or target, think of @ as a bullseye on
| a target), and the "$<" is the input (think redirection). The
| only other commonly used variable is "$^":
| foo : foo.o util.o other.o $(CC) $(LDFLAGS) -o
| $@ $^ $(LDLIBS)
|
| In this case, "$^" means "all inputs".
| pwdisswordfishz wrote:
| Ironically enough, I tend to write my Makefiles from scratch
| nearly every time, which means I have little reason to consider
| this term fitting.
| gsbcbdjfncnjd wrote:
| Counterpoint: make is good actually, you should learn it (like
| all such tools).
| solatic wrote:
| > Think about CI/CD setups, where users diagnose their copy-
| pasted CI/CD by doing print-style debugging over the network with
| a layer of intermediating VM orchestration. Ridiculous!
|
| I don't think the author understands the point of "CI/CD
| systems". And I don't really blame them, because workload
| orchestration systems have been abused and marketed to the point
| where we call them CI/CD systems instead. Sure, if you think the
| point of CI/CD is to just provide a unified build and deploy it
| somewhere, you can write that in whatever language you like, and
| not need to know a bunch of YAML-fu.
|
| But the _whole point_ of workload orchestration systems is to
| _configure_ the flow of workloads _between machines_ as they
| _inherently execute on different machines_. The status quo is to
| debug over the network because, fundamentally, different machines
| will be connected by a network and the workload orchestration
| system is figuring out which machine to put it on.
|
| If you think you can just run your CI/CD on a single server
| without networking or virtualization, I have some very large,
| parallelized testing suites to show you.
| semi-extrinsic wrote:
| > If you think you can just run your CI/CD on a single server
| without networking or virtualization, I have some very large,
| parallelized testing suites to show you.
|
| Nowadays you can get a single server with 256 cores and several
| terabytes of memory. I would be interested to learn what kind
| of testing suites have actual needs beyond that.
|
| Without virtualization though is definitely no problem. The
| whole docker/k8s/whatever shtick is mainly because devs think
| it's more fun to invent new things than to learn how to use old
| ones properly. At least as long as you're running your own code
| on your own hardware, there is not a single thing solved by
| virtualization that wouldn't be solved equally well (or better)
| with traditional tools like environment modules and Slurm.
| upbeat_general wrote:
| For a start, any suite that takes >X hours on a single node,
| especially compounded if you have a large team of developers.
|
| > At least as long as you're running your own code on your
| own hardware
|
| Assuming you keep a consistent env/OS across all nodes you
| will want to run said code. Which can be difficult, even just
| between two users on a single node.
|
| Not to mention the fact that a lot of (most?) code needs to
| (A) interoperate with other people's code and (B) at least
| sometimes run on other hardware.
| IgorPartola wrote:
| Make and Makefiles are incredibly simple when they are not
| autogenerated by autoconf. If they are generated by autoconf,
| don't modify them, they are a build artifact. But also, ditch
| autoconf if you can.
|
| In the broader sense: yes this effect is very real. You can fall
| to it or you can exploit it. How I exploit it: write a bit of
| code (or copy/paste it from somewhere). Use it in a project.
| Refine as needed. When starting the next project, copy that bit
| of code in. Modify for the second project. See if changes can be
| backported to the original project. Once both are running and are
| in sync, extract the bit of code and make it into a library.
| Sometimes this takes more projects to distill the thing into what
| a library should be. In the best case, open source the library so
| others can use it.
| Quekid5 wrote:
| They are simple but very often _wrong_. It 's surprisingly hard
| to write Makefiles that will actually do the right thing under
| anything other than "build from scratch" scenarios. (No, I'm
| not joking. The very existence of the _idea_ of "make clean"
| is the smoking gun.)
| IgorPartola wrote:
| That's why I usually write them from scratch and don't let
| them get over 100 lines long at most. Usually they are around
| 30 with white space.
|
| make clean makes lots of sense but is not even strictly
| necessary. In the world where all it does is find all the *.o
| files and deletes them it's not a bad thing at all.
| mauvehaus wrote:
| The idea that git offers a 'clean' command was revelatory to
| me. Your build system probably shouldn't need to know how to
| restore your environment to a clean state because your source
| control should _already know what a clean state is_.
|
| That's sort essential to serving its purpose, after all.
|
| I haven't yet run into a scenario where there was a clean
| task that couldn't be accomplished by using flags to git
| clean, usually -dfx[0]. If someone has an example of
| something complex enough to require a separate target in the
| build system, I'm all ears.
|
| [0] git is my Makefile effect program. I do not know it well,
| and have not invested the time to learn it. This says
| something about me, got, or both.
| withinboredom wrote:
| The problem with `git clean` is -X vs -x. -x (lowercase)
| removes EVERYTHING including .env files and other untracked
| files. -X (uppercase) removes only ignored files, but not
| untracked files.
|
| If there is a Makefile with a clean target, usually the
| first thing I do when I start is make it an alias for `git
| clean -X`.
|
| Usually, you want to keep your untracked files (they are
| usually experiments, debugging hooks, or whatever).
| mauvehaus wrote:
| You are almost certainly right that I was using -X. It's
| been a while since I had to deal with git.
| PaulHoule wrote:
| There are many angles.
|
| Part of the low-code/no-code story is that conventional
| programming requires programmers to not just decide what has to
| be done but in what order to put those things. (This is connected
| with parallelism because if tasks are done in a particular order
| you can't do more than one at a time.)
|
| An Excel spreadsheet is different from a FORTRAN program, for
| instance, because you can write a bunch of formulas and Excel
| updates the results automatically without you sequencing things.
|
| https://en.wikipedia.org/wiki/Topological_sorting
|
| is an easy approach to finding a valid order to do tasks in. It's
| used frequently in build systems but rarely in other software so
| it contributes to build systems seeming to be from another planet
|
| ---
|
| I work in Java a lot and I used to hate Maven, because, if you
| look at Maven as "an XML vocabulary" you're going to frequently
| find "you can't get from here" and looking for answers in Stack
| Overflow is going to dig you in deeper.
|
| The right way to think about Maven is that, like (part of)
| Spring, it is a system for writing XML files that configure a
| group of Java objects. Seen that way, writing a Maven plugin
| should be a second resort; the moment you're scratching your head
| wondering if it's possible to do something, you should (1) make
| sure you can't "go with the flow" and follow conventions, then
| (2) write a Maven plugin.
|
| The thing is, a Maven plugin is just an ordinary Maven class.
| You're a Java programmer, you know how to do things in Java. All
| the skills you use everyday apply, you're no longer in a weird,
| mysterious and limited environment. That's part of the "makefile
| program"; you probably build your code (edit files in Java, C,
| whatever) 1000s of times for every time you change something
| about your build system. On a team you can be very productive if
| you know the main language but have no idea about how the build
| works ( _if_ the build the works.)
|
| When you try this though you often run into political problems.
| In most places, for instance, only a few people on the team have
| the authority to create new maven projects (a plug-in _is_ a
| class defined it 's own project.) Maybe that makes sense because
| you don't want them breeding like rabbits, but a lot generally
| most systems are badly partitioned as it is, and I think many
| programmers wouldn't want to have the fight it would take to
| create a new project.
|
| People are accustomed to builds being SNAFU and FUBAR.
|
| When I first saw Maven I was baffled that, as a remote working on
| a system that had about 20 programmers and about 20 projects I
| couldn't build the system successfully at all. The build worked
| maybe 70% of the time at the office and people didn't seem to
| worry about it. I could live with that because they were building
| large complex systems that they were always throwing away and I
| was building simpler spike prototypes that worked.
|
| I worked at a number of places where builds were unreliable in
| ways that seemed quantitative rather than qualitative, eventually
| I realized the problem was really simple, if you were using
| snapshot builds and a lot of people were working on a project and
| you didn't have any transaction control you would often get a set
| of snapshots that were not compatible with each other.
|
| Most teams don't take builds seriously enough. I've found it rare
| to meet an engineering manager who can answer the question "how
| long does the build take?" and fantasize of going to a job
| interview, asking that question, and if I don't get an answer,
| standing up and walking out.
|
| For many projects I've worked on I've built "meta-build systems"
| where the assumption is that have 12 maven projects and 4 npm
| projects or something like that (aren't most of us using mixed
| languages in the React age? why isn't this treated as a first-
| class problem), and such a system can be smart about what gets
| built and what gets doesn't, what is running out of snapshots and
| what can have a fixed version, etc. Merges in changes from
| develop automatically, and if seven steps are required that take
| a total of 15 minutes I ought to be able to think about something
| else entirely for 15 minutes and hear a "beep" when it's done.
|
| Trouble is we don't take builds seriously enough: it's a
| technical problem and it's a political problem and we often don't
| face the technical problems because of the political problems.
| __turbobrew__ wrote:
| This happens to me all the time with bazel. It is too complicated
| and the documentation sucks so I just look for prior art and copy
| paste that. Sometimes I have to do something novel and it takes
| me several days of deep diving the bazel source code to figure
| out how to do something.
| DavidPiper wrote:
| > Complex tools are a necessity; they can't always be avoided.
| However, the occurrence of the Makefile effect in a simple
| application suggests that the tool is too complicated for that
| application.
|
| This footnote actually made me think about IDEs and the JS
| toolchain even more than makefiles.
|
| If I'm writing a small project (say, 10 code files) surely an IDE
| where most people only know how to use 4 of the 1000 buttons is
| overkill, and I'd use a makefile.
|
| Similarly surely 10 code files with 10 config dotfiles to set up
| a JS environment and tooling for dependencies, versioning,
| linting, transpiling, etc is overkill too.
|
| - Basic javac/gcc/swiftc/whatever commands are simple, even if
| they can scale up through every niche via configuration options.
|
| - Basic makefiles are simple, even if they can scale up to
| something like the xnu makefile tree (the most complex make
| system I've encountered).
|
| - Let's not talk about JS.
|
| I'm hesitant to use the word "lazy" to describe people who do
| what the author is describing - not just because I sometimes do
| it myself but because I believe that laziness is a derivative
| observation of time constraint, executive function exhaustion,
| and other factors. It also reminds me of the classic "I'm going
| to learn X, which handles/wraps Y, so that I can avoid learning
| Y", which is generally a bad pattern of motivation.
|
| At its core this feels like a failure to understand (or failure
| of others to teach) fundamentals / first principles of the tools
| being used.
___________________________________________________________________
(page generated 2025-01-11 23:00 UTC)